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/debmetaindex.h>
15 #include <apt-pkg/error.h>
16 #include <apt-pkg/init.h>
17 #include <apt-pkg/pkgrecords.h>
18 #include <apt-pkg/sourcelist.h>
19 #include <apt-pkg/sptr.h>
21 #include <sys/sysctl.h>
27 /* Extension Keywords {{{ */
28 #define _trace() fprintf(stderr, "_trace()@%s:%u[%s]\n", __FILE__, __LINE__, __FUNCTION__)
30 #define _assert(test) do \
32 fprintf(stderr, "_assert(%d:%s)@%s:%u[%s]\n", errno, #test, __FILE__, __LINE__, __FUNCTION__); \
39 - (void) setApplicationNameForUserAgent:(NSString *)applicationName;
42 static const int PulseInterval_ = 50000;
43 const char *Machine_ = NULL;
44 const char *SerialNumber_ = NULL;
46 @interface NSString (CydiaBypass)
47 - (NSString *) stringByAddingPercentEscapes;
50 @protocol ProgressDelegate
51 - (void) setError:(NSString *)error;
52 - (void) setTitle:(NSString *)title;
53 - (void) setPercent:(float)percent;
54 - (void) addOutput:(NSString *)output;
57 NSString *SizeString(double size) {
64 static const char *powers_[] = {"B", "kB", "MB", "GB"};
66 return [NSString stringWithFormat:@"%.1f%s", size, powers_[power]];
69 /* Status Delegation {{{ */
71 public pkgAcquireStatus
82 void setDelegate(id delegate) {
86 virtual bool MediaChange(std::string media, std::string drive) {
90 virtual void IMSHit(pkgAcquire::ItemDesc &item) {
93 virtual void Fetch(pkgAcquire::ItemDesc &item) {
94 [delegate_ setTitle:[NSString stringWithCString:("Downloading " + item.ShortDesc).c_str()]];
97 virtual void Done(pkgAcquire::ItemDesc &item) {
100 virtual void Fail(pkgAcquire::ItemDesc &item) {
101 [delegate_ performSelectorOnMainThread:@selector(setStatusFail) withObject:nil waitUntilDone:YES];
104 virtual bool Pulse(pkgAcquire *Owner) {
105 bool value = pkgAcquireStatus::Pulse(Owner);
108 double(CurrentBytes + CurrentItems) /
109 double(TotalBytes + TotalItems)
112 [delegate_ setPercent:percent];
116 virtual void Start() {
119 virtual void Stop() {
123 /* Progress Delegation {{{ */
131 virtual void Update() {
132 [delegate_ setTitle:[NSString stringWithCString:Op.c_str()]];
133 [delegate_ setPercent:(Percent / 100)];
142 void setDelegate(id delegate) {
143 delegate_ = delegate;
146 virtual void Done() {
147 [delegate_ setPercent:1];
152 /* External Constants {{{ */
153 extern NSString *kUIButtonBarButtonAction;
154 extern NSString *kUIButtonBarButtonInfo;
155 extern NSString *kUIButtonBarButtonInfoOffset;
156 extern NSString *kUIButtonBarButtonSelectedInfo;
157 extern NSString *kUIButtonBarButtonStyle;
158 extern NSString *kUIButtonBarButtonTag;
159 extern NSString *kUIButtonBarButtonTarget;
160 extern NSString *kUIButtonBarButtonTitle;
161 extern NSString *kUIButtonBarButtonTitleVerticalHeight;
162 extern NSString *kUIButtonBarButtonTitleWidth;
163 extern NSString *kUIButtonBarButtonType;
165 /* Mime Addresses {{{ */
166 @interface Address : NSObject {
174 - (NSString *) email;
176 + (Address *) addressWithString:(NSString *)string;
177 - (Address *) initWithString:(NSString *)string;
180 @implementation Address
189 - (NSString *) name {
193 - (NSString *) email {
197 + (Address *) addressWithString:(NSString *)string {
198 return [[[Address alloc] initWithString:string] autorelease];
201 - (Address *) initWithString:(NSString *)string {
202 if ((self = [super init]) != nil) {
205 pcre *code = pcre_compile("^\"?(.*)\"? <([^>]*)>$", 0, &error, &offset, NULL);
208 fprintf(stderr, "%d:%s\n", offset, error);
212 pcre_extra *study = NULL;
214 pcre_fullinfo(code, study, PCRE_INFO_CAPTURECOUNT, &capture);
215 int matches[(capture + 1) * 3];
217 size_t size = [string length];
218 const char *data = [string UTF8String];
220 if (pcre_exec(code, study, data, size, 0, 0, matches, sizeof(matches) / sizeof(matches[0])) >= 0) {
221 name_ = [[NSString stringWithCString:(data + matches[2]) length:(matches[3] - matches[2])] retain];
222 email_ = [[NSString stringWithCString:(data + matches[4]) length:(matches[5] - matches[4])] retain];
224 name_ = [[NSString stringWithCString:data length:size] retain];
233 /* Right Alignment {{{ */
234 @interface UIRightTextLabel : UITextLabel {
235 float _savedRightEdgeX;
236 BOOL _sizedtofit_flag;
239 - (void) setFrame:(CGRect)frame;
240 - (void) setText:(NSString *)text;
241 - (void) realignText;
244 @implementation UIRightTextLabel
246 - (void) setFrame:(CGRect)frame {
247 [super setFrame:frame];
248 if (_sizedtofit_flag == NO) {
249 _savedRightEdgeX = frame.origin.x;
254 - (void) setText:(NSString *)text {
255 [super setText:text];
259 - (void) realignText {
260 CGRect oldFrame = [self frame];
262 _sizedtofit_flag = YES;
263 [self sizeToFit]; // shrink down size so I can right align it
265 CGRect newFrame = [self frame];
267 oldFrame.origin.x = _savedRightEdgeX - newFrame.size.width;
268 oldFrame.size.width = newFrame.size.width;
269 [super setFrame:oldFrame];
270 _sizedtofit_flag = NO;
275 /* Linear Algebra {{{ */
276 inline float interpolate(float begin, float end, float fraction) {
277 return (end - begin) * fraction + begin;
282 @interface ResetView : UIView {
283 UINavigationBar *navbar_;
287 - (void) navigationBar:(UINavigationBar *)navbar poppedItem:(UINavigationItem *)item;
292 - (NSString *) leftTitle;
293 - (NSString *) rightTitle;
296 @implementation ResetView
298 - (void) navigationBar:(UINavigationBar *)navbar poppedItem:(UINavigationItem *)item {
299 if ([[navbar_ navigationItems] count] == 1)
310 if ([[navbar_ navigationItems] count] == 1)
312 else while ([[navbar_ navigationItems] count] != 1)
313 [navbar_ popNavigationItem];
317 - (void) _resetView {
318 [navbar_ showButtonsWithLeftTitle:[self leftTitle] rightTitle:[self rightTitle]];
321 - (NSString *) leftTitle {
325 - (NSString *) rightTitle {
334 @interface Database : NSObject {
336 pkgRecords *records_;
337 pkgProblemResolver *resolver_;
338 pkgAcquire *fetcher_;
340 SPtr<pkgPackageManager> manager_;
348 - (void) _readStatus:(NSNumber *)fd;
349 - (void) _readOutput:(NSNumber *)fd;
351 - (Package *) packageWithName:(NSString *)name;
354 - (pkgCacheFile &) cache;
355 - (pkgRecords *) records;
356 - (pkgProblemResolver *) resolver;
357 - (pkgAcquire &) fetcher;
365 - (void) setDelegate:(id)delegate;
368 /* Package Class {{{ */
369 @interface Package : NSObject {
370 pkgCache::PkgIterator iterator_;
372 pkgRecords::Parser *parser_;
373 pkgCache::VerIterator version_;
374 pkgCache::VerFileIterator file_;
377 - (Package *) initWithIterator:(pkgCache::PkgIterator)iterator database:(Database *)database version:(pkgCache::VerIterator)version file:(pkgCache::VerFileIterator)file;
378 + (Package *) packageWithIterator:(pkgCache::PkgIterator)iterator database:(Database *)database;
381 - (NSString *) section;
382 - (NSString *) latest;
383 - (NSString *) installed;
384 - (Address *) maintainer;
386 - (NSString *) tagline;
387 - (NSString *) description;
388 - (NSComparisonResult) compareBySectionAndName:(Package *)package;
394 @implementation Package
396 - (Package *) initWithIterator:(pkgCache::PkgIterator)iterator database:(Database *)database version:(pkgCache::VerIterator)version file:(pkgCache::VerFileIterator)file {
397 if ((self = [super init]) != nil) {
398 iterator_ = iterator;
399 database_ = database;
403 parser_ = &[database_ records]->Lookup(file);
407 + (Package *) packageWithIterator:(pkgCache::PkgIterator)iterator database:(Database *)database {
408 for (pkgCache::VerIterator version = iterator.VersionList(); !version.end(); ++version)
409 for (pkgCache::VerFileIterator file = version.FileList(); !file.end(); ++file)
410 return [[[Package alloc]
411 initWithIterator:iterator
419 - (NSString *) name {
420 return [[NSString stringWithCString:iterator_.Name()] lowercaseString];
423 - (NSString *) section {
424 return [NSString stringWithCString:iterator_.Section()];
427 - (NSString *) latest {
428 return [NSString stringWithCString:version_.VerStr()];
431 - (NSString *) installed {
432 return iterator_.CurrentVer().end() ? nil : [NSString stringWithCString:iterator_.CurrentVer().VerStr()];
435 - (Address *) maintainer {
436 return [Address addressWithString:[NSString stringWithCString:parser_->Maintainer().c_str()]];
440 return version_->InstalledSize;
443 - (NSString *) tagline {
444 return [NSString stringWithCString:parser_->ShortDesc().c_str()];
447 - (NSString *) description {
448 return [NSString stringWithCString:parser_->LongDesc().c_str()];
451 - (NSComparisonResult) compareBySectionAndName:(Package *)package {
452 NSComparisonResult result = [[self section] compare:[package section]];
453 if (result != NSOrderedSame)
455 return [[self name] compare:[package name]];
459 pkgProblemResolver *resolver = [database_ resolver];
460 resolver->Clear(iterator_);
461 resolver->Protect(iterator_);
462 [database_ cache]->MarkInstall(iterator_, false);
466 pkgProblemResolver *resolver = [database_ resolver];
467 resolver->Clear(iterator_);
468 resolver->Protect(iterator_);
469 resolver->Remove(iterator_);
470 [database_ cache]->MarkDelete(iterator_, true);
475 /* Section Class {{{ */
476 @interface Section : NSObject {
479 NSMutableArray *packages_;
484 - (Section *) initWithName:(NSString *)name row:(size_t)row;
487 - (void) addPackage:(Package *)package;
490 @implementation Section
498 - (Section *) initWithName:(NSString *)name row:(size_t)row {
499 if ((self = [super init]) != nil) {
500 name_ = [name retain];
502 packages_ = [[NSMutableArray arrayWithCapacity:16] retain];
506 - (NSString *) name {
514 - (void) addPackage:(Package *)package {
515 [packages_ addObject:package];
521 /* Confirmation View {{{ */
522 void AddTextView(NSMutableDictionary *fields, NSMutableArray *packages, NSString *key) {
523 if ([packages count] == 0)
526 CGColorSpaceRef space = CGColorSpaceCreateDeviceRGB();
527 float clear[] = {0, 0, 0, 0};
528 float blue[] = {0, 0, 0.4, 1};
530 UITextView *text([[[UITextView alloc] initWithFrame: CGRectMake(110, 3, 200, 60)] autorelease]);
531 [text setEditable:NO];
532 [text setTextSize:16];
533 [text setBackgroundColor:CGColorCreate(space, clear)];
534 [text setTextColor:CGColorCreate(space, blue)];
535 [text setText:([packages count] == 0 ? @"n/a" : [packages componentsJoinedByString:@", "])];
536 [text setEnabled:NO];
538 CGRect frame([text frame]);
539 CGSize size([text contentSize]);
540 frame.size.height = size.height;
541 [text setFrame:frame];
543 [fields setObject:text forKey:key];
546 @protocol ConfirmationViewDelegate
551 @interface ConfirmationView : UIView {
554 UITransitionView *transition_;
556 UINavigationBar *navbar_;
557 UIPreferencesTable *table_;
558 NSMutableDictionary *fields_;
559 UIAlertSheet *essential_;
565 - (void) transitionViewDidComplete:(UITransitionView*)view fromView:(UIView*)from toView:(UIView*)to;
566 - (void) navigationBar:(UINavigationBar *)navbar buttonClicked:(int)button;
567 - (void) alertSheet:(UIAlertSheet *)sheet buttonClicked:(int)button;
569 - (int) numberOfGroupsInPreferencesTable:(UIPreferencesTable *)table;
570 - (NSString *) preferencesTable:(UIPreferencesTable *)table titleForGroup:(int)group;
571 - (float) preferencesTable:(UIPreferencesTable *)table heightForRow:(int)row inGroup:(int)group withProposedHeight:(float)proposed;
572 - (int) preferencesTable:(UIPreferencesTable *)table numberOfRowsInGroup:(int)group;
573 - (UIPreferencesTableCell *) preferencesTable:(UIPreferencesTable *)table cellForRow:(int)row inGroup:(int)group;
575 - (id) initWithView:(UIView *)view database:(Database *)database delegate:(id)delegate;
579 @implementation ConfirmationView
582 [transition_ release];
587 if (essential_ != nil)
588 [essential_ release];
593 [transition_ transition:7 toView:nil];
597 - (void) transitionViewDidComplete:(UITransitionView*)view fromView:(UIView*)from toView:(UIView*)to {
598 if (from != nil && to == nil)
599 [self removeFromSuperview];
602 - (void) navigationBar:(UINavigationBar *)navbar buttonClicked:(int)button {
605 if (essential_ != nil)
606 [essential_ popupAlertAnimated:YES];
617 - (void) alertSheet:(UIAlertSheet *)sheet buttonClicked:(int)button {
618 [essential_ dismiss];
622 - (int) numberOfGroupsInPreferencesTable:(UIPreferencesTable *)table {
626 - (NSString *) preferencesTable:(UIPreferencesTable *)table titleForGroup:(int)group {
628 case 0: return @"Statistics";
629 case 1: return @"Modifications";
631 default: _assert(false);
635 - (int) preferencesTable:(UIPreferencesTable *)table numberOfRowsInGroup:(int)group {
638 case 1: return [fields_ count];
640 default: _assert(false);
644 - (float) preferencesTable:(UIPreferencesTable *)table heightForRow:(int)row inGroup:(int)group withProposedHeight:(float)proposed {
645 if (group != 1 || row == -1)
648 _assert(size_t(row) < [fields_ count]);
649 return [[[fields_ allValues] objectAtIndex:row] contentSize].height;
653 - (UIPreferencesTableCell *) preferencesTable:(UIPreferencesTable *)table cellForRow:(int)row inGroup:(int)group {
654 UIPreferencesTableCell *cell = [[[UIPreferencesTableCell alloc] init] autorelease];
655 [cell setShowSelection:NO];
658 case 0: switch (row) {
660 [cell setTitle:@"Downloading"];
661 [cell setValue:SizeString([database_ fetcher].FetchNeeded())];
665 [cell setTitle:@"Resuming At"];
666 [cell setValue:SizeString([database_ fetcher].PartialPresent())];
670 double size([database_ cache]->UsrSize());
673 [cell setTitle:@"Disk Freeing"];
674 [cell setValue:SizeString(-size)];
676 [cell setTitle:@"Disk Using"];
677 [cell setValue:SizeString(size)];
681 default: _assert(false);
685 _assert(size_t(row) < [fields_ count]);
686 [cell setTitle:[[fields_ allKeys] objectAtIndex:row]];
687 [cell addSubview:[[fields_ allValues] objectAtIndex:row]];
690 default: _assert(false);
696 - (id) initWithView:(UIView *)view database:(Database *)database delegate:(id)delegate {
697 if ((self = [super initWithFrame:[view bounds]]) != nil) {
698 database_ = database;
699 delegate_ = delegate;
701 transition_ = [[UITransitionView alloc] initWithFrame:[self bounds]];
702 [self addSubview:transition_];
704 overlay_ = [[UIView alloc] initWithFrame:[transition_ bounds]];
706 CGSize navsize = [UINavigationBar defaultSize];
707 CGRect navrect = {{0, 0}, navsize};
708 CGRect bounds = [overlay_ bounds];
710 navbar_ = [[UINavigationBar alloc] initWithFrame:navrect];
711 [navbar_ setBarStyle:1];
712 [navbar_ setDelegate:self];
714 UINavigationItem *navitem = [[[UINavigationItem alloc] initWithTitle:@"Confirm"] autorelease];
715 [navbar_ pushNavigationItem:navitem];
716 [navbar_ showButtonsWithLeftTitle:@"Cancel" rightTitle:@"Confirm"];
718 fields_ = [[NSMutableDictionary dictionaryWithCapacity:16] retain];
720 NSMutableArray *installing = [NSMutableArray arrayWithCapacity:16];
721 NSMutableArray *upgrading = [NSMutableArray arrayWithCapacity:16];
722 NSMutableArray *removing = [NSMutableArray arrayWithCapacity:16];
724 bool essential(false);
726 pkgCacheFile &cache([database_ cache]);
727 for (pkgCache::PkgIterator iterator = cache->PkgBegin(); !iterator.end(); ++iterator) {
728 NSString *name([NSString stringWithCString:iterator.Name()]);
729 if (cache[iterator].NewInstall())
730 [installing addObject:name];
731 else if (cache[iterator].Upgrade())
732 [upgrading addObject:name];
733 else if (cache[iterator].Delete()) {
734 [removing addObject:name];
735 if ((iterator->Flags & pkgCache::Flag::Essential) != 0)
743 essential_ = [[UIAlertSheet alloc]
744 initWithTitle:@"Unable to Comply"
745 buttons:[NSArray arrayWithObjects:@"Okay", nil]
751 [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."];
754 AddTextView(fields_, installing, @"Installing");
755 AddTextView(fields_, upgrading, @"Upgrading");
756 AddTextView(fields_, removing, @"Removing");
758 table_ = [[UIPreferencesTable alloc] initWithFrame:CGRectMake(
759 0, navsize.height, bounds.size.width, bounds.size.height - navsize.height
762 [table_ setReusesTableCells:YES];
763 [table_ setDataSource:self];
766 [overlay_ addSubview:navbar_];
767 [overlay_ addSubview:table_];
769 [view addSubview:self];
771 [transition_ setDelegate:self];
773 UIView *blank = [[[UIView alloc] initWithFrame:[transition_ bounds]] autorelease];
774 [transition_ transition:0 toView:blank];
775 [transition_ transition:3 toView:overlay_];
781 /* Package View {{{ */
782 @interface PackageView : UIView {
783 UIPreferencesTable *table_;
786 NSMutableArray *cells_;
792 - (int) numberOfGroupsInPreferencesTable:(UIPreferencesTable *)table;
793 - (NSString *) preferencesTable:(UIPreferencesTable *)table titleForGroup:(int)group;
794 - (int) preferencesTable:(UIPreferencesTable *)table numberOfRowsInGroup:(int)group;
795 - (UIPreferencesTableCell *) preferencesTable:(UIPreferencesTable *)table cellForRow:(int)row inGroup:(int)group;
797 - (BOOL) canSelectRow:(int)row;
798 - (void) tableRowSelected:(NSNotification *)notification;
800 - (id) initWithFrame:(struct CGRect)frame database:(Database *)database;
801 - (void) setPackage:(Package *)package;
802 - (void) setDelegate:(id)delegate;
805 @implementation PackageView
816 - (int) numberOfGroupsInPreferencesTable:(UIPreferencesTable *)table {
820 - (NSString *) preferencesTable:(UIPreferencesTable *)table titleForGroup:(int)group {
822 case 0: return @"Specifics";
823 case 1: return @"Description";
825 default: _assert(false);
829 - (int) preferencesTable:(UIPreferencesTable *)table numberOfRowsInGroup:(int)group {
834 default: _assert(false);
838 - (UIPreferencesTableCell *) preferencesTable:(UIPreferencesTable *)table cellForRow:(int)row inGroup:(int)group {
839 UIPreferencesTableCell *cell;
842 case 0: switch (row) {
844 cell = [cells_ objectAtIndex:0];
845 [cell setTitle:@"Name"];
846 [cell setValue:[package_ name]];
850 cell = [cells_ objectAtIndex:1];
851 [cell setTitle:@"Installed"];
852 NSString *installed([package_ installed]);
853 [cell setValue:(installed == nil ? @"n/a" : installed)];
857 cell = [cells_ objectAtIndex:2];
858 [cell setTitle:@"Latest"];
859 [cell setValue:[package_ latest]];
863 cell = [cells_ objectAtIndex:3];
864 [cell setTitle:@"Section"];
865 [cell setValue:[package_ section]];
869 cell = [cells_ objectAtIndex:4];
870 [cell setTitle:@"Size"];
871 [cell setValue:SizeString([package_ size])];
875 cell = [cells_ objectAtIndex:5];
876 [cell setTitle:@"Maintainer"];
877 [cell setValue:[[package_ maintainer] name]];
878 [cell setShowDisclosure:YES];
879 [cell setShowSelection:YES];
882 default: _assert(false);
885 case 1: switch (row) {
887 cell = [cells_ objectAtIndex:6];
889 [cell setValue:[package_ tagline]];
893 cell = [cells_ objectAtIndex:7];
894 [cell setTitle:@"Description"];
895 [cell setValue:[package_ description]];
899 default: _assert(false);
905 - (BOOL) canSelectRow:(int)row {
909 - (void) tableRowSelected:(NSNotification *)notification {
910 switch ([table_ selectedRow]) {
912 [delegate_ openURL:[NSURL URLWithString:[NSString stringWithFormat:@"mailto:%@?subject=%@",
913 [[package_ maintainer] email],
914 [[NSString stringWithFormat:@"regarding apt package \"%@\"", [package_ name]] stringByAddingPercentEscapes]
920 - (id) initWithFrame:(struct CGRect)frame database:(Database *)database {
921 if ((self = [super initWithFrame:frame]) != nil) {
922 database_ = [database retain];
924 table_ = [[UIPreferencesTable alloc] initWithFrame:[self bounds]];
925 [self addSubview:table_];
927 [table_ setDataSource:self];
928 [table_ setDelegate:self];
930 cells_ = [[NSMutableArray arrayWithCapacity:16] retain];
932 for (unsigned i = 0; i != 8; ++i) {
933 UIPreferencesTableCell *cell = [[[UIPreferencesTableCell alloc] init] autorelease];
934 [cell setShowSelection:NO];
935 [cells_ addObject:cell];
940 - (void) setPackage:(Package *)package {
941 package_ = [package retain];
945 - (void) setDelegate:(id)delegate {
946 delegate_ = delegate;
951 /* Package Cell {{{ */
952 @protocol PackageCellDelegate
953 - (NSString *) versionWithPackage:(Package *)package;
956 @interface PackageCell : UITableCell {
958 UIRightTextLabel *version_;
959 UITextLabel *description_;
964 - (PackageCell *) initWithPackage:(Package *)package delegate:(id)delegate;
966 - (void) _setSelected:(float)fraction;
967 - (void) setSelected:(BOOL)selected;
968 - (void) setSelected:(BOOL)selected withFade:(BOOL)fade;
969 - (void) _setSelectionFadeFraction:(float)fraction;
973 @implementation PackageCell
978 [description_ release];
982 - (PackageCell *) initWithPackage:(Package *)package delegate:(id)delegate {
983 if ((self = [super init]) != nil) {
984 GSFontRef bold = GSFontCreateWithName("Helvetica", kGSFontTraitBold, 22);
985 GSFontRef large = GSFontCreateWithName("Helvetica", kGSFontTraitNone, 16);
986 GSFontRef small = GSFontCreateWithName("Helvetica", kGSFontTraitNone, 14);
988 CGColorSpaceRef space = CGColorSpaceCreateDeviceRGB();
989 float clear[] = {0, 0, 0, 0};
991 name_ = [[UITextLabel alloc] initWithFrame:CGRectMake(12, 7, 250, 25)];
992 [name_ setText:[package name]];
993 [name_ setBackgroundColor:CGColorCreate(space, clear)];
994 [name_ setFont:bold];
996 version_ = [[UIRightTextLabel alloc] initWithFrame:CGRectMake(290, 7, 70, 25)];
997 [version_ setText:[delegate versionWithPackage:package]];
998 [version_ setBackgroundColor:CGColorCreate(space, clear)];
999 [version_ setFont:large];
1001 description_ = [[UITextLabel alloc] initWithFrame:CGRectMake(13, 35, 315, 20)];
1002 [description_ setText:[package tagline]];
1003 [description_ setBackgroundColor:CGColorCreate(space, clear)];
1004 [description_ setFont:small];
1006 [self addSubview:name_];
1007 [self addSubview:version_];
1008 [self addSubview:description_];
1016 - (void) _setSelected:(float)fraction {
1017 CGColorSpaceRef space = CGColorSpaceCreateDeviceRGB();
1020 interpolate(0.0, 1.0, fraction),
1021 interpolate(0.0, 1.0, fraction),
1022 interpolate(0.0, 1.0, fraction),
1026 interpolate(0.2, 1.0, fraction),
1027 interpolate(0.2, 1.0, fraction),
1028 interpolate(1.0, 1.0, fraction),
1032 interpolate(0.4, 1.0, fraction),
1033 interpolate(0.4, 1.0, fraction),
1034 interpolate(0.4, 1.0, fraction),
1037 [name_ setColor:CGColorCreate(space, black)];
1038 [version_ setColor:CGColorCreate(space, blue)];
1039 [description_ setColor:CGColorCreate(space, gray)];
1042 - (void) setSelected:(BOOL)selected {
1043 [self _setSelected:(selected ? 1.0 : 0.0)];
1044 [super setSelected:selected];
1047 - (void) setSelected:(BOOL)selected withFade:(BOOL)fade {
1049 [self _setSelected:(selected ? 1.0 : 0.0)];
1050 [super setSelected:selected withFade:fade];
1053 - (void) _setSelectionFadeFraction:(float)fraction {
1054 [self _setSelected:fraction];
1055 [super _setSelectionFadeFraction:fraction];
1060 /* Sources View {{{ */
1061 @interface SourcesView : ResetView {
1062 UISectionList *list_;
1063 Database *database_;
1065 NSMutableArray *sources_;
1068 - (void) navigationBar:(UINavigationBar *)navbar buttonClicked:(int)button;
1070 - (id) initWithFrame:(CGRect)frame database:(Database *)database;
1071 - (void) setDelegate:(id)delegate;
1072 - (void) reloadData;
1073 - (NSString *) leftTitle;
1074 - (NSString *) rightTitle;
1077 @implementation SourcesView
1079 - (void) navigationBar:(UINavigationBar *)navbar buttonClicked:(int)button {
1091 if (sources_ != nil)
1097 - (id) initWithFrame:(CGRect)frame database:(Database *)database {
1098 if ((self = [super initWithFrame:frame]) != nil) {
1099 database_ = database;
1102 CGSize navsize = [UINavigationBar defaultSize];
1103 CGRect navrect = {{0, 0}, navsize};
1104 CGRect bounds = [self bounds];
1106 navbar_ = [[UINavigationBar alloc] initWithFrame:navrect];
1107 [self addSubview:navbar_];
1109 [navbar_ setBarStyle:1];
1110 [navbar_ setDelegate:self];
1112 UINavigationItem *navitem = [[[UINavigationItem alloc] initWithTitle:@"Sources"] autorelease];
1113 [navbar_ pushNavigationItem:navitem];
1115 list_ = [[UISectionList alloc] initWithFrame:CGRectMake(
1116 0, navsize.height, bounds.size.width, bounds.size.height - navsize.height
1119 [list_ setDataSource:self];
1120 //[list_ setShouldHideHeaderInShortLists:NO];
1124 - (void) setDelegate:(id)delegate {
1125 delegate_ = delegate;
1128 - (void) reloadData {
1130 _assert(list.ReadMainList());
1132 sources_ = [[NSMutableArray arrayWithCapacity:16] retain];
1134 for (pkgSourceList::const_iterator source = list.begin(); source != list.end(); ++source) {
1135 metaIndex *index(*source);
1136 fprintf(stderr, "\"%s\" \"%s\" \"%s\" \"%s\"\n", index->GetURI().c_str(), index->GetDist().c_str(), index->GetType(), index->IsTrusted() ? "true" : "false");
1138 debReleaseIndex *dindex(dynamic_cast<debReleaseIndex *>(index));
1142 fprintf(stderr, " \"%s\"\n", dindex->MetaIndexFile("Release").c_str());
1144 std::ifstream release(dindex->MetaIndexFile("Release").c_str());
1146 while (std::getline(release, line)) {
1147 std::string::size_type colon(line.find(':'));
1148 if (colon == std::string::npos)
1150 std::string name(line.substr(0, colon));
1151 std::string value(line.substr(colon + 1));
1152 while (!value.empty() && value[0] == ' ')
1153 value = value.substr(1);
1154 std::cerr << "[" << name << "|" << value << "]" << std::endl;
1161 - (NSString *) leftTitle {
1162 return @"Refresh All";
1165 - (NSString *) rightTitle {
1172 @implementation Database
1174 - (void) _readStatus:(NSNumber *)fd {
1175 NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
1177 __gnu_cxx::stdio_filebuf<char> ib([fd intValue], std::ios::in);
1178 std::istream is(&ib);
1183 pcre *code = pcre_compile("^([^:]*):([^:]*):([^:]*):(.*)$", 0, &error, &offset, NULL);
1185 pcre_extra *study = NULL;
1187 pcre_fullinfo(code, study, PCRE_INFO_CAPTURECOUNT, &capture);
1188 int matches[(capture + 1) * 3];
1190 while (std::getline(is, line)) {
1191 const char *data(line.c_str());
1193 _assert(pcre_exec(code, study, data, line.size(), 0, 0, matches, sizeof(matches) / sizeof(matches[0])) >= 0);
1195 std::istringstream buffer(line.substr(matches[6], matches[7] - matches[6]));
1198 [delegate_ setPercent:(percent / 100)];
1200 NSString *string = [NSString stringWithCString:(data + matches[8]) length:(matches[9] - matches[8])];
1201 std::string type(line.substr(matches[2], matches[3] - matches[2]));
1203 if (type == "pmerror")
1204 [delegate_ setError:string];
1205 else if (type == "pmstatus")
1206 [delegate_ setTitle:string];
1207 else if (type == "pmconffile")
1209 else _assert(false);
1215 - (void) _readOutput:(NSNumber *)fd {
1216 NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
1218 __gnu_cxx::stdio_filebuf<char> ib([fd intValue], std::ios::in);
1219 std::istream is(&ib);
1222 while (std::getline(is, line))
1223 [delegate_ addOutput:[NSString stringWithCString:line.c_str()]];
1228 - (Package *) packageWithName:(NSString *)name {
1229 pkgCache::PkgIterator iterator(cache_->FindPkg([name cString]));
1230 return iterator.end() ? nil : [Package packageWithIterator:iterator database:self];
1233 - (Database *) init {
1234 if ((self = [super init]) != nil) {
1242 _assert(pipe(fds) != -1);
1246 detachNewThreadSelector:@selector(_readStatus:)
1248 withObject:[[NSNumber numberWithInt:fds[0]] retain]
1251 _assert(pipe(fds) != -1);
1252 _assert(dup2(fds[1], 1) != -1);
1253 _assert(close(fds[1]) != -1);
1256 detachNewThreadSelector:@selector(_readOutput:)
1258 withObject:[[NSNumber numberWithInt:fds[0]] retain]
1263 - (pkgCacheFile &) cache {
1267 - (pkgRecords *) records {
1271 - (pkgProblemResolver *) resolver {
1275 - (pkgAcquire &) fetcher {
1279 - (void) reloadData {
1287 cache_.Open(progress_, true);
1288 records_ = new pkgRecords(cache_);
1289 resolver_ = new pkgProblemResolver(cache_);
1290 fetcher_ = new pkgAcquire(&status_);
1295 pkgRecords records(cache_);
1297 lock_ = new FileFd();
1298 lock_->Fd(GetLock(_config->FindDir("Dir::Cache::Archives") + "lock"));
1299 _assert(!_error->PendingError());
1302 _assert(list.ReadMainList());
1304 manager_ = (_system->CreatePM(cache_));
1305 _assert(manager_->GetArchives(fetcher_, &list, &records));
1306 _assert(!_error->PendingError());
1310 if (fetcher_->Run(PulseInterval_) != pkgAcquire::Continue)
1314 pkgPackageManager::OrderResult result = manager_->DoInstall(statusfd_);
1316 if (result == pkgPackageManager::Failed)
1318 if (_error->PendingError())
1320 if (result != pkgPackageManager::Completed)
1326 _assert(list.ReadMainList());
1329 lock.Fd(GetLock(_config->FindDir("Dir::State::Lists") + "lock"));
1330 _assert(!_error->PendingError());
1332 pkgAcquire fetcher(&status_);
1333 _assert(list.GetIndexes(&fetcher));
1334 _assert(fetcher.Run(PulseInterval_) != pkgAcquire::Failed);
1336 bool failed = false;
1337 for (pkgAcquire::ItemIterator item = fetcher.ItemsBegin(); item != fetcher.ItemsEnd(); item++)
1338 if ((*item)->Status != pkgAcquire::Item::StatDone) {
1339 (*item)->Finished();
1343 if (!failed && _config->FindB("APT::Get::List-Cleanup", true) == true) {
1344 _assert(fetcher.Clean(_config->FindDir("Dir::State::lists")));
1345 _assert(fetcher.Clean(_config->FindDir("Dir::State::lists") + "partial/"));
1350 _assert(cache_->DelCount() == 0 && cache_->InstCount() == 0);
1351 _assert(pkgApplyStatus(cache_));
1353 if (cache_->BrokenCount() != 0) {
1354 _assert(pkgFixBroken(cache_));
1355 _assert(cache_->BrokenCount() == 0);
1356 _assert(pkgMinimizeUpgrade(cache_));
1359 _assert(pkgDistUpgrade(cache_));
1362 - (void) setDelegate:(id)delegate {
1363 delegate_ = delegate;
1364 status_.setDelegate(delegate);
1365 progress_.setDelegate(delegate);
1370 /* Progress Data {{{ */
1371 @interface ProgressData : NSObject {
1377 - (ProgressData *) initWithSelector:(SEL)selector target:(id)target object:(id)object;
1384 @implementation ProgressData
1386 - (ProgressData *) initWithSelector:(SEL)selector target:(id)target object:(id)object {
1387 if ((self = [super init]) != nil) {
1388 selector_ = selector;
1408 /* Progress View {{{ */
1409 @interface ProgressView : UIView <
1413 UIView *background_;
1414 UITransitionView *transition_;
1416 UINavigationBar *navbar_;
1417 UIProgressBar *progress_;
1418 UITextView *output_;
1419 UITextLabel *status_;
1421 UIAlertSheet *alert_;
1426 - (ProgressView *) initWithFrame:(struct CGRect)frame delegate:(id)delegate;
1427 - (void) setContentView:(UIView *)view;
1430 - (void) alertSheet:(UIAlertSheet *)sheet buttonClicked:(int)button;
1432 - (void) _retachThread;
1433 - (void) _detachNewThreadData:(ProgressData *)data;
1434 - (void) detachNewThreadSelector:(SEL)selector toTarget:(id)target withObject:(id)object;
1436 - (void) setError:(NSString *)error;
1437 - (void) _setError:(NSString *)error;
1439 - (void) setTitle:(NSString *)title;
1440 - (void) _setTitle:(NSString *)title;
1442 - (void) setPercent:(float)percent;
1443 - (void) _setPercent:(NSNumber *)percent;
1445 - (void) addOutput:(NSString *)output;
1446 - (void) _addOutput:(NSString *)output;
1448 - (void) setStatusFail;
1451 @protocol ProgressViewDelegate
1452 - (void) progressViewIsComplete:(ProgressView *)sender;
1455 @implementation ProgressView
1459 [background_ release];
1460 [transition_ release];
1463 [progress_ release];
1469 - (ProgressView *) initWithFrame:(struct CGRect)frame delegate:(id)delegate {
1470 if ((self = [super initWithFrame:frame]) != nil) {
1471 delegate_ = delegate;
1474 CGColorSpaceRef space = CGColorSpaceCreateDeviceRGB();
1475 float black[] = {0.0, 0.0, 0.0, 1.0};
1476 float white[] = {1.0, 1.0, 1.0, 1.0};
1477 float clear[] = {0.0, 0.0, 0.0, 0.0};
1479 background_ = [[UIView alloc] initWithFrame:[self bounds]];
1480 [background_ setBackgroundColor:CGColorCreate(space, black)];
1481 [self addSubview:background_];
1483 transition_ = [[UITransitionView alloc] initWithFrame:[self bounds]];
1484 [self addSubview:transition_];
1486 overlay_ = [[UIView alloc] initWithFrame:[transition_ bounds]];
1488 CGSize navsize = [UINavigationBar defaultSize];
1489 CGRect navrect = {{0, 0}, navsize};
1491 navbar_ = [[UINavigationBar alloc] initWithFrame:navrect];
1492 [overlay_ addSubview:navbar_];
1494 [navbar_ setBarStyle:1];
1495 [navbar_ setDelegate:self];
1497 UINavigationItem *navitem = [[[UINavigationItem alloc] initWithTitle:@"Running..."] autorelease];
1498 [navbar_ pushNavigationItem:navitem];
1500 CGRect bounds = [overlay_ bounds];
1501 CGSize prgsize = [UIProgressBar defaultSize];
1504 (bounds.size.width - prgsize.width) / 2,
1505 bounds.size.height - prgsize.height - 20
1508 progress_ = [[UIProgressBar alloc] initWithFrame:prgrect];
1509 [overlay_ addSubview:progress_];
1511 status_ = [[UITextLabel alloc] initWithFrame:CGRectMake(
1513 bounds.size.height - prgsize.height - 50,
1514 bounds.size.width - 20,
1518 [status_ setColor:CGColorCreate(space, white)];
1519 [status_ setBackgroundColor:CGColorCreate(space, clear)];
1521 [status_ setCentersHorizontally:YES];
1522 //[status_ setFont:font];
1524 output_ = [[UITextView alloc] initWithFrame:CGRectMake(
1526 navrect.size.height + 20,
1527 bounds.size.width - 20,
1528 bounds.size.height - navsize.height - 62 - navrect.size.height
1531 //[output_ setTextFont:@"Courier New"];
1532 [output_ setTextSize:12];
1534 [output_ setTextColor:CGColorCreate(space, white)];
1535 [output_ setBackgroundColor:CGColorCreate(space, clear)];
1537 [output_ setMarginTop:0];
1538 [output_ setAllowsRubberBanding:YES];
1540 [overlay_ addSubview:output_];
1541 [overlay_ addSubview:status_];
1543 [progress_ setStyle:0];
1547 - (void) setContentView:(UIView *)view {
1551 - (void) resetView {
1552 [transition_ transition:6 toView:view_];
1555 - (void) alertSheet:(UIAlertSheet *)sheet buttonClicked:(int)button {
1561 - (void) _retachThread {
1562 [delegate_ progressViewIsComplete:self];
1566 - (void) _detachNewThreadData:(ProgressData *)data {
1567 NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
1569 [[data target] performSelector:[data selector] withObject:[data object]];
1570 [self performSelectorOnMainThread:@selector(_retachThread) withObject:nil waitUntilDone:YES];
1576 - (void) detachNewThreadSelector:(SEL)selector toTarget:(id)target withObject:(id)object {
1577 [status_ setText:nil];
1578 [output_ setText:@""];
1579 [progress_ setProgress:0];
1581 [transition_ transition:6 toView:overlay_];
1584 detachNewThreadSelector:@selector(_detachNewThreadData:)
1586 withObject:[[ProgressData alloc]
1587 initWithSelector:selector
1594 - (void) setStatusFail {
1597 - (void) setError:(NSString *)error {
1599 performSelectorOnMainThread:@selector(_setError:)
1605 - (void) _setError:(NSString *)error {
1606 _assert(alert_ == nil);
1608 alert_ = [[UIAlertSheet alloc]
1609 initWithTitle:@"Package Error"
1610 buttons:[NSArray arrayWithObjects:@"Okay", nil]
1611 defaultButtonIndex:0
1616 [alert_ setBodyText:error];
1617 [alert_ popupAlertAnimated:YES];
1620 - (void) setTitle:(NSString *)title {
1622 performSelectorOnMainThread:@selector(_setTitle:)
1628 - (void) _setTitle:(NSString *)title {
1629 [status_ setText:[title stringByAppendingString:@"..."]];
1632 - (void) setPercent:(float)percent {
1634 performSelectorOnMainThread:@selector(_setPercent:)
1635 withObject:[NSNumber numberWithFloat:percent]
1640 - (void) _setPercent:(NSNumber *)percent {
1641 [progress_ setProgress:[percent floatValue]];
1644 - (void) addOutput:(NSString *)output {
1646 performSelectorOnMainThread:@selector(_addOutput:)
1652 - (void) _addOutput:(NSString *)output {
1653 [output_ setText:[NSString stringWithFormat:@"%@\n%@", [output_ text], output]];
1654 CGSize size = [output_ contentSize];
1655 CGRect rect = {{0, size.height}, {size.width, 0}};
1656 [output_ scrollRectToVisible:rect animated:YES];
1662 @protocol PackagesViewDelegate
1665 - (void) openURL:(NSString *)url;
1668 /* PackagesView {{{ */
1669 @interface PackagesView : ResetView <
1672 Database *database_;
1673 NSMutableArray *packages_;
1674 NSMutableArray *sections_;
1676 UISectionList *list_;
1677 UITransitionView *transition_;
1680 PackageView *pkgview_;
1683 - (int) numberOfSectionsInSectionList:(UISectionList *)list;
1684 - (NSString *) sectionList:(UISectionList *)list titleForSection:(int)section;
1685 - (int) sectionList:(UISectionList *)list rowForSection:(int)section;
1687 - (int) numberOfRowsInTable:(UITable *)table;
1688 - (float) table:(UITable *)table heightForRow:(int)row;
1689 - (UITableCell *) table:(UITable *)table cellForRow:(int)row column:(UITableColumn *)col;
1690 - (BOOL) table:(UITable *)table showDisclosureForRow:(int)row;
1691 - (void) tableRowSelected:(NSNotification*)notification;
1693 - (void) navigationBar:(UINavigationBar *)navbar buttonClicked:(int)button;
1694 - (void) navigationBar:(UINavigationBar *)navbar poppedItem:(UINavigationItem *)item;
1696 - (id) initWithFrame:(struct CGRect)frame database:(Database *)database;
1697 - (void) setDelegate:(id)delegate;
1699 - (void) reloadData:(BOOL)reset;
1701 - (NSString *) title;
1702 - (void) perform:(Package *)package;
1703 - (void) addPackage:(Package *)package;
1704 - (NSString *) versionWithPackage:(Package *)package;
1707 @implementation PackagesView
1709 - (int) numberOfSectionsInSectionList:(UISectionList *)list {
1710 return [sections_ count];
1713 - (NSString *) sectionList:(UISectionList *)list titleForSection:(int)section {
1714 return [[sections_ objectAtIndex:section] name];
1717 - (int) sectionList:(UISectionList *)list rowForSection:(int)section {
1718 return [[sections_ objectAtIndex:section] row];
1721 - (int) numberOfRowsInTable:(UITable *)table {
1722 return [packages_ count];
1725 - (float) table:(UITable *)table heightForRow:(int)row {
1729 - (UITableCell *) table:(UITable *)table cellForRow:(int)row column:(UITableColumn *)col {
1730 Package *package = [packages_ objectAtIndex:row];
1731 PackageCell *cell = [[[PackageCell alloc] initWithPackage:package delegate:self] autorelease];
1735 - (BOOL) table:(UITable *)table showDisclosureForRow:(int)row {
1739 - (void) tableRowSelected:(NSNotification*)notification {
1740 int row = [[list_ table] selectedRow];
1744 package_ = [packages_ objectAtIndex:row];
1745 pkgname_ = [[package_ name] retain];
1747 UINavigationItem *navitem = [[UINavigationItem alloc] initWithTitle:[package_ name]];
1748 [navbar_ pushNavigationItem:navitem];
1750 [navbar_ showButtonsWithLeftTitle:nil rightTitle:[self title]];
1752 [pkgview_ setPackage:package_];
1753 [transition_ transition:1 toView:pkgview_];
1756 - (void) navigationBar:(UINavigationBar *)navbar buttonClicked:(int)button {
1758 [self perform:package_];
1760 pkgProblemResolver *resolver = [database_ resolver];
1762 resolver->InstallProtect();
1763 if (!resolver->Resolve(true))
1766 [delegate_ perform];
1770 - (void) navigationBar:(UINavigationBar *)navbar poppedItem:(UINavigationItem *)item {
1772 [super navigationBar:navbar poppedItem:item];
1775 - (id) initWithFrame:(struct CGRect)frame database:(Database *)database {
1776 if ((self = [super initWithFrame:frame]) != nil) {
1777 database_ = [database retain];
1779 struct CGRect bounds = [self bounds];
1780 CGSize navsize = [UINavigationBar defaultSize];
1781 CGRect navrect = {{0, 0}, navsize};
1783 navbar_ = [[UINavigationBar alloc] initWithFrame:navrect];
1784 [self addSubview:navbar_];
1786 [navbar_ setBarStyle:1];
1787 [navbar_ setDelegate:self];
1789 UINavigationItem *navitem = [[[UINavigationItem alloc] initWithTitle:[self title]] autorelease];
1790 [navbar_ pushNavigationItem:navitem];
1791 [navitem setBackButtonTitle:@"Packages"];
1793 transition_ = [[UITransitionView alloc] initWithFrame:CGRectMake(
1794 bounds.origin.x, bounds.origin.y + navsize.height, bounds.size.width, bounds.size.height - navsize.height
1797 [self addSubview:transition_];
1799 list_ = [[UISectionList alloc] initWithFrame:[transition_ bounds] showSectionIndex:NO];
1800 [list_ setDataSource:self];
1801 [list_ setShouldHideHeaderInShortLists:NO];
1803 [transition_ transition:0 toView:list_];
1805 UITableColumn *column = [[UITableColumn alloc]
1806 initWithTitle:@"Name"
1808 width:frame.size.width
1811 UITable *table = [list_ table];
1812 [table setSeparatorStyle:1];
1813 [table addTableColumn:column];
1814 [table setDelegate:self];
1816 pkgview_ = [[PackageView alloc] initWithFrame:[transition_ bounds] database:database_];
1820 - (void) setDelegate:(id)delegate {
1821 delegate_ = delegate;
1822 [pkgview_ setDelegate:delegate];
1826 [transition_ transition:(resetting_ ? 0 : 2) toView:list_];
1827 UITable *table = [list_ table];
1828 [table selectRow:-1 byExtendingSelection:NO withFade:(resetting_ ? NO : YES)];
1832 - (void) reloadData:(BOOL)reset {
1833 packages_ = [[NSMutableArray arrayWithCapacity:16] retain];
1835 if (sections_ != nil) {
1836 [sections_ release];
1840 for (pkgCache::PkgIterator iterator = [database_ cache]->PkgBegin(); !iterator.end(); ++iterator)
1841 if (Package *package = [Package packageWithIterator:iterator database:database_])
1842 [self addPackage:package];
1844 [packages_ sortUsingSelector:@selector(compareBySectionAndName:)];
1845 sections_ = [[NSMutableArray arrayWithCapacity:16] retain];
1847 Section *section = nil;
1848 for (size_t offset = 0, count = [packages_ count]; offset != count; ++offset) {
1849 Package *package = [packages_ objectAtIndex:offset];
1850 NSString *name = [package section];
1852 if (section == nil || ![[section name] isEqual:name]) {
1853 section = [[Section alloc] initWithName:name row:offset];
1854 [sections_ addObject:section];
1857 [section addPackage:package];
1863 else if (package_ != nil) {
1864 package_ = [database_ packageWithName:pkgname_];
1865 [pkgview_ setPackage:package_];
1869 - (NSString *) title {
1873 - (void) perform:(Package *)package {
1876 - (void) addPackage:(Package *)package {
1877 [packages_ addObject:package];
1880 - (NSString *) versionWithPackage:(Package *)package {
1887 /* InstallView {{{ */
1888 @interface InstallView : PackagesView {
1891 - (NSString *) title;
1892 - (void) addPackage:(Package *)package;
1893 - (void) perform:(Package *)package;
1894 - (NSString *) versionWithPackage:(Package *)package;
1897 @implementation InstallView
1899 - (NSString *) title {
1903 - (void) addPackage:(Package *)package {
1904 if ([package installed] == nil)
1905 [super addPackage:package];
1908 - (void) perform:(Package *)package {
1912 - (NSString *) versionWithPackage:(Package *)package {
1913 return [package latest];
1918 /* UpgradeView {{{ */
1919 @interface UpgradeView : PackagesView {
1922 - (void) navigationBar:(UINavigationBar *)navbar buttonClicked:(int)button;
1924 - (NSString *) title;
1925 - (NSString *) leftTitle;
1926 - (void) addPackage:(Package *)package;
1927 - (void) perform:(Package *)package;
1928 - (NSString *) versionWithPackage:(Package *)package;
1931 @implementation UpgradeView
1933 - (void) navigationBar:(UINavigationBar *)navbar buttonClicked:(int)button {
1935 [super navigationBar:navbar buttonClicked:button];
1937 [database_ upgrade];
1938 [delegate_ perform];
1942 - (NSString *) title {
1946 - (NSString *) leftTitle {
1947 return @"Upgrade All";
1950 - (void) addPackage:(Package *)package {
1951 NSString *installed = [package installed];
1952 if (installed != nil && [[package latest] compare:installed] != NSOrderedSame)
1953 [super addPackage:package];
1956 - (void) perform:(Package *)package {
1960 - (NSString *) versionWithPackage:(Package *)package {
1961 return [package latest];
1966 /* UninstallView {{{ */
1967 @interface UninstallView : PackagesView {
1970 - (NSString *) title;
1971 - (void) addPackage:(Package *)package;
1972 - (void) perform:(Package *)package;
1973 - (NSString *) versionWithPackage:(Package *)package;
1976 @implementation UninstallView
1978 - (NSString *) title {
1979 return @"Uninstall";
1982 - (void) addPackage:(Package *)package {
1983 if ([package installed] != nil)
1984 [super addPackage:package];
1987 - (void) perform:(Package *)package {
1991 - (NSString *) versionWithPackage:(Package *)package {
1992 return [package installed];
1998 @interface Cydia : UIApplication <
1999 ConfirmationViewDelegate,
2000 PackagesViewDelegate,
2001 ProgressViewDelegate
2006 UITransitionView *transition_;
2007 UIButtonBar *buttonbar_;
2009 UIAlertSheet *alert_;
2010 ConfirmationView *confirm_;
2012 Database *database_;
2013 ProgressView *progress_;
2016 UINavigationBar *navbar_;
2017 UIScroller *scroller_;
2018 UIWebView *webview_;
2021 InstallView *install_;
2022 UpgradeView *upgrade_;
2023 UninstallView *uninstall_;
2024 SourcesView *sources_;
2028 - (void) reloadData:(BOOL)reset;
2034 - (void) progressViewIsComplete:(ProgressView *)progress;
2036 - (void) navigationBar:(UINavigationBar *)navbar buttonClicked:(int)button;
2037 - (void) alertSheet:(UIAlertSheet *)sheet buttonClicked:(int)button;
2038 - (void) buttonBarItemTapped:(id)sender;
2040 - (void) view:(UIView *)sender didSetFrame:(CGRect)frame;
2041 - (void) view:(UIView *)view didDrawInRect:(CGRect)rect duration:(float)duration;
2043 - (void) applicationDidFinishLaunching:(id)unused;
2046 #include <objc/objc-class.h>
2048 @implementation Cydia
2051 NSMutableURLRequest *request = [NSMutableURLRequest
2053 cachePolicy:NSURLRequestReloadIgnoringCacheData
2054 timeoutInterval:30.0
2057 [request addValue:[NSString stringWithCString:Machine_] forHTTPHeaderField:@"X-Machine"];
2058 [request addValue:[NSString stringWithCString:SerialNumber_] forHTTPHeaderField:@"X-Serial-Number"];
2060 [webview_ loadRequest:request];
2063 - (void) reloadData:(BOOL)reset {
2064 [database_ reloadData];
2065 [install_ reloadData:reset];
2066 [upgrade_ reloadData:reset];
2067 [uninstall_ reloadData:reset];
2068 [sources_ reloadData];
2072 [database_ prepare];
2073 confirm_ = [[ConfirmationView alloc] initWithView:underlay_ database:database_ delegate:self];
2077 [self reloadData:NO];
2083 [overlay_ removeFromSuperview];
2086 detachNewThreadSelector:@selector(perform)
2094 detachNewThreadSelector:@selector(update)
2100 - (void) progressViewIsComplete:(ProgressView *)progress {
2101 [self reloadData:YES];
2103 if (confirm_ != nil) {
2104 [underlay_ addSubview:overlay_];
2105 [confirm_ removeFromSuperview];
2111 - (void) navigationBar:(UINavigationBar *)navbar buttonClicked:(int)button {
2118 _assert(alert_ == nil);
2120 alert_ = [[UIAlertSheet alloc]
2121 initWithTitle:@"About Cydia Packager"
2122 buttons:[NSArray arrayWithObjects:@"Close", nil]
2123 defaultButtonIndex:0
2128 [alert_ setBodyText:
2129 @"Copyright (C) 2007\n"
2130 "Jay Freeman (saurik)\n"
2131 "saurik@saurik.com\n"
2132 "http://www.saurik.com/\n"
2135 "http://www.theokorigroup.com/\n"
2137 "College of Creative Studies,\n"
2138 "University of California,\n"
2140 "http://www.ccs.ucsb.edu/\n"
2143 "bad_, BHSPitMonkey, Cobra, core,\n"
2144 "Corona, cromas, Darken, dtzWill,\n"
2145 "francis, Godores, jerry, Kingstone,\n"
2146 "lounger, rockabilly, tman, Wbiggs"
2149 [alert_ presentSheetFromButtonBar:buttonbar_];
2154 - (void) alertSheet:(UIAlertSheet *)sheet buttonClicked:(int)button {
2160 - (void) buttonBarItemTapped:(id)sender {
2163 switch ([sender tag]) {
2164 case 1: view = featured_; break;
2165 case 2: view = install_; break;
2166 case 3: view = upgrade_; break;
2167 case 4: view = uninstall_; break;
2168 case 5: view = sources_; break;
2174 if ([view respondsToSelector:@selector(resetView)])
2175 [(id) view resetView];
2176 [transition_ transition:0 toView:view];
2179 - (void) view:(UIView *)view didSetFrame:(CGRect)frame {
2180 [scroller_ setContentSize:frame.size];
2183 - (void) view:(UIView *)view didDrawInRect:(CGRect)rect duration:(float)duration {
2184 [scroller_ setContentSize:[webview_ bounds].size];
2187 - (void) applicationDidFinishLaunching:(id)unused {
2188 _assert(pkgInitConfig(*_config));
2189 _assert(pkgInitSystem(*_config, _system));
2194 CGRect screenrect = [UIHardware fullScreenApplicationContentRect];
2195 window_ = [[UIWindow alloc] initWithContentRect:screenrect];
2197 [window_ orderFront: self];
2198 [window_ makeKey: self];
2199 [window_ _setHidden: NO];
2201 progress_ = [[ProgressView alloc] initWithFrame:[window_ bounds] delegate:self];
2202 [window_ setContentView:progress_];
2204 underlay_ = [[UIView alloc] initWithFrame:[progress_ bounds]];
2205 [progress_ setContentView:underlay_];
2207 overlay_ = [[UIView alloc] initWithFrame:[underlay_ bounds]];
2208 [underlay_ addSubview:overlay_];
2210 transition_ = [[UITransitionView alloc] initWithFrame:CGRectMake(
2211 0, 0, screenrect.size.width, screenrect.size.height - 48
2214 [overlay_ addSubview:transition_];
2216 featured_ = [[UIView alloc] initWithFrame:[transition_ bounds]];
2218 CGSize navsize = [UINavigationBar defaultSize];
2219 CGRect navrect = {{0, 0}, navsize};
2221 navbar_ = [[UINavigationBar alloc] initWithFrame:navrect];
2222 [featured_ addSubview:navbar_];
2224 [navbar_ setBarStyle:1];
2225 [navbar_ setDelegate:self];
2227 [navbar_ showButtonsWithLeftTitle:@"About" rightTitle:@"Reload"];
2229 UINavigationItem *navitem = [[UINavigationItem alloc] initWithTitle:@"Featured"];
2230 [navbar_ pushNavigationItem:navitem];
2232 struct CGRect subbounds = [featured_ bounds];
2233 subbounds.origin.y += navsize.height;
2234 subbounds.size.height -= navsize.height;
2236 UIImageView *pinstripe = [[UIImageView alloc] initWithFrame:subbounds];
2237 [pinstripe setImage:[UIImage applicationImageNamed:@"pinstripe.png"]];
2238 [featured_ addSubview:pinstripe];
2240 scroller_ = [[UIScroller alloc] initWithFrame:subbounds];
2241 [featured_ addSubview:scroller_];
2243 [scroller_ setScrollingEnabled:YES];
2244 [scroller_ setAdjustForContentSizeChange:YES];
2245 [scroller_ setClipsSubviews:YES];
2246 [scroller_ setAllowsRubberBanding:YES];
2247 [scroller_ setScrollDecelerationFactor:0.99];
2248 [scroller_ setDelegate:self];
2250 webview_ = [[UIWebView alloc] initWithFrame:[scroller_ bounds]];
2251 [scroller_ addSubview:webview_];
2253 [webview_ setTilingEnabled:YES];
2254 [webview_ setTileSize:CGSizeMake(screenrect.size.width, 500)];
2255 [webview_ setAutoresizes:YES];
2256 [webview_ setDelegate:self];
2258 NSArray *buttonitems = [NSArray arrayWithObjects:
2259 [NSDictionary dictionaryWithObjectsAndKeys:
2260 @"buttonBarItemTapped:", kUIButtonBarButtonAction,
2261 @"featured-up.png", kUIButtonBarButtonInfo,
2262 @"featured-dn.png", kUIButtonBarButtonSelectedInfo,
2263 [NSNumber numberWithInt:1], kUIButtonBarButtonTag,
2264 self, kUIButtonBarButtonTarget,
2265 @"Featured", kUIButtonBarButtonTitle,
2266 @"0", kUIButtonBarButtonType,
2269 [NSDictionary dictionaryWithObjectsAndKeys:
2270 @"buttonBarItemTapped:", kUIButtonBarButtonAction,
2271 @"install-up.png", kUIButtonBarButtonInfo,
2272 @"install-dn.png", kUIButtonBarButtonSelectedInfo,
2273 [NSNumber numberWithInt:2], kUIButtonBarButtonTag,
2274 self, kUIButtonBarButtonTarget,
2275 @"Install", kUIButtonBarButtonTitle,
2276 @"0", kUIButtonBarButtonType,
2279 [NSDictionary dictionaryWithObjectsAndKeys:
2280 @"buttonBarItemTapped:", kUIButtonBarButtonAction,
2281 @"upgrade-up.png", kUIButtonBarButtonInfo,
2282 @"upgrade-dn.png", kUIButtonBarButtonSelectedInfo,
2283 [NSNumber numberWithInt:3], kUIButtonBarButtonTag,
2284 self, kUIButtonBarButtonTarget,
2285 @"Upgrade", kUIButtonBarButtonTitle,
2286 @"0", kUIButtonBarButtonType,
2289 [NSDictionary dictionaryWithObjectsAndKeys:
2290 @"buttonBarItemTapped:", kUIButtonBarButtonAction,
2291 @"uninstall-up.png", kUIButtonBarButtonInfo,
2292 @"uninstall-dn.png", kUIButtonBarButtonSelectedInfo,
2293 [NSNumber numberWithInt:4], kUIButtonBarButtonTag,
2294 self, kUIButtonBarButtonTarget,
2295 @"Uninstall", kUIButtonBarButtonTitle,
2296 @"0", kUIButtonBarButtonType,
2299 [NSDictionary dictionaryWithObjectsAndKeys:
2300 @"buttonBarItemTapped:", kUIButtonBarButtonAction,
2301 @"sources-up.png", kUIButtonBarButtonInfo,
2302 @"sources-dn.png", kUIButtonBarButtonSelectedInfo,
2303 [NSNumber numberWithInt:5], kUIButtonBarButtonTag,
2304 self, kUIButtonBarButtonTarget,
2305 @"Sources", kUIButtonBarButtonTitle,
2306 @"0", kUIButtonBarButtonType,
2310 buttonbar_ = [[UIButtonBar alloc]
2312 withFrame:CGRectMake(
2313 0, screenrect.size.height - 48,
2314 screenrect.size.width, 48
2316 withItemList:buttonitems
2319 [buttonbar_ setDelegate:self];
2320 [buttonbar_ setBarStyle:1];
2321 [buttonbar_ setButtonBarTrackingMode:2];
2323 int buttons[5] = {1, 2, 3, 4, 5};
2324 [buttonbar_ registerButtonGroup:0 withButtons:buttons withCount:5];
2325 [buttonbar_ showButtonGroup:0 withDuration:0];
2327 for (int i = 0; i != 5; ++i)
2328 [[buttonbar_ viewWithTag:(i + 1)] setFrame:CGRectMake(
2329 i * 64 + 2, 1, 60, 48
2332 [buttonbar_ showSelectionForButton:1];
2333 [transition_ transition:0 toView:featured_];
2335 [overlay_ addSubview:buttonbar_];
2337 database_ = [[Database alloc] init];
2338 [database_ setDelegate:progress_];
2340 install_ = [[InstallView alloc] initWithFrame:[transition_ bounds] database:database_];
2341 [install_ setDelegate:self];
2343 upgrade_ = [[UpgradeView alloc] initWithFrame:[transition_ bounds] database:database_];
2344 [upgrade_ setDelegate:self];
2346 uninstall_ = [[UninstallView alloc] initWithFrame:[transition_ bounds] database:database_];
2347 [uninstall_ setDelegate:self];
2349 sources_ = [[SourcesView alloc] initWithFrame:[transition_ bounds] database:database_];
2350 [sources_ setDelegate:self];
2354 UIAlertSheet *alert = [[UIAlertSheet alloc]
2355 initWithTitle:@"Alert Title"
2356 buttons:[NSArray arrayWithObjects:@"Yes", nil]
2357 defaultButtonIndex:0
2362 NSLog(@"%p\n", [alert table]);
2363 [[alert table] setDelegate:self];
2364 [[alert table] reloadData];
2366 [alert addTextFieldWithValue:@"Title" label:@"Label"];
2367 [alert setShowsOverSpringBoardAlerts:YES];
2368 [alert setBodyText:@"This is an alert."];
2369 [alert presentSheetFromButtonBar:buttonbar_];
2370 //[alert popupAlertAnimated:YES];
2374 [self reloadData:NO];
2375 [progress_ resetView];
2377 Package *package([database_ packageWithName:@"cydia"]);
2378 NSString *application = package == nil ? @"Cydia" : [NSString stringWithFormat:@"Cydia/%@", [package installed]];
2379 WebView *webview = [webview_ webView];
2380 [webview setApplicationNameForUserAgent:application];
2382 url_ = [NSURL URLWithString:@"http://cydia.saurik.com/"];
2388 int main(int argc, char *argv[]) {
2389 NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
2392 sysctlbyname("hw.machine", NULL, &size, NULL, 0);
2393 char *machine = new char[size];
2394 sysctlbyname("hw.machine", machine, &size, NULL, 0);
2397 if (CFMutableDictionaryRef dict = IOServiceMatching("IOPlatformExpertDevice"))
2398 if (io_service_t service = IOServiceGetMatchingService(kIOMasterPortDefault, dict)) {
2399 if (CFTypeRef serial = IORegistryEntryCreateCFProperty(service, CFSTR(kIOPlatformSerialNumberKey), kCFAllocatorDefault, 0)) {
2400 SerialNumber_ = strdup(CFStringGetCStringPtr((CFStringRef) serial, CFStringGetSystemEncoding()));
2404 IOObjectRelease(service);
2407 UIApplicationMain(argc, argv, [Cydia class]);