]> git.saurik.com Git - cydia.git/blob - Cydia.mm
Checkpointing working memory implementation.
[cydia.git] / Cydia.mm
1 /* #include Directives {{{ */
2 #include <UIKit/UIKit.h>
3 #import <GraphicsServices/GraphicsServices.h>
4
5 #include <sstream>
6 #include <ext/stdio_filebuf.h>
7
8 #include <apt-pkg/acquire.h>
9 #include <apt-pkg/acquire-item.h>
10 #include <apt-pkg/algorithms.h>
11 #include <apt-pkg/cachefile.h>
12 #include <apt-pkg/configuration.h>
13 #include <apt-pkg/error.h>
14 #include <apt-pkg/init.h>
15 #include <apt-pkg/pkgrecords.h>
16 #include <apt-pkg/sourcelist.h>
17 #include <apt-pkg/sptr.h>
18
19 #include <errno.h>
20 #include <pcre.h>
21 #include <string.h>
22 /* }}} */
23 /* Extension Keywords {{{ */
24 #define _trace() fprintf(stderr, "_trace()@%s:%u[%s]\n", __FILE__, __LINE__, __FUNCTION__)
25
26 #define _assert(test) do \
27 if (!(test)) { \
28 fprintf(stderr, "_assert(%d:%s)@%s:%u[%s]\n", errno, #test, __FILE__, __LINE__, __FUNCTION__); \
29 exit(-1); \
30 } \
31 while (false)
32 /* }}} */
33
34 @protocol ProgressDelegate
35 - (void) setError:(NSString *)error;
36 - (void) setTitle:(NSString *)title;
37 - (void) setPercent:(float)percent;
38 - (void) addOutput:(NSString *)output;
39 @end
40
41 /* Status Delegation {{{ */
42 class Status :
43 public pkgAcquireStatus
44 {
45 private:
46 id delegate_;
47
48 public:
49 Status() :
50 delegate_(nil)
51 {
52 }
53
54 void setDelegate(id delegate) {
55 delegate_ = delegate;
56 }
57
58 virtual bool MediaChange(std::string media, std::string drive) {
59 return false;
60 }
61
62 virtual void IMSHit(pkgAcquire::ItemDesc &item) {
63 [delegate_ performSelectorOnMainThread:@selector(setStatusIMSHit) withObject:nil waitUntilDone:YES];
64 }
65
66 virtual void Fetch(pkgAcquire::ItemDesc &item) {
67 [delegate_ setTitle:[NSString stringWithCString:item.Description.c_str()]];
68 }
69
70 virtual void Done(pkgAcquire::ItemDesc &item) {
71 [delegate_ performSelectorOnMainThread:@selector(setStatusDone) withObject:nil waitUntilDone:YES];
72 }
73
74 virtual void Fail(pkgAcquire::ItemDesc &item) {
75 [delegate_ performSelectorOnMainThread:@selector(setStatusFail) withObject:nil waitUntilDone:YES];
76 }
77
78 virtual bool Pulse(pkgAcquire *Owner) {
79 bool value = pkgAcquireStatus::Pulse(Owner);
80
81 float percent(
82 double(CurrentBytes + CurrentItems) /
83 double(TotalBytes + TotalItems)
84 );
85
86 [delegate_ setPercent:percent];
87 return value;
88 }
89
90 virtual void Start() {
91 }
92
93 virtual void Stop() {
94 }
95 };
96 /* }}} */
97 /* Progress Delegation {{{ */
98 class Progress :
99 public OpProgress
100 {
101 private:
102 id delegate_;
103
104 protected:
105 virtual void Update() {
106 [delegate_ setTitle:[NSString stringWithCString:Op.c_str()]];
107 [delegate_ setPercent:(Percent / 100)];
108 }
109
110 public:
111 Progress() :
112 delegate_(nil)
113 {
114 }
115
116 void setDelegate(id delegate) {
117 delegate_ = delegate;
118 }
119
120 virtual void Done() {
121 [delegate_ setPercent:1];
122 }
123 };
124 /* }}} */
125
126 /* External Constants {{{ */
127 extern NSString *kUIButtonBarButtonAction;
128 extern NSString *kUIButtonBarButtonInfo;
129 extern NSString *kUIButtonBarButtonInfoOffset;
130 extern NSString *kUIButtonBarButtonSelectedInfo;
131 extern NSString *kUIButtonBarButtonStyle;
132 extern NSString *kUIButtonBarButtonTag;
133 extern NSString *kUIButtonBarButtonTarget;
134 extern NSString *kUIButtonBarButtonTitle;
135 extern NSString *kUIButtonBarButtonTitleVerticalHeight;
136 extern NSString *kUIButtonBarButtonTitleWidth;
137 extern NSString *kUIButtonBarButtonType;
138 /* }}} */
139 /* Mime Addresses {{{ */
140 @interface Address : NSObject {
141 NSString *name_;
142 NSString *email_;
143 }
144
145 - (void) dealloc;
146
147 - (NSString *) name;
148 - (NSString *) email;
149
150 + (Address *) addressWithString:(NSString *)string;
151 - (Address *) initWithString:(NSString *)string;
152 @end
153
154 @implementation Address
155
156 - (void) dealloc {
157 [name_ release];
158 [email_ release];
159 [super dealloc];
160 }
161
162 - (NSString *) name {
163 return name_;
164 }
165
166 - (NSString *) email {
167 return email_;
168 }
169
170 + (Address *) addressWithString:(NSString *)string {
171 return [[[Address alloc] initWithString:string] autorelease];
172 }
173
174 - (Address *) initWithString:(NSString *)string {
175 if ((self = [super init]) != nil) {
176 const char *error;
177 int offset;
178 pcre *code = pcre_compile("^\"?(.*)\"? <([^>]*)>$", 0, &error, &offset, NULL);
179
180 if (code == NULL) {
181 fprintf(stderr, "%d:%s\n", offset, error);
182 _assert(false);
183 }
184
185 pcre_extra *study = NULL;
186 int capture;
187 pcre_fullinfo(code, study, PCRE_INFO_CAPTURECOUNT, &capture);
188 int matches[(capture + 1) * 3];
189
190 size_t size = [string length];
191 const char *data = [string UTF8String];
192
193 _assert(pcre_exec(code, study, data, size, 0, 0, matches, sizeof(matches) / sizeof(matches[0])) >= 0);
194
195 name_ = [[NSString stringWithCString:(data + matches[2]) length:(matches[3] - matches[2])] retain];
196 email_ = [[NSString stringWithCString:(data + matches[4]) length:(matches[5] - matches[4])] retain];
197 } return self;
198 }
199
200 @end
201 /* }}} */
202
203 /* Right Alignment {{{ */
204 @interface UIRightTextLabel : UITextLabel {
205 float _savedRightEdgeX;
206 BOOL _sizedtofit_flag;
207 }
208
209 - (void) setFrame:(CGRect)frame;
210 - (void) setText:(NSString *)text;
211 - (void) realignText;
212 @end
213
214 @implementation UIRightTextLabel
215
216 - (void) setFrame:(CGRect)frame {
217 [super setFrame:frame];
218 if (_sizedtofit_flag == NO) {
219 _savedRightEdgeX = frame.origin.x;
220 [self realignText];
221 }
222 }
223
224 - (void) setText:(NSString *)text {
225 [super setText:text];
226 [self realignText];
227 }
228
229 - (void) realignText {
230 CGRect oldFrame = [self frame];
231
232 _sizedtofit_flag = YES;
233 [self sizeToFit]; // shrink down size so I can right align it
234
235 CGRect newFrame = [self frame];
236
237 oldFrame.origin.x = _savedRightEdgeX - newFrame.size.width;
238 oldFrame.size.width = newFrame.size.width;
239 [super setFrame:oldFrame];
240 _sizedtofit_flag = NO;
241 }
242
243 @end
244 /* }}} */
245 /* Linear Algebra {{{ */
246 inline float interpolate(float begin, float end, float fraction) {
247 return (end - begin) * fraction + begin;
248 }
249 /* }}} */
250
251 @interface Database : NSObject {
252 pkgCacheFile cache_;
253 pkgRecords *records_;
254 pkgProblemResolver *resolver_;
255
256 id delegate_;
257 Status status_;
258 Progress progress_;
259 int statusfd_;
260 }
261
262 - (Database *) init;
263 - (pkgCacheFile &) cache;
264 - (pkgRecords *) records;
265 - (pkgProblemResolver *) resolver;
266 - (void) reloadData;
267
268 - (void) perform;
269 - (void) update;
270 - (void) upgrade;
271
272 - (void) setDelegate:(id)delegate;
273 @end
274
275 /* Package Class {{{ */
276 @interface Package : NSObject {
277 pkgCache::PkgIterator iterator_;
278 Database *database_;
279 pkgRecords::Parser *parser_;
280 pkgCache::VerIterator version_;
281 pkgCache::VerFileIterator file_;
282 }
283
284 - (Package *) initWithIterator:(pkgCache::PkgIterator)iterator database:(Database *)database version:(pkgCache::VerIterator)version file:(pkgCache::VerFileIterator)file;
285 + (Package *) packageWithIterator:(pkgCache::PkgIterator)iterator database:(Database *)database;
286
287 - (NSString *) name;
288 - (NSString *) section;
289 - (BOOL) installed;
290 - (NSString *) version;
291 - (Address *) maintainer;
292 - (size_t) size;
293 - (NSString *) tagline;
294 - (NSString *) description;
295 - (NSComparisonResult) compareBySectionAndName:(Package *)package;
296
297 - (void) install;
298 - (void) remove;
299 @end
300
301 @implementation Package
302
303 - (Package *) initWithIterator:(pkgCache::PkgIterator)iterator database:(Database *)database version:(pkgCache::VerIterator)version file:(pkgCache::VerFileIterator)file {
304 if ((self = [super init]) != nil) {
305 iterator_ = iterator;
306 database_ = database;
307
308 version_ = version;
309 file_ = file;
310 parser_ = &[database_ records]->Lookup(file);
311 } return self;
312 }
313
314 + (Package *) packageWithIterator:(pkgCache::PkgIterator)iterator database:(Database *)database {
315 for (pkgCache::VerIterator version = iterator.VersionList(); !version.end(); ++version)
316 for (pkgCache::VerFileIterator file = version.FileList(); !file.end(); ++file)
317 return [[[Package alloc]
318 initWithIterator:iterator
319 database:database
320 version:version
321 file:file]
322 autorelease];
323 return nil;
324 }
325
326 - (NSString *) name {
327 return [NSString stringWithCString:iterator_.Name()];
328 }
329
330 - (NSString *) section {
331 return [NSString stringWithCString:iterator_.Section()];
332 }
333
334 - (BOOL) installed {
335 return iterator_->CurrentState != pkgCache::State::NotInstalled;
336 }
337
338 - (NSString *) version {
339 return [NSString stringWithCString:version_.VerStr()];
340 }
341
342 - (Address *) maintainer {
343 return [Address addressWithString:[NSString stringWithCString:parser_->Maintainer().c_str()]];
344 }
345
346 - (size_t) size {
347 return version_->InstalledSize;
348 }
349
350 - (NSString *) tagline {
351 return [NSString stringWithCString:parser_->ShortDesc().c_str()];
352 }
353
354 - (NSString *) description {
355 return [NSString stringWithCString:parser_->LongDesc().c_str()];
356 }
357
358 - (NSComparisonResult) compareBySectionAndName:(Package *)package {
359 NSComparisonResult result = [[self section] compare:[package section]];
360 if (result != NSOrderedSame)
361 return result;
362 return [[self name] compare:[package name]];
363 }
364
365 - (void) install {
366 pkgProblemResolver *resolver = [database_ resolver];
367 resolver->Clear(iterator_);
368 resolver->Protect(iterator_);
369 [database_ cache]->MarkInstall(iterator_, false);
370 }
371
372 - (void) remove {
373 pkgProblemResolver *resolver = [database_ resolver];
374 resolver->Clear(iterator_);
375 resolver->Protect(iterator_);
376 resolver->Remove(iterator_);
377 [database_ cache]->MarkDelete(iterator_, true);
378 }
379
380 @end
381 /* }}} */
382 /* Section Class {{{ */
383 @interface Section : NSObject {
384 NSString *name_;
385 size_t row_;
386 NSMutableArray *packages_;
387 }
388
389 - (void) dealloc;
390
391 - (Section *) initWithName:(NSString *)name row:(size_t)row;
392 - (NSString *) name;
393 - (size_t) row;
394 - (void) addPackage:(Package *)package;
395 @end
396
397 @implementation Section
398
399 - (void) dealloc {
400 [name_ release];
401 [packages_ release];
402 [super dealloc];
403 }
404
405 - (Section *) initWithName:(NSString *)name row:(size_t)row {
406 if ((self = [super init]) != nil) {
407 name_ = [name retain];
408 row_ = row;
409 packages_ = [[NSMutableArray arrayWithCapacity:16] retain];
410 } return self;
411 }
412
413 - (NSString *) name {
414 return name_;
415 }
416
417 - (size_t) row {
418 return row_;
419 }
420
421 - (void) addPackage:(Package *)package {
422 [packages_ addObject:package];
423 }
424
425 @end
426 /* }}} */
427
428 /* Confirmation View {{{ */
429 @interface ConfirmationView : UIView {
430 }
431
432 @end
433
434 @implementation ConfirmationView
435 @end
436 /* }}} */
437 /* Package View {{{ */
438 @interface PackageView : UIPreferencesTable {
439 Package *package_;
440 Database *database_;
441 NSMutableArray *cells_;
442 }
443
444 - (void) dealloc;
445
446 - (int) numberOfGroupsInPreferencesTable:(UIPreferencesTable *)table;
447 - (int) preferencesTable:(UIPreferencesTable *)table numberOfRowsInGroup:(int)group;
448 - (UIPreferencesTableCell *) preferencesTable:(UIPreferencesTable *)table cellForRow:(int)row inGroup:(int)group;
449
450 - (PackageView *) initWithFrame:(struct CGRect)frame database:(Database *)database;
451 - (void) setPackage:(Package *)package;
452 @end
453
454 @implementation PackageView
455
456 - (void) dealloc {
457 if (package_ != nil)
458 [package_ release];
459 [database_ release];
460 [cells_ release];
461 [super dealloc];
462 }
463
464 - (int) numberOfGroupsInPreferencesTable:(UIPreferencesTable *)table {
465 return 2;
466 }
467
468 - (NSString *) preferencesTable:(UIPreferencesTable *)table titleForGroup:(int)group {
469 switch (group) {
470 case 0:
471 return @"Specifics";
472 break;
473
474 case 1:
475 return @"Description";
476 break;
477
478 default: _assert(false);
479 }
480 }
481
482 - (int) preferencesTable:(UIPreferencesTable *)table numberOfRowsInGroup:(int)group {
483 switch (group) {
484 case 0:
485 return 5;
486 break;
487
488 case 1:
489 return 1;
490 break;
491
492 default: _assert(false);
493 }
494 }
495
496 - (UIPreferencesTableCell *) preferencesTable:(UIPreferencesTable *)table cellForRow:(int)row inGroup:(int)group {
497 UIPreferencesTableCell *cell;
498
499 switch (group) {
500 case 0: switch (row) {
501 case 0:
502 cell = [cells_ objectAtIndex:0];
503 [cell setTitle:@"Name"];
504 [cell setValue:[package_ name]];
505 break;
506
507 case 1:
508 cell = [cells_ objectAtIndex:1];
509 [cell setTitle:@"Version"];
510 [cell setValue:[package_ version]];
511 break;
512
513 case 2:
514 cell = [cells_ objectAtIndex:2];
515 [cell setTitle:@"Section"];
516 [cell setValue:[package_ section]];
517 break;
518
519 case 3: {
520 double size = [package_ size];
521 unsigned power = 0;
522 while (size > 1024) {
523 size /= 1024;
524 ++power;
525 }
526
527 cell = [cells_ objectAtIndex:3];
528 [cell setTitle:@"Size"];
529 [cell setValue:[NSString stringWithFormat:@"%.1f%c", size, "bkMG"[power]]];
530 } break;
531
532 case 4:
533 cell = [cells_ objectAtIndex:4];
534 [cell setTitle:@"Maintainer"];
535 [cell setValue:[[package_ maintainer] name]];
536 [cell setShowDisclosure:YES];
537 [cell setShowSelection:YES];
538 break;
539
540 default: _assert(false);
541 } break;
542
543 case 1: switch (row) {
544 case 0:
545 cell = [cells_ objectAtIndex:5];
546 [cell setTitle:nil];
547 [cell setValue:[package_ tagline]];
548 break;
549
550 case 1:
551 cell = [cells_ objectAtIndex:6];
552 [cell setTitle:@"Description"];
553 [cell setValue:[package_ description]];
554 break;
555 } break;
556
557 default: _assert(false);
558 }
559
560 return cell;
561 }
562
563 - (PackageView *) initWithFrame:(struct CGRect)frame database:(Database *)database {
564 if ((self = [super initWithFrame:frame]) != nil) {
565 database_ = [database retain];
566 [self setDataSource:self];
567
568 cells_ = [[NSMutableArray arrayWithCapacity:16] retain];
569
570 for (unsigned i = 0; i != 6; ++i) {
571 struct CGRect frame = [self frameOfPreferencesCellAtRow:0 inGroup:0];
572 UIPreferencesTableCell *cell = [[[UIPreferencesTableCell alloc] init] autorelease];
573 [cell setShowSelection:NO];
574 [cells_ addObject:cell];
575 }
576 } return self;
577 }
578
579 - (void) setPackage:(Package *)package {
580 package_ = [package retain];
581 [self reloadData];
582 }
583
584 @end
585 /* }}} */
586 /* Package Cell {{{ */
587 @interface PackageCell : UITableCell {
588 UITextLabel *name_;
589 UIRightTextLabel *version_;
590 UITextLabel *description_;
591 }
592
593 - (void) dealloc;
594
595 - (PackageCell *) initWithPackage:(Package *)package;
596
597 - (void) _setSelected:(float)fraction;
598 - (void) setSelected:(BOOL)selected;
599 - (void) setSelected:(BOOL)selected withFade:(BOOL)fade;
600 - (void) _setSelectionFadeFraction:(float)fraction;
601
602 @end
603
604 @implementation PackageCell
605
606 - (void) dealloc {
607 [name_ release];
608 [version_ release];
609 [description_ release];
610 [super dealloc];
611 }
612
613 - (PackageCell *) initWithPackage:(Package *)package {
614 if ((self = [super init]) != nil) {
615 GSFontRef bold = GSFontCreateWithName("Helvetica", kGSFontTraitBold, 22);
616 GSFontRef large = GSFontCreateWithName("Helvetica", kGSFontTraitNone, 16);
617 GSFontRef small = GSFontCreateWithName("Helvetica", kGSFontTraitNone, 14);
618
619 CGColorSpaceRef space = CGColorSpaceCreateDeviceRGB();
620 float clear[] = {0, 0, 0, 0};
621
622 name_ = [[UITextLabel alloc] initWithFrame:CGRectMake(12, 7, 250, 25)];
623 [name_ setText:[package name]];
624 [name_ setBackgroundColor:CGColorCreate(space, clear)];
625 [name_ setFont:bold];
626
627 version_ = [[UIRightTextLabel alloc] initWithFrame:CGRectMake(290, 7, 70, 25)];
628 [version_ setText:[package version]];
629 [version_ setBackgroundColor:CGColorCreate(space, clear)];
630 [version_ setFont:large];
631
632 description_ = [[UITextLabel alloc] initWithFrame:CGRectMake(13, 35, 315, 20)];
633 [description_ setText:[package tagline]];
634 [description_ setBackgroundColor:CGColorCreate(space, clear)];
635 [description_ setFont:small];
636
637 [self addSubview:name_];
638 [self addSubview:version_];
639 [self addSubview:description_];
640
641 CFRelease(small);
642 CFRelease(large);
643 CFRelease(bold);
644 } return self;
645 }
646
647 - (void) _setSelected:(float)fraction {
648 CGColorSpaceRef space = CGColorSpaceCreateDeviceRGB();
649
650 float black[] = {
651 interpolate(0.0, 1.0, fraction),
652 interpolate(0.0, 1.0, fraction),
653 interpolate(0.0, 1.0, fraction),
654 1.0};
655
656 float blue[] = {
657 interpolate(0.2, 1.0, fraction),
658 interpolate(0.2, 1.0, fraction),
659 interpolate(1.0, 1.0, fraction),
660 1.0};
661
662 float gray[] = {
663 interpolate(0.4, 1.0, fraction),
664 interpolate(0.4, 1.0, fraction),
665 interpolate(0.4, 1.0, fraction),
666 1.0};
667
668 [name_ setColor:CGColorCreate(space, black)];
669 [version_ setColor:CGColorCreate(space, blue)];
670 [description_ setColor:CGColorCreate(space, gray)];
671 }
672
673 - (void) setSelected:(BOOL)selected {
674 [self _setSelected:(selected ? 1.0 : 0.0)];
675 [super setSelected:selected];
676 }
677
678 - (void) setSelected:(BOOL)selected withFade:(BOOL)fade {
679 if (!fade)
680 [self _setSelected:(selected ? 1.0 : 0.0)];
681 [super setSelected:selected withFade:fade];
682 }
683
684 - (void) _setSelectionFadeFraction:(float)fraction {
685 [self _setSelected:fraction];
686 [super _setSelectionFadeFraction:fraction];
687 }
688
689 @end
690 /* }}} */
691
692 @implementation Database
693
694 - (void) _readStatus:(NSNumber *)fd {
695 NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
696
697 __gnu_cxx::stdio_filebuf<char> ib([fd intValue], std::ios::in);
698 std::istream is(&ib);
699 std::string line;
700
701 const char *error;
702 int offset;
703 pcre *code = pcre_compile("^([^:]*):([^:]*):([^:]*):(.*)$", 0, &error, &offset, NULL);
704
705 pcre_extra *study = NULL;
706 int capture;
707 pcre_fullinfo(code, study, PCRE_INFO_CAPTURECOUNT, &capture);
708 int matches[(capture + 1) * 3];
709
710 while (std::getline(is, line)) {
711 const char *data(line.c_str());
712 fprintf(stderr, "fd(%s)\n", data);
713
714 _assert(pcre_exec(code, study, data, line.size(), 0, 0, matches, sizeof(matches) / sizeof(matches[0])) >= 0);
715
716 std::string type(line.substr(matches[2], matches[3] - matches[2]));
717
718 std::istringstream buffer(line.substr(matches[6], matches[7] - matches[6]));
719 float percent;
720 buffer >> percent;
721 [delegate_ setPercent:(percent / 100)];
722
723 NSString *string = [NSString stringWithCString:(data + matches[8]) length:(matches[9] - matches[8])];
724
725 if (type == "pmerror")
726 [delegate_ setError:string];
727 else if (type == "pmstatus")
728 [delegate_ setTitle:string];
729 }
730
731 [pool release];
732 }
733
734 - (void) _readOutput:(NSNumber *)fd {
735 NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
736
737 __gnu_cxx::stdio_filebuf<char> ib([fd intValue], std::ios::in);
738 std::istream is(&ib);
739 std::string line;
740
741 while (std::getline(is, line))
742 [delegate_ addOutput:[NSString stringWithCString:line.c_str()]];
743
744 [pool release];
745 }
746
747 - (Database *) init {
748 if ((self = [super init]) != nil) {
749 records_ = NULL;
750 resolver_ = NULL;
751
752 int fds[2];
753
754 _assert(pipe(fds) != -1);
755 printf("%d %d\n", fds[0], fds[1]);
756 statusfd_ = fds[1];
757
758 [NSThread
759 detachNewThreadSelector:@selector(_readStatus:)
760 toTarget:self
761 withObject:[[NSNumber numberWithInt:fds[0]] retain]
762 ];
763
764 _assert(pipe(fds) != -1);
765 printf("%d %d\n", fds[0], fds[1]);
766 _assert(dup2(fds[1], 1) != -1);
767 _assert(close(fds[1]) != -1);
768
769 [NSThread
770 detachNewThreadSelector:@selector(_readOutput:)
771 toTarget:self
772 withObject:[[NSNumber numberWithInt:fds[0]] retain]
773 ];
774 } return self;
775 }
776
777 - (pkgCacheFile &) cache {
778 return cache_;
779 }
780
781 - (pkgRecords *) records {
782 return records_;
783 }
784
785 - (pkgProblemResolver *) resolver {
786 return resolver_;
787 }
788
789 - (void) reloadData {
790 _trace();
791 _error->Discard();
792 _trace();
793 delete resolver_;
794 _trace();
795 delete records_;
796 _trace();
797 cache_.Close();
798 _trace();
799 cache_.Open(progress_, true);
800 _trace();
801 records_ = new pkgRecords(cache_);
802 _trace();
803 resolver_ = new pkgProblemResolver(cache_);
804 _trace();
805 }
806
807 - (void) perform {
808 _trace();
809 pkgRecords records(cache_);
810
811 _trace();
812 FileFd lock;
813 lock.Fd(GetLock(_config->FindDir("Dir::Cache::Archives") + "lock"));
814 _assert(!_error->PendingError());
815
816 _trace();
817 pkgAcquire fetcher(&status_);
818 pkgSourceList list;
819 _assert(list.ReadMainList());
820
821 _trace();
822 SPtr<pkgPackageManager> manager(_system->CreatePM(cache_));
823 _assert(manager->GetArchives(&fetcher, &list, &records));
824 _assert(!_error->PendingError());
825 _assert(fetcher.Run() != pkgAcquire::Failed);
826
827 _trace();
828 _system->UnLock();
829 pkgPackageManager::OrderResult result = manager->DoInstall(statusfd_);
830
831 if (result == pkgPackageManager::Failed)
832 return;
833 if (_error->PendingError())
834 return;
835 if (result != pkgPackageManager::Completed)
836 return;
837 }
838
839 - (void) update {
840 pkgSourceList list;
841 _assert(list.ReadMainList());
842
843 FileFd lock;
844 lock.Fd(GetLock(_config->FindDir("Dir::State::Lists") + "lock"));
845 _assert(!_error->PendingError());
846
847 pkgAcquire fetcher(&status_);
848 _assert(list.GetIndexes(&fetcher));
849 _assert(fetcher.Run() != pkgAcquire::Failed);
850
851 bool failed = false;
852 for (pkgAcquire::ItemIterator item = fetcher.ItemsBegin(); item != fetcher.ItemsEnd(); item++)
853 if ((*item)->Status != pkgAcquire::Item::StatDone) {
854 (*item)->Finished();
855 failed = true;
856 }
857
858 if (!failed && _config->FindB("APT::Get::List-Cleanup", true) == true) {
859 _assert(fetcher.Clean(_config->FindDir("Dir::State::lists")));
860 _assert(fetcher.Clean(_config->FindDir("Dir::State::lists") + "partial/"));
861 }
862 }
863
864 - (void) upgrade {
865 _assert(cache_->DelCount() == 0 && cache_->InstCount() == 0);
866 _assert(pkgApplyStatus(cache_));
867
868 if (cache_->BrokenCount() != 0) {
869 _assert(pkgFixBroken(cache_));
870 _assert(cache_->BrokenCount() == 0);
871 _assert(pkgMinimizeUpgrade(cache_));
872 }
873
874 _assert(pkgDistUpgrade(cache_));
875
876 //InstallPackages(cache_, true);
877 }
878
879 - (void) setDelegate:(id)delegate {
880 delegate_ = delegate;
881 status_.setDelegate(delegate);
882 progress_.setDelegate(delegate);
883 }
884
885 @end
886
887 /* Progress Data {{{ */
888 @interface ProgressData : NSObject {
889 SEL selector_;
890 id target_;
891 id object_;
892 }
893
894 - (ProgressData *) initWithSelector:(SEL)selector target:(id)target object:(id)object;
895
896 - (SEL) selector;
897 - (id) target;
898 - (id) object;
899 @end
900
901 @implementation ProgressData
902
903 - (ProgressData *) initWithSelector:(SEL)selector target:(id)target object:(id)object {
904 if ((self = [super init]) != nil) {
905 selector_ = selector;
906 target_ = target;
907 object_ = object;
908 } return self;
909 }
910
911 - (SEL) selector {
912 return selector_;
913 }
914
915 - (id) target {
916 return target_;
917 }
918
919 - (id) object {
920 return object_;
921 }
922
923 @end
924 /* }}} */
925 /* Progress View {{{ */
926 @interface ProgressView : UIView <
927 ProgressDelegate
928 > {
929 UIView *view_;
930 UITransitionView *transition_;
931 UIView *overlay_;
932 UINavigationBar *navbar_;
933 UIProgressBar *progress_;
934 UITextView *output_;
935 UITextLabel *status_;
936 id delegate_;
937 UIAlertSheet *alert_;
938 }
939
940 - (void) dealloc;
941
942 - (ProgressView *) initWithFrame:(struct CGRect)frame delegate:(id)delegate;
943 - (void) setContentView:(UIView *)view;
944 - (void) resetView;
945
946 - (void) alertSheet:(UIAlertSheet *)sheet buttonClicked:(int)button;
947
948 - (void) _retachThread;
949 - (void) _detachNewThreadData:(ProgressData *)data;
950 - (void) detachNewThreadSelector:(SEL)selector toTarget:(id)target withObject:(id)object;
951
952 - (void) setError:(NSString *)error;
953 - (void) _setError:(NSString *)error;
954
955 - (void) setTitle:(NSString *)title;
956 - (void) _setTitle:(NSString *)title;
957
958 - (void) setPercent:(float)percent;
959 - (void) _setPercent:(NSNumber *)percent;
960
961 - (void) addOutput:(NSString *)output;
962 - (void) _addOutput:(NSString *)output;
963
964 - (void) setStatusIMSHit;
965 - (void) setStatusDone;
966 - (void) setStatusFail;
967
968 - (void) setStatusStart;
969 - (void) setStatusStop;
970 @end
971
972 @protocol ProgressViewDelegate
973 - (void) progressViewIsComplete:(ProgressView *)sender;
974 @end
975
976 @implementation ProgressView
977
978 - (void) dealloc {
979 [view_ release];
980 [transition_ release];
981 [overlay_ release];
982 [navbar_ release];
983 [progress_ release];
984 [output_ release];
985 [status_ release];
986 [super dealloc];
987 }
988
989 - (ProgressView *) initWithFrame:(struct CGRect)frame delegate:(id)delegate {
990 if ((self = [super initWithFrame:frame]) != nil) {
991 delegate_ = delegate;
992 alert_ = nil;
993
994 transition_ = [[UITransitionView alloc] initWithFrame:[self bounds]];
995 [self addSubview:transition_];
996
997 CGColorSpaceRef space = CGColorSpaceCreateDeviceRGB();
998 float black[] = {0.0, 0.0, 0.0, 1.0};
999 float white[] = {1.0, 1.0, 1.0, 1.0};
1000 float clear[] = {0.0, 0.0, 0.0, 0.0};
1001
1002 overlay_ = [[UIView alloc] initWithFrame:[transition_ bounds]];
1003 [overlay_ setBackgroundColor:CGColorCreate(space, black)];
1004
1005 CGSize navsize = [UINavigationBar defaultSize];
1006 CGRect navrect = {{0, 0}, navsize};
1007
1008 navbar_ = [[UINavigationBar alloc] initWithFrame:navrect];
1009 [overlay_ addSubview:navbar_];
1010
1011 [navbar_ setBarStyle:1];
1012 [navbar_ setDelegate:self];
1013
1014 UINavigationItem *navitem = [[[UINavigationItem alloc] initWithTitle:@"Running..."] autorelease];
1015 [navbar_ pushNavigationItem:navitem];
1016
1017 CGRect bounds = [overlay_ bounds];
1018 CGSize prgsize = [UIProgressBar defaultSize];
1019
1020 CGRect prgrect = {{
1021 (bounds.size.width - prgsize.width) / 2,
1022 bounds.size.height - prgsize.height - 20
1023 }, prgsize};
1024
1025 progress_ = [[UIProgressBar alloc] initWithFrame:prgrect];
1026 [overlay_ addSubview:progress_];
1027
1028 status_ = [[UITextLabel alloc] initWithFrame:CGRectMake(
1029 10,
1030 bounds.size.height - prgsize.height - 50,
1031 bounds.size.width - 20,
1032 24
1033 )];
1034
1035 [status_ setColor:CGColorCreate(space, white)];
1036 [status_ setBackgroundColor:CGColorCreate(space, clear)];
1037
1038 [status_ setCentersHorizontally:YES];
1039
1040 output_ = [[UITextView alloc] initWithFrame:CGRectMake(
1041 10,
1042 navrect.size.height + 20,
1043 bounds.size.width - 20,
1044 bounds.size.height - navsize.height - 62 - navrect.size.height
1045 )];
1046
1047 //[output_ setTextFont:@"Courier New"];
1048 [output_ setTextSize:12];
1049
1050 [output_ setTextColor:CGColorCreate(space, white)];
1051 [output_ setBackgroundColor:CGColorCreate(space, clear)];
1052
1053 [output_ setMarginTop:0];
1054 [output_ setAllowsRubberBanding:YES];
1055
1056 [overlay_ addSubview:output_];
1057 [overlay_ addSubview:status_];
1058
1059 [progress_ setStyle:0];
1060 } return self;
1061 }
1062
1063 - (void) setContentView:(UIView *)view {
1064 view_ = view;
1065 }
1066
1067 - (void) resetView {
1068 [transition_ transition:6 toView:view_];
1069 _trace();
1070 }
1071
1072 - (void) alertSheet:(UIAlertSheet *)sheet buttonClicked:(int)button {
1073 [alert_ dismiss];
1074 [alert_ release];
1075 alert_ = nil;
1076 }
1077
1078 - (void) _retachThread {
1079 _trace();
1080 [delegate_ progressViewIsComplete:self];
1081 _trace();
1082 [self resetView];
1083 _trace();
1084 }
1085
1086 - (void) _detachNewThreadData:(ProgressData *)data {
1087 NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
1088
1089 _trace();
1090 [[data target] performSelector:[data selector] withObject:[data object]];
1091 _trace();
1092 [self performSelectorOnMainThread:@selector(_retachThread) withObject:nil waitUntilDone:YES];
1093 _trace();
1094
1095 [data release];
1096 [pool release];
1097 }
1098
1099 - (void) detachNewThreadSelector:(SEL)selector toTarget:(id)target withObject:(id)object {
1100 [status_ setText:nil];
1101 [output_ setText:@""];
1102 [progress_ setProgress:0];
1103
1104 [transition_ transition:6 toView:overlay_];
1105
1106 [NSThread
1107 detachNewThreadSelector:@selector(_detachNewThreadData:)
1108 toTarget:self
1109 withObject:[[ProgressData alloc]
1110 initWithSelector:selector
1111 target:target
1112 object:object
1113 ]
1114 ];
1115 }
1116
1117 - (void) setStatusIMSHit {
1118 _trace();
1119 }
1120
1121 - (void) setStatusDone {
1122 _trace();
1123 }
1124
1125 - (void) setStatusFail {
1126 _trace();
1127 }
1128
1129 - (void) setError:(NSString *)error {
1130 [self
1131 performSelectorOnMainThread:@selector(_setError:)
1132 withObject:error
1133 waitUntilDone:YES
1134 ];
1135 }
1136
1137 - (void) _setError:(NSString *)error {
1138 _assert(alert_ == nil);
1139
1140 alert_ = [[UIAlertSheet alloc]
1141 initWithTitle:@"Package Error"
1142 buttons:[NSArray arrayWithObjects:@"Okay", nil]
1143 defaultButtonIndex:0
1144 delegate:self
1145 context:self
1146 ];
1147
1148 [alert_ setBodyText:error];
1149 [alert_ popupAlertAnimated:YES];
1150 }
1151
1152 - (void) setTitle:(NSString *)title {
1153 [self
1154 performSelectorOnMainThread:@selector(_setTitle:)
1155 withObject:title
1156 waitUntilDone:YES
1157 ];
1158 }
1159
1160 - (void) _setTitle:(NSString *)title {
1161 [status_ setText:[title stringByAppendingString:@"..."]];
1162 }
1163
1164 - (void) setPercent:(float)percent {
1165 [self
1166 performSelectorOnMainThread:@selector(_setPercent:)
1167 withObject:[NSNumber numberWithFloat:percent]
1168 waitUntilDone:YES
1169 ];
1170 }
1171
1172 - (void) _setPercent:(NSNumber *)percent {
1173 [progress_ setProgress:[percent floatValue]];
1174 }
1175
1176 - (void) addOutput:(NSString *)output {
1177 [self
1178 performSelectorOnMainThread:@selector(_addOutput:)
1179 withObject:output
1180 waitUntilDone:YES
1181 ];
1182 }
1183
1184 - (void) _addOutput:(NSString *)output {
1185 [output_ setText:[NSString stringWithFormat:@"%@\n%@", [output_ text], output]];
1186 }
1187
1188 - (void) setStatusStart {
1189 _trace();
1190 }
1191
1192 - (void) setStatusStop {
1193 _trace();
1194 }
1195
1196 @end
1197 /* }}} */
1198
1199 @protocol PackagesDelegate
1200
1201 - (void) perform;
1202
1203 @end
1204
1205 @interface Packages : UIView {
1206 NSString *title_;
1207 Database *database_;
1208 bool (*filter_)(Package *package);
1209 NSMutableArray *packages_;
1210 NSMutableArray *sections_;
1211 id delegate_;
1212 UISectionList *list_;
1213 UINavigationBar *navbar_;
1214 UITransitionView *transition_;
1215 Package *package_;
1216 PackageView *pkgview_;
1217 SEL selector_;
1218 }
1219
1220 - (int) numberOfSectionsInSectionList:(UISectionList *)list;
1221 - (NSString *) sectionList:(UISectionList *)list titleForSection:(int)section;
1222 - (int) sectionList:(UISectionList *)list rowForSection:(int)section;
1223
1224 - (int) numberOfRowsInTable:(UITable *)table;
1225 - (float) table:(UITable *)table heightForRow:(int)row;
1226 - (UITableCell *) table:(UITable *)table cellForRow:(int)row column:(UITableColumn *)col;
1227 - (BOOL) table:(UITable *)table showDisclosureForRow:(int)row;
1228 - (void) tableRowSelected:(NSNotification*)notification;
1229
1230 - (void) navigationBar:(UINavigationBar *)navbar buttonClicked:(int)button;
1231 - (void) navigationBar:(UINavigationBar *)navbar poppedItem:(UINavigationItem *)item;
1232
1233 - (Packages *) initWithFrame:(struct CGRect)frame title:(NSString *)title database:(Database *)database filter:(bool (*)(Package *))filter selector:(SEL)selector;
1234 - (void) setDelegate:(id)delegate;
1235 - (void) deselect;
1236 - (void) reloadData;
1237 @end
1238
1239 @implementation Packages
1240
1241 - (int) numberOfSectionsInSectionList:(UISectionList *)list {
1242 return [sections_ count];
1243 }
1244
1245 - (NSString *) sectionList:(UISectionList *)list titleForSection:(int)section {
1246 return [[sections_ objectAtIndex:section] name];
1247 }
1248
1249 - (int) sectionList:(UISectionList *)list rowForSection:(int)section {
1250 return [[sections_ objectAtIndex:section] row];
1251 }
1252
1253 - (int) numberOfRowsInTable:(UITable *)table {
1254 return [packages_ count];
1255 }
1256
1257 - (float) table:(UITable *)table heightForRow:(int)row {
1258 return 64;
1259 }
1260
1261 - (UITableCell *) table:(UITable *)table cellForRow:(int)row column:(UITableColumn *)col {
1262 Package *package = [packages_ objectAtIndex:row];
1263 PackageCell *cell = [[[PackageCell alloc] initWithPackage:package] autorelease];
1264 return cell;
1265 }
1266
1267 - (BOOL) table:(UITable *)table showDisclosureForRow:(int)row {
1268 return YES;
1269 }
1270
1271 - (void) tableRowSelected:(NSNotification*)notification {
1272 int row = [[list_ table] selectedRow];
1273 if (row == INT_MAX)
1274 return;
1275
1276 package_ = [packages_ objectAtIndex:row];
1277
1278 UINavigationItem *navitem = [[UINavigationItem alloc] initWithTitle:[package_ name]];
1279 [navbar_ pushNavigationItem:navitem];
1280
1281 [navbar_ showButtonsWithLeftTitle:nil rightTitle:title_];
1282
1283 [pkgview_ setPackage:package_];
1284 [transition_ transition:1 toView:pkgview_];
1285 }
1286
1287 - (void) navigationBar:(UINavigationBar *)navbar buttonClicked:(int)button {
1288 if (button == 0) {
1289 [package_ performSelector:selector_];
1290
1291 pkgProblemResolver *resolver = [database_ resolver];
1292
1293 resolver->InstallProtect();
1294 if (!resolver->Resolve(true))
1295 _error->Discard();
1296
1297 [delegate_ perform];
1298 }
1299 }
1300
1301 - (void) navigationBar:(UINavigationBar *)navbar poppedItem:(UINavigationItem *)item {
1302 [self deselect];
1303 [navbar_ showButtonsWithLeftTitle:nil rightTitle:nil];
1304 }
1305
1306 - (Packages *) initWithFrame:(struct CGRect)frame title:(NSString *)title database:(Database *)database filter:(bool (*)(Package *))filter selector:(SEL)selector {
1307 if ((self = [super initWithFrame:frame]) != nil) {
1308 title_ = [title retain];
1309 database_ = [database retain];
1310 filter_ = filter;
1311 selector_ = selector;
1312
1313 struct CGRect bounds = [self bounds];
1314 CGSize navsize = [UINavigationBar defaultSize];
1315 CGRect navrect = {{0, 0}, navsize};
1316
1317 navbar_ = [[UINavigationBar alloc] initWithFrame:navrect];
1318 [self addSubview:navbar_];
1319
1320 [navbar_ setBarStyle:1];
1321 [navbar_ setDelegate:self];
1322
1323 UINavigationItem *navitem = [[[UINavigationItem alloc] initWithTitle:title] autorelease];
1324 [navbar_ pushNavigationItem:navitem];
1325 [navitem setBackButtonTitle:@"Packages"];
1326
1327 transition_ = [[UITransitionView alloc] initWithFrame:CGRectMake(
1328 bounds.origin.x, bounds.origin.y + navsize.height, bounds.size.width, bounds.size.height - navsize.height
1329 )];
1330
1331 [self addSubview:transition_];
1332
1333 list_ = [[UISectionList alloc] initWithFrame:[transition_ bounds] showSectionIndex:NO];
1334 [list_ setDataSource:self];
1335
1336 [transition_ transition:0 toView:list_];
1337
1338 UITableColumn *column = [[UITableColumn alloc]
1339 initWithTitle:@"Name"
1340 identifier:@"name"
1341 width:frame.size.width
1342 ];
1343
1344 UITable *table = [list_ table];
1345 [table setSeparatorStyle:1];
1346 [table addTableColumn:column];
1347 [table setDelegate:self];
1348
1349 pkgview_ = [[PackageView alloc] initWithFrame:[transition_ bounds] database:database_];
1350 } return self;
1351 }
1352
1353 - (void) setDelegate:(id)delegate {
1354 delegate_ = delegate;
1355 }
1356
1357 - (void) deselect {
1358 [transition_ transition:2 toView:list_];
1359 UITable *table = [list_ table];
1360 [table selectRow:-1 byExtendingSelection:NO withFade:YES];
1361 package_ = nil;
1362 }
1363
1364 - (void) reloadData {
1365 packages_ = [[NSMutableArray arrayWithCapacity:16] retain];
1366
1367 _trace();
1368 if (sections_ != nil) {
1369 [sections_ release];
1370 sections_ = nil;
1371 }
1372
1373 _trace();
1374 for (pkgCache::PkgIterator iterator = [database_ cache]->PkgBegin(); !iterator.end(); ++iterator) {
1375 Package *package = [Package packageWithIterator:iterator database:database_];
1376 if (package == nil)
1377 continue;
1378 if (filter_(package))
1379 [packages_ addObject:package];
1380 }
1381
1382 _trace();
1383 [packages_ sortUsingSelector:@selector(compareBySectionAndName:)];
1384 sections_ = [[NSMutableArray arrayWithCapacity:16] retain];
1385
1386 _trace();
1387 Section *section = nil;
1388 _trace();
1389 for (size_t offset = 0, count = [packages_ count]; offset != count; ++offset) {
1390 _trace();
1391 Package *package = [packages_ objectAtIndex:offset];
1392 _trace();
1393 NSString *name = [package section];
1394
1395 _trace();
1396 if (section == nil || ![[section name] isEqual:name]) {
1397 section = [[Section alloc] initWithName:name row:offset];
1398 [sections_ addObject:section];
1399 }
1400
1401 _trace();
1402 [section addPackage:package];
1403 _trace();
1404 }
1405
1406 _trace();
1407 [list_ reloadData];
1408 _trace();
1409 if (package_ != nil)
1410 [navbar_ popNavigationItem];
1411 _trace();
1412 }
1413
1414 @end
1415
1416 bool IsInstalled(Package *package) {
1417 return [package installed];
1418 }
1419
1420 bool IsNotInstalled(Package *package) {
1421 return ![package installed];
1422 }
1423
1424 @interface Cydia : UIApplication <
1425 PackagesDelegate,
1426 ProgressViewDelegate
1427 > {
1428 UIWindow *window_;
1429 UITransitionView *transition_;
1430 UIButtonBar *buttonbar_;
1431 UIAlertSheet *alert_;
1432
1433 Database *database_;
1434 ProgressView *progress_;
1435
1436 UIView *featured_;
1437 UINavigationBar *navbar_;
1438 UIScroller *scroller_;
1439 UIWebView *webview_;
1440 NSURL *url_;
1441
1442 Packages *install_;
1443 Packages *uninstall_;
1444 }
1445
1446 - (void) loadNews;
1447 - (void) reloadData;
1448 - (void) perform;
1449
1450 - (void) progressViewIsComplete:(ProgressView *)progress;
1451
1452 - (void) navigationBar:(UINavigationBar *)navbar buttonClicked:(int)button;
1453 - (void) alertSheet:(UIAlertSheet *)sheet buttonClicked:(int)button;
1454 - (void) buttonBarItemTapped:(id)sender;
1455
1456 - (void) view:(UIView *)sender didSetFrame:(CGRect)frame;
1457 - (void) view:(UIView *)view didDrawInRect:(CGRect)rect duration:(float)duration;
1458
1459 - (void) applicationDidFinishLaunching:(id)unused;
1460 @end
1461
1462 @implementation Cydia
1463
1464 - (void) loadNews {
1465 [webview_ loadRequest:[NSURLRequest
1466 requestWithURL:url_
1467 cachePolicy:NSURLRequestReloadIgnoringCacheData
1468 timeoutInterval:30.0
1469 ]];
1470 }
1471
1472 - (void) reloadData {
1473 _trace();
1474 [database_ reloadData];
1475 _trace();
1476 [install_ reloadData];
1477 _trace();
1478 [uninstall_ reloadData];
1479 _trace();
1480 }
1481
1482 - (void) perform {
1483 _trace();
1484 [progress_
1485 detachNewThreadSelector:@selector(perform)
1486 toTarget:database_
1487 withObject:nil
1488 ];
1489 }
1490
1491 - (void) progressViewIsComplete:(ProgressView *)progress {
1492 _trace();
1493 [self reloadData];
1494 _trace();
1495 }
1496
1497 - (void) navigationBar:(UINavigationBar *)navbar buttonClicked:(int)button {
1498 switch (button) {
1499 case 0:
1500 [self loadNews];
1501 break;
1502
1503 case 1:
1504 _assert(alert_ == nil);
1505
1506 alert_ = [[UIAlertSheet alloc]
1507 initWithTitle:@"About Cydia Packager"
1508 buttons:[NSArray arrayWithObjects:@"Close", nil]
1509 defaultButtonIndex:0
1510 delegate:self
1511 context:self
1512 ];
1513
1514 [alert_ setBodyText:
1515 @"Copyright (C) 2007\n"
1516 "Jay Freeman (saurik)\n"
1517 "saurik@saurik.com\n"
1518 "http://www.saurik.com/\n"
1519 "\n"
1520 "The Okori Group\n"
1521 "http://www.theokorigroup.com/\n"
1522 "\n"
1523 "College of Creative Studies,\n"
1524 "University of California,\n"
1525 "Santa Barbara\n"
1526 "http://www.ccs.ucsb.edu/\n"
1527 "\n"
1528 "Special Thanks:\n"
1529 "bad_, BHSPitMonkey, Cobra, core,\n"
1530 "Corona, cromas, Darken, dtzWill,\n"
1531 "francis, Godores, jerry, Kingstone,\n"
1532 "lounger, rockabilly, tman, Wbiggs"
1533 ];
1534
1535 [alert_ presentSheetFromButtonBar:buttonbar_];
1536 break;
1537 }
1538 }
1539
1540 - (void) alertSheet:(UIAlertSheet *)sheet buttonClicked:(int)button {
1541 [alert_ dismiss];
1542 [alert_ release];
1543 alert_ = nil;
1544 }
1545
1546 - (void) buttonBarItemTapped:(id)sender {
1547 UIView *view;
1548
1549 switch ([sender tag]) {
1550 case 1: view = featured_; break;
1551 case 2: view = install_; break;
1552 case 4: view = uninstall_; break;
1553
1554 default:
1555 _assert(false);
1556 }
1557
1558 [transition_ transition:0 toView:view];
1559 }
1560
1561 - (void) view:(UIView *)view didSetFrame:(CGRect)frame {
1562 [scroller_ setContentSize:frame.size];
1563 }
1564
1565 - (void) view:(UIView *)view didDrawInRect:(CGRect)rect duration:(float)duration {
1566 [scroller_ setContentSize:[webview_ bounds].size];
1567 }
1568
1569 - (void) applicationDidFinishLaunching:(id)unused {
1570 _assert(pkgInitConfig(*_config));
1571 _assert(pkgInitSystem(*_config, _system));
1572
1573 CGRect screenrect = [UIHardware fullScreenApplicationContentRect];
1574 window_ = [[UIWindow alloc] initWithContentRect:screenrect];
1575
1576 [window_ orderFront: self];
1577 [window_ makeKey: self];
1578 [window_ _setHidden: NO];
1579
1580 progress_ = [[ProgressView alloc] initWithFrame:[window_ bounds] delegate:self];
1581 [window_ setContentView:progress_];
1582
1583 UIView *view = [[UIView alloc] initWithFrame:[progress_ bounds]];
1584 [progress_ setContentView:view];
1585
1586 transition_ = [[UITransitionView alloc] initWithFrame:CGRectMake(
1587 0, 0, screenrect.size.width, screenrect.size.height - 48
1588 )];
1589
1590 [view addSubview:transition_];
1591
1592 featured_ = [[UIView alloc] initWithFrame:[transition_ bounds]];
1593
1594 CGSize navsize = [UINavigationBar defaultSize];
1595 CGRect navrect = {{0, 0}, navsize};
1596
1597 navbar_ = [[UINavigationBar alloc] initWithFrame:navrect];
1598 [featured_ addSubview:navbar_];
1599
1600 [navbar_ setBarStyle:1];
1601 [navbar_ setDelegate:self];
1602
1603 [navbar_ showButtonsWithLeftTitle:@"About" rightTitle:@"Reload"];
1604
1605 UINavigationItem *navitem = [[UINavigationItem alloc] initWithTitle:@"Featured"];
1606 [navbar_ pushNavigationItem:navitem];
1607
1608 struct CGRect subbounds = [featured_ bounds];
1609 subbounds.origin.y += navsize.height;
1610 subbounds.size.height -= navsize.height;
1611
1612 UIImageView *pinstripe = [[UIImageView alloc] initWithFrame:subbounds];
1613 [pinstripe setImage:[UIImage applicationImageNamed:@"pinstripe.png"]];
1614 [featured_ addSubview:pinstripe];
1615
1616 scroller_ = [[UIScroller alloc] initWithFrame:subbounds];
1617 [featured_ addSubview:scroller_];
1618
1619 [scroller_ setScrollingEnabled:YES];
1620 [scroller_ setAdjustForContentSizeChange:YES];
1621 [scroller_ setClipsSubviews:YES];
1622 [scroller_ setAllowsRubberBanding:YES];
1623 [scroller_ setScrollDecelerationFactor:0.99];
1624 [scroller_ setDelegate:self];
1625
1626 webview_ = [[UIWebView alloc] initWithFrame:[scroller_ bounds]];
1627 [scroller_ addSubview:webview_];
1628
1629 [webview_ setTilingEnabled:YES];
1630 [webview_ setTileSize:CGSizeMake(screenrect.size.width, 500)];
1631 [webview_ setAutoresizes:YES];
1632 [webview_ setDelegate:self];
1633
1634 url_ = [NSURL URLWithString:@"http://cydia.saurik.com/"];
1635 [self loadNews];
1636
1637 NSArray *buttonitems = [NSArray arrayWithObjects:
1638 [NSDictionary dictionaryWithObjectsAndKeys:
1639 @"buttonBarItemTapped:", kUIButtonBarButtonAction,
1640 @"featured-up.png", kUIButtonBarButtonInfo,
1641 @"featured-dn.png", kUIButtonBarButtonSelectedInfo,
1642 [NSNumber numberWithInt:1], kUIButtonBarButtonTag,
1643 self, kUIButtonBarButtonTarget,
1644 @"Featured", kUIButtonBarButtonTitle,
1645 @"0", kUIButtonBarButtonType,
1646 nil],
1647
1648 [NSDictionary dictionaryWithObjectsAndKeys:
1649 @"buttonBarItemTapped:", kUIButtonBarButtonAction,
1650 @"install-up.png", kUIButtonBarButtonInfo,
1651 @"install-dn.png", kUIButtonBarButtonSelectedInfo,
1652 [NSNumber numberWithInt:2], kUIButtonBarButtonTag,
1653 self, kUIButtonBarButtonTarget,
1654 @"Install", kUIButtonBarButtonTitle,
1655 @"0", kUIButtonBarButtonType,
1656 nil],
1657
1658 [NSDictionary dictionaryWithObjectsAndKeys:
1659 @"buttonBarItemTapped:", kUIButtonBarButtonAction,
1660 @"upgrade-up.png", kUIButtonBarButtonInfo,
1661 @"upgrade-dn.png", kUIButtonBarButtonSelectedInfo,
1662 [NSNumber numberWithInt:3], kUIButtonBarButtonTag,
1663 self, kUIButtonBarButtonTarget,
1664 @"Upgrade", kUIButtonBarButtonTitle,
1665 @"0", kUIButtonBarButtonType,
1666 nil],
1667
1668 [NSDictionary dictionaryWithObjectsAndKeys:
1669 @"buttonBarItemTapped:", kUIButtonBarButtonAction,
1670 @"uninstall-up.png", kUIButtonBarButtonInfo,
1671 @"uninstall-dn.png", kUIButtonBarButtonSelectedInfo,
1672 [NSNumber numberWithInt:4], kUIButtonBarButtonTag,
1673 self, kUIButtonBarButtonTarget,
1674 @"Uninstall", kUIButtonBarButtonTitle,
1675 @"0", kUIButtonBarButtonType,
1676 nil],
1677
1678 [NSDictionary dictionaryWithObjectsAndKeys:
1679 @"buttonBarItemTapped:", kUIButtonBarButtonAction,
1680 @"sources-up.png", kUIButtonBarButtonInfo,
1681 @"sources-dn.png", kUIButtonBarButtonSelectedInfo,
1682 [NSNumber numberWithInt:5], kUIButtonBarButtonTag,
1683 self, kUIButtonBarButtonTarget,
1684 @"Sources", kUIButtonBarButtonTitle,
1685 @"0", kUIButtonBarButtonType,
1686 nil],
1687 nil];
1688
1689 buttonbar_ = [[UIButtonBar alloc]
1690 initInView:view
1691 withFrame:CGRectMake(
1692 0, screenrect.size.height - 48,
1693 screenrect.size.width, 48
1694 )
1695 withItemList:buttonitems
1696 ];
1697
1698 [buttonbar_ setDelegate:self];
1699 [buttonbar_ setBarStyle:1];
1700 [buttonbar_ setButtonBarTrackingMode:2];
1701
1702 int buttons[5] = {1, 2, 3, 4, 5};
1703 [buttonbar_ registerButtonGroup:0 withButtons:buttons withCount:5];
1704 [buttonbar_ showButtonGroup:0 withDuration:0];
1705
1706 for (int i = 0; i != 5; ++i)
1707 [[buttonbar_ viewWithTag:(i + 1)] setFrame:CGRectMake(
1708 i * 64 + 2, 1, 60, 48
1709 )];
1710
1711 [buttonbar_ showSelectionForButton:1];
1712 [transition_ transition:0 toView:featured_];
1713
1714 [view addSubview:buttonbar_];
1715
1716 database_ = [[Database alloc] init];
1717 [database_ setDelegate:progress_];
1718
1719 install_ = [[Packages alloc] initWithFrame:[transition_ bounds] title:@"Install" database:database_ filter:&IsNotInstalled selector:@selector(install)];
1720 [install_ setDelegate:self];
1721
1722 uninstall_ = [[Packages alloc] initWithFrame:[transition_ bounds] title:@"Uninstall" database:database_ filter:&IsInstalled selector:@selector(remove)];
1723 [uninstall_ setDelegate:self];
1724
1725 #if 0
1726
1727 UIAlertSheet *alert = [[UIAlertSheet alloc]
1728 initWithTitle:@"Alert Title"
1729 buttons:[NSArray arrayWithObjects:@"Yes", nil]
1730 defaultButtonIndex:0
1731 delegate:self
1732 context:self
1733 ];
1734
1735 NSLog(@"%p\n", [alert table]);
1736 [[alert table] setDelegate:self];
1737 [[alert table] reloadData];
1738
1739 [alert addTextFieldWithValue:@"Title" label:@"Label"];
1740 [alert setShowsOverSpringBoardAlerts:YES];
1741 [alert setBodyText:@"This is an alert."];
1742 [alert presentSheetFromButtonBar:buttonbar_];
1743 //[alert popupAlertAnimated:YES];
1744
1745 #endif
1746
1747 [self reloadData];
1748 [progress_ resetView];
1749 }
1750
1751 @end
1752
1753 int main(int argc, char *argv[]) {
1754 NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
1755 UIApplicationMain(argc, argv, [Cydia class]);
1756 [pool release];
1757 }