]> git.saurik.com Git - cydia.git/blob - Cydia.mm
Terrified I might lose this code ;P.
[cydia.git] / Cydia.mm
1 /* #include Directives {{{ */
2 #include <UIKit/UIKit.h>
3 #import <GraphicsServices/GraphicsServices.h>
4
5 #include <apt-pkg/acquire.h>
6 #include <apt-pkg/acquire-item.h>
7 #include <apt-pkg/algorithms.h>
8 #include <apt-pkg/cachefile.h>
9 #include <apt-pkg/configuration.h>
10 #include <apt-pkg/error.h>
11 #include <apt-pkg/init.h>
12 #include <apt-pkg/pkgrecords.h>
13 #include <apt-pkg/sourcelist.h>
14
15 #include <pcre.h>
16 #include <string.h>
17 /* }}} */
18 /* Extension Keywords {{{ */
19 #define _trace() printf("_trace()@%s:%u[%s]\n", __FILE__, __LINE__, __FUNCTION__)
20
21 #define _assert(test) do \
22 if (!(test)) { \
23 printf("_assert(%s)@%s:%u[%s]\n", #test, __FILE__, __LINE__, __FUNCTION__); \
24 exit(-1); \
25 } \
26 while (false)
27 /* }}} */
28
29 /* Status Delegation {{{ */
30 class Status :
31 public pkgAcquireStatus
32 {
33 private:
34 id delegate_;
35
36 public:
37 Status() :
38 delegate_(nil)
39 {
40 }
41
42 void setDelegate(id delegate) {
43 delegate_ = delegate;
44 }
45
46 virtual bool MediaChange(std::string media, std::string drive) {
47 return false;
48 }
49
50 virtual void IMSHit(pkgAcquire::ItemDesc &item) {
51 [delegate_ performSelectorOnMainThread:@selector(setStatusIMSHit) withObject:nil waitUntilDone:YES];
52 }
53
54 virtual void Fetch(pkgAcquire::ItemDesc &item) {
55 [delegate_ performSelectorOnMainThread:@selector(setStatusFetch) withObject:nil waitUntilDone:YES];
56 }
57
58 virtual void Done(pkgAcquire::ItemDesc &item) {
59 [delegate_ performSelectorOnMainThread:@selector(setStatusDone) withObject:nil waitUntilDone:YES];
60 }
61
62 virtual void Fail(pkgAcquire::ItemDesc &item) {
63 [delegate_ performSelectorOnMainThread:@selector(setStatusFail) withObject:nil waitUntilDone:YES];
64 }
65
66 virtual bool Pulse(pkgAcquire *Owner) {
67 [delegate_ performSelectorOnMainThread:@selector(setStatusPulse) withObject:nil waitUntilDone:YES];
68 return true;
69 }
70
71 virtual void Start() {
72 [delegate_ performSelectorOnMainThread:@selector(setStatusStart) withObject:nil waitUntilDone:YES];
73 }
74
75 virtual void Stop() {
76 [delegate_ performSelectorOnMainThread:@selector(setStatusStop) withObject:nil waitUntilDone:YES];
77 }
78 };
79 /* }}} */
80 /* Progress Delegation {{{ */
81 class Progress :
82 public OpProgress
83 {
84 private:
85 id delegate_;
86
87 protected:
88 virtual void Update() {
89 printf("Update(): %f (%s)\n", Percent, Op.c_str());
90 }
91
92 public:
93 Progress() :
94 delegate_(nil)
95 {
96 }
97
98 void setDelegate(id delegate) {
99 delegate_ = delegate;
100 }
101
102 virtual void Done() {
103 printf("Done()\n");
104 }
105 };
106 /* }}} */
107
108 /* External Constants {{{ */
109 extern NSString *kUIButtonBarButtonAction;
110 extern NSString *kUIButtonBarButtonInfo;
111 extern NSString *kUIButtonBarButtonInfoOffset;
112 extern NSString *kUIButtonBarButtonSelectedInfo;
113 extern NSString *kUIButtonBarButtonStyle;
114 extern NSString *kUIButtonBarButtonTag;
115 extern NSString *kUIButtonBarButtonTarget;
116 extern NSString *kUIButtonBarButtonTitle;
117 extern NSString *kUIButtonBarButtonTitleVerticalHeight;
118 extern NSString *kUIButtonBarButtonTitleWidth;
119 extern NSString *kUIButtonBarButtonType;
120 /* }}} */
121 /* Mime Addresses {{{ */
122 @interface Address : NSObject {
123 NSString *name_;
124 NSString *email_;
125 }
126
127 - (NSString *) name;
128 - (NSString *) email;
129
130 + (Address *) addressWithString:(NSString *)string;
131 - (Address *) initWithString:(NSString *)string;
132 @end
133
134 @implementation Address
135
136 - (NSString *) name {
137 return name_;
138 }
139
140 - (NSString *) email {
141 return email_;
142 }
143
144 + (Address *) addressWithString:(NSString *)string {
145 return [[[Address alloc] initWithString:string] retain];
146 }
147
148 - (Address *) initWithString:(NSString *)string {
149 if ((self = [super init]) != nil) {
150 const char *error;
151 int offset;
152
153 pcre *code = pcre_compile("^\"?(.*)\"? <([^>]*)>$", 0, &error, &offset, NULL);
154
155 if (code == NULL) {
156 printf("%d:%s\n", offset, error);
157 _assert(false);
158 }
159
160 pcre_extra *study = NULL;
161 int capture;
162 pcre_fullinfo(code, study, PCRE_INFO_CAPTURECOUNT, &capture);
163
164 size_t size = [string length];
165 const char *data = [string UTF8String];
166
167 int matches[(capture + 1) * 3];
168 pcre_exec(code, study, data, size, 0, 0, matches, sizeof(matches) / sizeof(matches[0]));
169
170 name_ = [[NSString stringWithCString:(data + matches[2]) length:(matches[3] - matches[2])] retain];
171 email_ = [[NSString stringWithCString:(data + matches[4]) length:(matches[5] - matches[4])] retain];
172 } return self;
173 }
174
175 @end
176 /* }}} */
177
178 /* Right Alignment {{{ */
179 @interface UIRightTextLabel : UITextLabel {
180 float _savedRightEdgeX;
181 BOOL _sizedtofit_flag;
182 }
183
184 - (void) setFrame:(CGRect)frame;
185 - (void) setText:(NSString *)text;
186 - (void) realignText;
187 @end
188
189 @implementation UIRightTextLabel
190
191 - (void) setFrame:(CGRect)frame {
192 [super setFrame:frame];
193 if (_sizedtofit_flag == NO) {
194 _savedRightEdgeX = frame.origin.x;
195 [self realignText];
196 }
197 }
198
199 - (void) setText:(NSString *)text {
200 [super setText:text];
201 [self realignText];
202 }
203
204 - (void) realignText {
205 CGRect oldFrame = [self frame];
206
207 _sizedtofit_flag = YES;
208 [self sizeToFit]; // shrink down size so I can right align it
209
210 CGRect newFrame = [self frame];
211
212 oldFrame.origin.x = _savedRightEdgeX - newFrame.size.width;
213 oldFrame.size.width = newFrame.size.width;
214 [super setFrame:oldFrame];
215 _sizedtofit_flag = NO;
216 }
217
218 @end
219 /* }}} */
220
221 @interface Database : NSObject {
222 pkgCacheFile cache_;
223 pkgRecords *records_;
224 pkgProblemResolver *resolver_;
225
226 Status status_;
227 Progress progress_;
228 }
229
230 - (Database *) init;
231 - (pkgCacheFile &) cache;
232 - (pkgRecords *) records;
233 - (pkgProblemResolver *) resolver;
234 - (void) reloadData;
235 - (void) update;
236 - (void) upgrade;
237 - (void) setDelegate:(id)delegate;
238 @end
239
240 /* Package Class {{{ */
241 @interface Package : NSObject {
242 pkgCache::PkgIterator iterator_;
243 Database *database_;
244 UITableCell *cell_;
245 pkgRecords::Parser *parser_;
246 pkgCache::VerIterator version_;
247 pkgCache::VerFileIterator file_;
248 }
249
250 - (Package *) initWithIterator:(pkgCache::PkgIterator)iterator database:(Database *)database version:(pkgCache::VerIterator)version file:(pkgCache::VerFileIterator)file;
251 + (Package *) packageWithIterator:(pkgCache::PkgIterator)iterator database:(Database *)database;
252
253 - (NSString *) name;
254 - (NSString *) section;
255 - (BOOL) installed;
256 - (NSString *) version;
257 - (Address *) maintainer;
258 - (size_t) size;
259 - (NSString *) tagline;
260 - (NSString *) description;
261 - (UITableCell *) cell;
262 - (void) setCell:(UITableCell *)cell;
263 - (NSComparisonResult) compareBySectionAndName:(Package *)package;
264
265 - (void) install;
266 - (void) remove;
267 @end
268
269 @implementation Package
270
271 - (Package *) initWithIterator:(pkgCache::PkgIterator)iterator database:(Database *)database version:(pkgCache::VerIterator)version file:(pkgCache::VerFileIterator)file {
272 if ((self = [super init]) != nil) {
273 iterator_ = iterator;
274 database_ = database;
275 cell_ = nil;
276
277 version_ = version;
278 file_ = file;
279 parser_ = &[database_ records]->Lookup(file);
280 } return self;
281 }
282
283 + (Package *) packageWithIterator:(pkgCache::PkgIterator)iterator database:(Database *)database {
284 for (pkgCache::VerIterator version = iterator.VersionList(); !version.end(); ++version)
285 for (pkgCache::VerFileIterator file = version.FileList(); !file.end(); ++file)
286 return [[Package alloc] initWithIterator:iterator database:database version:version file:file];
287 return nil;
288 }
289
290 - (NSString *) name {
291 return [NSString stringWithCString:iterator_.Name()];
292 }
293
294 - (NSString *) section {
295 return [NSString stringWithCString:iterator_.Section()];
296 }
297
298 - (BOOL) installed {
299 return iterator_->CurrentState != pkgCache::State::NotInstalled;
300 }
301
302 - (NSString *) version {
303 return [NSString stringWithCString:version_.VerStr()];
304 }
305
306 - (Address *) maintainer {
307 return [Address addressWithString:[NSString stringWithCString:parser_->Maintainer().c_str()]];
308 }
309
310 - (size_t) size {
311 return version_->InstalledSize;
312 }
313
314 - (NSString *) tagline {
315 return [NSString stringWithCString:parser_->ShortDesc().c_str()];
316 }
317
318 - (NSString *) description {
319 return [NSString stringWithCString:parser_->LongDesc().c_str()];
320 }
321
322 - (UITableCell *) cell {
323 return cell_;
324 }
325
326 - (void) setCell:(UITableCell *)cell {
327 cell_ = cell;
328 }
329
330 - (NSComparisonResult) compareBySectionAndName:(Package *)package {
331 NSComparisonResult result = [[self section] compare:[package section]];
332 if (result != NSOrderedSame)
333 return result;
334 return [[self name] compare:[package name]];
335 }
336
337 - (void) install {
338 pkgProblemResolver *resolver = [database_ resolver];
339 resolver->Clear(iterator_);
340 resolver->Protect(iterator_);
341 [database_ cache]->MarkInstall(iterator_, false);
342 }
343
344 - (void) remove {
345 pkgProblemResolver *resolver = [database_ resolver];
346 resolver->Clear(iterator_);
347 resolver->Protect(iterator_);
348 resolver->Remove(iterator_);
349 [database_ cache]->MarkDelete(iterator_, false);
350 }
351
352 @end
353 /* }}} */
354 /* Section Class {{{ */
355 @interface Section : NSObject {
356 NSString *name_;
357 size_t row_;
358 NSMutableArray *packages_;
359 }
360
361 - (Section *) initWithName:(NSString *)name row:(size_t)row;
362 - (NSString *) name;
363 - (size_t) row;
364 - (void) addPackage:(Package *)package;
365 @end
366
367 @implementation Section
368
369 - (Section *) initWithName:(NSString *)name row:(size_t)row {
370 if ((self = [super init]) != nil) {
371 name_ = [name retain];
372 row_ = row;
373 packages_ = [[NSMutableArray arrayWithCapacity:16] retain];
374 } return self;
375 }
376
377 - (NSString *) name {
378 return name_;
379 }
380
381 - (size_t) row {
382 return row_;
383 }
384
385 - (void) addPackage:(Package *)package {
386 [packages_ addObject:package];
387 }
388
389 @end
390 /* }}} */
391
392 /* Confirmation View {{{ */
393 @interface ConfirmationView : UIView {
394 }
395
396 @end
397
398 @implementation ConfirmationView
399 @end
400 /* }}} */
401 /* Package View {{{ */
402 @interface PackageView : UIPreferencesTable {
403 Package *package_;
404 Database *database_;
405 NSMutableArray *cells_;
406 }
407
408 - (int) numberOfGroupsInPreferencesTable:(UIPreferencesTable *)table;
409 - (int) preferencesTable:(UIPreferencesTable *)table numberOfRowsInGroup:(int)group;
410 - (UIPreferencesTableCell *) preferencesTable:(UIPreferencesTable *)table cellForRow:(int)row inGroup:(int)group;
411
412 - (PackageView *) initWithFrame:(struct CGRect)frame database:(Database *)database;
413 - (void) setPackage:(Package *)package;
414 @end
415
416 @implementation PackageView
417
418 - (int) numberOfGroupsInPreferencesTable:(UIPreferencesTable *)table {
419 return 2;
420 }
421
422 - (NSString *) preferencesTable:(UIPreferencesTable *)table titleForGroup:(int)group {
423 switch (group) {
424 case 0:
425 return @"Specifics";
426 break;
427
428 case 1:
429 return @"Description";
430 break;
431
432 default: _assert(false);
433 }
434 }
435
436 - (int) preferencesTable:(UIPreferencesTable *)table numberOfRowsInGroup:(int)group {
437 switch (group) {
438 case 0:
439 return 5;
440 break;
441
442 case 1:
443 return 1;
444 break;
445
446 default: _assert(false);
447 }
448 }
449
450 - (UIPreferencesTableCell *) preferencesTable:(UIPreferencesTable *)table cellForRow:(int)row inGroup:(int)group {
451 UIPreferencesTableCell *cell;
452
453 switch (group) {
454 case 0: switch (row) {
455 case 0:
456 cell = [cells_ objectAtIndex:0];
457 [cell setTitle:@"Name"];
458 [cell setValue:[package_ name]];
459 break;
460
461 case 1:
462 cell = [cells_ objectAtIndex:1];
463 [cell setTitle:@"Version"];
464 [cell setValue:[package_ version]];
465 break;
466
467 case 2:
468 cell = [cells_ objectAtIndex:2];
469 [cell setTitle:@"Section"];
470 [cell setValue:[package_ section]];
471 break;
472
473 case 3: {
474 double size = [package_ size];
475 unsigned power = 0;
476 while (size > 1024) {
477 size /= 1024;
478 ++power;
479 }
480
481 cell = [cells_ objectAtIndex:3];
482 [cell setTitle:@"Size"];
483 [cell setValue:[NSString stringWithFormat:@"%.1f%c", size, "bkMG"[power]]];
484 } break;
485
486 case 4:
487 cell = [cells_ objectAtIndex:4];
488 [cell setTitle:@"Maintainer"];
489 [cell setValue:[[package_ maintainer] name]];
490 [cell setShowDisclosure:YES];
491 [cell setShowSelection:YES];
492 break;
493
494 default: _assert(false);
495 } break;
496
497 case 1: switch (row) {
498 case 0:
499 cell = [cells_ objectAtIndex:5];
500 [cell setTitle:@"Tagline"];
501 [cell setValue:[package_ tagline]];
502 break;
503
504 case 1:
505 cell = [cells_ objectAtIndex:6];
506 [cell setTitle:@"Description"];
507 [cell setValue:[package_ description]];
508 break;
509 } break;
510
511 default: _assert(false);
512 }
513
514 return cell;
515 }
516
517 - (PackageView *) initWithFrame:(struct CGRect)frame database:(Database *)database {
518 if ((self = [super initWithFrame:frame]) != nil) {
519 database_ = database;
520 [self setDataSource:self];
521
522 cells_ = [[NSMutableArray arrayWithCapacity:16] retain];
523
524 for (unsigned i = 0; i != 6; ++i) {
525 struct CGRect frame = [self frameOfPreferencesCellAtRow:0 inGroup:0];
526 UIPreferencesTableCell *cell = [[UIPreferencesTableCell alloc] init];
527 [cell setShowSelection:NO];
528 [cells_ addObject:cell];
529 }
530 } return self;
531 }
532
533 - (void) setPackage:(Package *)package {
534 package_ = package;
535 [self reloadData];
536 }
537
538 @end
539 /* }}} */
540
541 @implementation Database
542
543 - (Database *) init {
544 if ((self = [super init]) != nil) {
545 records_ = NULL;
546 resolver_ = NULL;
547 } return self;
548 }
549
550 - (pkgCacheFile &) cache {
551 return cache_;
552 }
553
554 - (pkgRecords *) records {
555 return records_;
556 }
557
558 - (pkgProblemResolver *) resolver {
559 return resolver_;
560 }
561
562 - (void) reloadData {
563 delete resolver_;
564 delete records_;
565 cache_.Close();
566 cache_.Open(progress_, true);
567 records_ = new pkgRecords(cache_);
568 resolver_ = new pkgProblemResolver(cache_);
569 }
570
571 - (void) update {
572 NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
573
574 pkgSourceList list;
575 _assert(list.ReadMainList());
576
577 FileFd lock;
578 lock.Fd(GetLock(_config->FindDir("Dir::State::Lists") + "lock"));
579 _assert(!_error->PendingError());
580
581 pkgAcquire fetcher(&status_);
582 _assert(list.GetIndexes(&fetcher));
583 _assert(fetcher.Run() != pkgAcquire::Failed);
584
585 bool failed = false;
586 for (pkgAcquire::ItemIterator item = fetcher.ItemsBegin(); item != fetcher.ItemsEnd(); item++)
587 if ((*item)->Status != pkgAcquire::Item::StatDone) {
588 (*item)->Finished();
589 failed = true;
590 }
591
592 if (!failed && _config->FindB("APT::Get::List-Cleanup", true) == true) {
593 _assert(fetcher.Clean(_config->FindDir("Dir::State::lists")));
594 _assert(fetcher.Clean(_config->FindDir("Dir::State::lists") + "partial/"));
595 }
596
597 [pool release];
598 }
599
600 - (void) upgrade {
601 NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
602
603 _assert(cache_->DelCount() == 0 && cache_->InstCount() == 0);
604 _assert(pkgApplyStatus(cache_));
605
606 if (cache_->BrokenCount() != 0) {
607 _assert(pkgFixBroken(cache_));
608 _assert(cache_->BrokenCount() == 0);
609 _assert(pkgMinimizeUpgrade(cache_));
610 }
611
612 _assert(pkgDistUpgrade(cache_));
613
614 //InstallPackages(cache_, true);
615
616 [pool release];
617 }
618
619 - (void) setDelegate:(id)delegate {
620 status_.setDelegate(delegate);
621 progress_.setDelegate(delegate);
622 }
623
624 @end
625
626 /* Progress Data {{{ */
627 @interface ProgressData : NSObject {
628 SEL selector_;
629 id target_;
630 id object_;
631 }
632
633 - (ProgressData *) initWithSelector:(SEL)selector target:(id)target object:(id)object;
634
635 - (SEL) selector;
636 - (id) target;
637 - (id) object;
638 @end
639
640 @implementation ProgressData
641
642 - (ProgressData *) initWithSelector:(SEL)selector target:(id)target object:(id)object {
643 if ((self = [super init]) != nil) {
644 selector_ = selector;
645 target_ = target;
646 object_ = object;
647 } return self;
648 }
649
650 - (SEL) selector {
651 return selector_;
652 }
653
654 - (id) target {
655 return target_;
656 }
657
658 - (id) object {
659 return object_;
660 }
661
662 @end
663 /* }}} */
664
665 @interface ProgressView : UIView {
666 UIView *view_;
667 UITransitionView *transition_;
668 UIView *progress_;
669 UINavigationBar *navbar_;
670 }
671
672 - (ProgressView *) initWithFrame:(struct CGRect)frame;
673 - (void) setContentView:(UIView *)view;
674 - (void) resetView;
675
676 - (void) _detachNewThreadData:(ProgressData *)data;
677 - (void) detachNewThreadSelector:(SEL)selector toTarget:(id)target withObject:(id)object;
678
679 - (void) setStatusIMSHit;
680 - (void) setStatusFetch;
681 - (void) setStatusDone;
682 - (void) setStatusFail;
683 - (void) setStatusPulse;
684
685 - (void) setStatusStart;
686 - (void) setStatusStop;
687 @end
688
689 @implementation ProgressView
690
691 - (ProgressView *) initWithFrame:(struct CGRect)frame {
692 if ((self = [super initWithFrame:frame]) != nil) {
693 transition_ = [[UITransitionView alloc] initWithFrame:[self bounds]];
694 [self addSubview:transition_];
695
696 progress_ = [[UIView alloc] initWithFrame:[transition_ bounds]];
697
698 CGColorSpaceRef space = CGColorSpaceCreateDeviceRGB();
699 float black[] = {0.0, 0.0, 0.0, 1.0};
700 [progress_ setBackgroundColor:CGColorCreate(space, black)];
701
702 CGSize navsize = [UINavigationBar defaultSize];
703 CGRect navrect = {{0, 0}, navsize};
704
705 navbar_ = [[UINavigationBar alloc] initWithFrame:navrect];
706 [progress_ addSubview:navbar_];
707
708 [navbar_ setBarStyle:1];
709 [navbar_ setDelegate:self];
710
711 UINavigationItem *navitem = [[UINavigationItem alloc] initWithTitle:nil];
712 [navbar_ pushNavigationItem:navitem];
713 } return self;
714 }
715
716 - (void) setContentView:(UIView *)view {
717 view_ = view;
718 }
719
720 - (void) resetView {
721 [transition_ transition:6 toView:view_];
722 }
723
724 - (void) _detachNewThreadData:(ProgressData *)data {
725 NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
726
727 [[data target] performSelector:[data selector] withObject:[data object]];
728 [self performSelectorOnMainThread:@selector(resetView) withObject:nil waitUntilDone:YES];
729
730 [pool release];
731 }
732
733 - (void) detachNewThreadSelector:(SEL)selector toTarget:(id)target withObject:(id)object {
734 [transition_ transition:6 toView:progress_];
735
736 [NSThread
737 detachNewThreadSelector:@selector(_detachNewThreadData:)
738 toTarget:self
739 withObject:[[ProgressData alloc]
740 initWithSelector:selector
741 target:target
742 object:object
743 ]
744 ];
745 }
746
747 - (void) setStatusIMSHit {
748 _trace();
749 }
750
751 - (void) setStatusFetch {
752 _trace();
753 }
754
755 - (void) setStatusDone {
756 _trace();
757 }
758
759 - (void) setStatusFail {
760 _trace();
761 }
762
763 - (void) setStatusPulse {
764 _trace();
765 }
766
767 - (void) setStatusStart {
768 _trace();
769 }
770
771 - (void) setStatusStop {
772 _trace();
773 }
774
775 @end
776
777 @protocol PackagesDelegate
778
779 - (void) viewPackage:(Package *)package;
780
781 @end
782
783 @interface Packages : UIView {
784 NSString *title_;
785 Database *database_;
786 bool (*filter_)(Package *package);
787 NSMutableArray *packages_;
788 NSMutableArray *sections_;
789 id delegate_;
790 UISectionList *list_;
791 UINavigationBar *navbar_;
792 UITransitionView *transition_;
793 Package *package_;
794 PackageView *pkgview_;
795 SEL selector_;
796 }
797
798 - (int) numberOfSectionsInSectionList:(UISectionList *)list;
799 - (NSString *) sectionList:(UISectionList *)list titleForSection:(int)section;
800 - (int) sectionList:(UISectionList *)list rowForSection:(int)section;
801
802 - (int) numberOfRowsInTable:(UITable *)table;
803 - (float) table:(UITable *)table heightForRow:(int)row;
804 - (UITableCell *) table:(UITable *)table cellForRow:(int)row column:(UITableColumn *)col;
805 - (BOOL) table:(UITable *)table showDisclosureForRow:(int)row;
806 - (void) tableRowSelected:(NSNotification*)notification;
807
808 - (void) navigationBar:(UINavigationBar *)navbar buttonClicked:(int)button;
809 - (void) navigationBar:(UINavigationBar *)navbar poppedItem:(UINavigationItem *)item;
810
811 - (Packages *) initWithFrame:(struct CGRect)frame title:(NSString *)title database:(Database *)database filter:(bool (*)(Package *))filter selector:(SEL)selector;
812 - (void) setDelegate:(id)delegate;
813 - (void) addPackage:(Package *)package;
814 - (NSMutableArray *) packages;
815 - (void) reloadData;
816 @end
817
818 @implementation Packages
819
820 - (int) numberOfSectionsInSectionList:(UISectionList *)list {
821 return [sections_ count];
822 }
823
824 - (NSString *) sectionList:(UISectionList *)list titleForSection:(int)section {
825 return [[sections_ objectAtIndex:section] name];
826 }
827
828 - (int) sectionList:(UISectionList *)list rowForSection:(int)section {
829 return [[sections_ objectAtIndex:section] row];
830 }
831
832 - (int) numberOfRowsInTable:(UITable *)table {
833 return [packages_ count];
834 }
835
836 - (float) table:(UITable *)table heightForRow:(int)row {
837 return 64;
838 }
839
840 - (UITableCell *) table:(UITable *)table cellForRow:(int)row column:(UITableColumn *)col {
841 Package *package = [packages_ objectAtIndex:row]; {
842 UITableCell *cell = [package cell];
843 if (cell != nil)
844 return cell;
845 }
846
847 #if 0
848 UIImageAndTextTableCell *cell_ = [[UIImageAndTextTableCell alloc] init];
849 [package setCell:cell_];
850
851 [cell_ setTitle:[package name]];
852 return cell_;
853 #endif
854
855 UITableCell *cell = [[UITableCell alloc] init];
856 [package setCell:cell];
857
858 GSFontRef bold = GSFontCreateWithName("Helvetica", kGSFontTraitBold, 22);
859 GSFontRef large = GSFontCreateWithName("Helvetica", kGSFontTraitNone, 16);
860 GSFontRef small = GSFontCreateWithName("Helvetica", kGSFontTraitNone, 14);
861
862 CGColorSpaceRef space = CGColorSpaceCreateDeviceRGB();
863 float blue[] = {0.2, 0.2, 1.0, 1.0};
864 float gray[] = {0.4, 0.4, 0.4, 1.0};
865 float clear[] = {0, 0, 0, 0};
866
867 UITextLabel *name = [[UITextLabel alloc] initWithFrame:CGRectMake(12, 7, 250, 25)];
868 [name setText:[package name]];
869 [name setBackgroundColor:CGColorCreate(space, clear)];
870 [name setFont:bold];
871
872 UIRightTextLabel *version = [[UIRightTextLabel alloc] initWithFrame:CGRectMake(290, 7, 70, 25)];
873 [version setText:[package version]];
874 [version setColor:CGColorCreate(space, blue)];
875 [version setBackgroundColor:CGColorCreate(space, clear)];
876 [version setFont:large];
877
878 UITextLabel *description = [[UITextLabel alloc] initWithFrame:CGRectMake(13, 35, 315, 20)];
879 [description setText:[package tagline]];
880 [description setColor:CGColorCreate(space, gray)];
881 [description setBackgroundColor:CGColorCreate(space, clear)];
882 [description setFont:small];
883
884 [cell addSubview:name];
885 [cell addSubview:version];
886 [cell addSubview:description];
887
888 CFRelease(small);
889 CFRelease(large);
890 CFRelease(bold);
891
892 return cell;
893 }
894
895 - (BOOL) table:(UITable *)table showDisclosureForRow:(int)row {
896 return YES;
897 }
898
899 - (void) tableRowSelected:(NSNotification*)notification {
900 int row = [[list_ table] selectedRow];
901 if (row == INT_MAX)
902 return;
903
904 package_ = [packages_ objectAtIndex:row];
905
906 UINavigationItem *navitem = [[UINavigationItem alloc] initWithTitle:[package_ name]];
907 [navbar_ pushNavigationItem:navitem];
908
909 [navbar_ showButtonsWithLeftTitle:nil rightTitle:title_];
910
911 [pkgview_ setPackage:package_];
912 [transition_ transition:1 toView:pkgview_];
913
914 }
915
916 - (void) navigationBar:(UINavigationBar *)navbar buttonClicked:(int)button {
917 if (button == 0) {
918 printf("bef:%ld\n", [database_ cache]->InstCount());
919 [package_ performSelector:selector_];
920
921 pkgProblemResolver *resolver = [database_ resolver];
922
923 resolver->InstallProtect();
924 if (!resolver->Resolve(true))
925 _error->Discard();
926
927 printf("aft:%ld\n", [database_ cache]->InstCount());
928 _assert(false);
929 }
930 }
931
932 - (void) navigationBar:(UINavigationBar *)navbar poppedItem:(UINavigationItem *)item {
933 [transition_ transition:2 toView:list_];
934 [navbar_ showButtonsWithLeftTitle:nil rightTitle:nil];
935 UITable *table = [list_ table];
936 [table selectRow:-1 byExtendingSelection:NO withFade:YES];
937 //UITableCell *cell = [table cellAtRow:[table selectedRow] column:0];
938 //[table selectCell:nil inRow:-1 column:-1 withFade:YES];
939 //[table highlightRow:-1];
940 //[cell setSelected:NO withFade:YES];
941 package_ = nil;
942 }
943
944 - (Packages *) initWithFrame:(struct CGRect)frame title:(NSString *)title database:(Database *)database filter:(bool (*)(Package *))filter selector:(SEL)selector {
945 if ((self = [super initWithFrame:frame]) != nil) {
946 title_ = title;
947 database_ = database;
948 filter_ = filter;
949 selector_ = selector;
950
951 packages_ = [[NSMutableArray arrayWithCapacity:16] retain];
952
953 struct CGRect bounds = [self bounds];
954 CGSize navsize = [UINavigationBar defaultSize];
955 CGRect navrect = {{0, 0}, navsize};
956
957 navbar_ = [[UINavigationBar alloc] initWithFrame:navrect];
958 [self addSubview:navbar_];
959
960 [navbar_ setBarStyle:1];
961 [navbar_ setDelegate:self];
962
963 UINavigationItem *navitem = [[UINavigationItem alloc] initWithTitle:title];
964 [navbar_ pushNavigationItem:navitem];
965 [navitem setBackButtonTitle:@"Packages"];
966
967 transition_ = [[UITransitionView alloc] initWithFrame:CGRectMake(
968 bounds.origin.x, bounds.origin.y + navsize.height, bounds.size.width, bounds.size.height - navsize.height
969 )];
970
971 [self addSubview:transition_];
972
973 list_ = [[UISectionList alloc] initWithFrame:[transition_ bounds] showSectionIndex:NO];
974 [list_ setDataSource:self];
975
976 [transition_ transition:0 toView:list_];
977
978 UITableColumn *column = [[UITableColumn alloc]
979 initWithTitle:@"Name"
980 identifier:@"name"
981 width:frame.size.width
982 ];
983
984 UITable *table = [list_ table];
985 [table setSeparatorStyle:1];
986 [table addTableColumn:column];
987 [table setDelegate:self];
988
989 pkgview_ = [[PackageView alloc] initWithFrame:[transition_ bounds] database:database_];
990 } return self;
991 }
992
993 - (void) setDelegate:(id)delegate {
994 delegate_ = delegate;
995 }
996
997 - (void) addPackage:(Package *)package {
998 _assert(sections_ == nil);
999 [packages_ addObject:package];
1000 }
1001
1002 - (NSMutableArray *) packages {
1003 return packages_;
1004 }
1005
1006 - (void) reloadData {
1007 for (pkgCache::PkgIterator iterator = [database_ cache]->PkgBegin(); !iterator.end(); ++iterator) {
1008 Package *package = [Package packageWithIterator:iterator database:database_];
1009 if (package == nil)
1010 continue;
1011 if (filter_(package))
1012 [self addPackage:package];
1013 }
1014
1015 [packages_ sortUsingSelector:@selector(compareBySectionAndName:)];
1016 sections_ = [[NSMutableArray arrayWithCapacity:16] retain];
1017
1018 Section *section = nil;
1019 for (size_t offset = 0, count = [packages_ count]; offset != count; ++offset) {
1020 Package *package = [packages_ objectAtIndex:offset];
1021 NSString *name = [package section];
1022
1023 if (section == nil || ![[section name] isEqual:name]) {
1024 section = [[Section alloc] initWithName:name row:offset];
1025 [sections_ addObject:section];
1026 }
1027
1028 [section addPackage:package];
1029 }
1030
1031 [list_ reloadData];
1032 }
1033
1034 @end
1035
1036 bool IsInstalled(Package *package) {
1037 return [package installed];
1038 }
1039
1040 bool IsNotInstalled(Package *package) {
1041 return ![package installed];
1042 }
1043
1044 @interface Cydia : UIApplication <PackagesDelegate> {
1045 UIWindow *window_;
1046 UITransitionView *transition_;
1047
1048 Database *database_;
1049 ProgressView *progress_;
1050
1051 UIView *featured_;
1052 UINavigationBar *navbar_;
1053 UIScroller *scroller_;
1054 UIWebView *webview_;
1055 NSURL *url_;
1056
1057 Packages *install_;
1058 Packages *uninstall_;
1059 }
1060
1061 - (void) loadNews;
1062 - (void) reloadData;
1063
1064 - (void) navigationBar:(UINavigationBar *)navbar buttonClicked:(int)button;
1065 - (void) buttonBarItemTapped:(id)sender;
1066
1067 - (void) view:(UIView *)sender didSetFrame:(CGRect)frame;
1068 - (void) view:(UIView *)view didDrawInRect:(CGRect)rect duration:(float)duration;
1069
1070 - (void) viewPackage:(Package *)package;
1071
1072 - (void) applicationDidFinishLaunching:(id)unused;
1073 @end
1074
1075 @implementation Cydia
1076
1077 - (void) loadNews {
1078 [webview_ loadRequest:[NSURLRequest
1079 requestWithURL:url_
1080 cachePolicy:NSURLRequestReloadIgnoringCacheData
1081 timeoutInterval:30.0
1082 ]];
1083 }
1084
1085 - (void) reloadData {
1086 [database_ reloadData];
1087 [install_ reloadData];
1088 [uninstall_ reloadData];
1089 }
1090
1091 - (void) navigationBar:(UINavigationBar *)navbar buttonClicked:(int)button {
1092 switch (button) {
1093 case 0:
1094 [self loadNews];
1095 break;
1096
1097 case 1:
1098 break;
1099 }
1100 }
1101
1102 - (void) buttonBarItemTapped:(id)sender {
1103 UIView *view;
1104
1105 switch ([sender tag]) {
1106 case 1: view = featured_; break;
1107 case 2: view = install_; break;
1108 case 4: view = uninstall_; break;
1109
1110 default:
1111 _assert(false);
1112 }
1113
1114 [transition_ transition:0 toView:view];
1115 }
1116
1117 - (void) view:(UIView *)view didSetFrame:(CGRect)frame {
1118 [scroller_ setContentSize:frame.size];
1119 }
1120
1121 - (void) view:(UIView *)view didDrawInRect:(CGRect)rect duration:(float)duration {
1122 [scroller_ setContentSize:[webview_ bounds].size];
1123 }
1124
1125 - (void) viewPackage:(Package *)package {
1126 _assert(false);
1127 }
1128
1129 - (void) applicationDidFinishLaunching:(id)unused {
1130 _assert(pkgInitConfig(*_config));
1131 _assert(pkgInitSystem(*_config, _system));
1132
1133 CGRect screenrect = [UIHardware fullScreenApplicationContentRect];
1134 window_ = [[UIWindow alloc] initWithContentRect:screenrect];
1135
1136 [window_ orderFront: self];
1137 [window_ makeKey: self];
1138 [window_ _setHidden: NO];
1139
1140 progress_ = [[ProgressView alloc] initWithFrame:[window_ bounds]];
1141 [database_ setDelegate:progress_];
1142 [window_ setContentView:progress_];
1143
1144 UIView *view = [[UIView alloc] initWithFrame:[progress_ bounds]];
1145 [progress_ setContentView:view];
1146
1147 transition_ = [[UITransitionView alloc] initWithFrame:CGRectMake(
1148 0, 0, screenrect.size.width, screenrect.size.height - 48
1149 )];
1150
1151 [view addSubview:transition_];
1152
1153 featured_ = [[UIView alloc] initWithFrame:[transition_ bounds]];
1154
1155 CGSize navsize = [UINavigationBar defaultSize];
1156 CGRect navrect = {{0, 0}, navsize};
1157
1158 navbar_ = [[UINavigationBar alloc] initWithFrame:navrect];
1159 [featured_ addSubview:navbar_];
1160
1161 [navbar_ setBarStyle:1];
1162 [navbar_ setDelegate:self];
1163
1164 [navbar_ showButtonsWithLeftTitle:@"About" rightTitle:@"Reload"];
1165
1166 UINavigationItem *navitem = [[UINavigationItem alloc] initWithTitle:@"Featured"];
1167 [navbar_ pushNavigationItem:navitem];
1168
1169 struct CGRect subbounds = [featured_ bounds];
1170 subbounds.origin.y += navsize.height;
1171 subbounds.size.height -= navsize.height;
1172
1173 UIImageView *pinstripe = [[UIImageView alloc] initWithFrame:subbounds];
1174 [pinstripe setImage:[UIImage applicationImageNamed:@"pinstripe.png"]];
1175 [featured_ addSubview:pinstripe];
1176
1177 scroller_ = [[UIScroller alloc] initWithFrame:subbounds];
1178 [featured_ addSubview:scroller_];
1179
1180 [scroller_ setScrollingEnabled:YES];
1181 [scroller_ setAdjustForContentSizeChange:YES];
1182 [scroller_ setClipsSubviews:YES];
1183 [scroller_ setAllowsRubberBanding:YES];
1184 [scroller_ setScrollDecelerationFactor:0.99];
1185 [scroller_ setDelegate:self];
1186
1187 webview_ = [[UIWebView alloc] initWithFrame:[scroller_ bounds]];
1188 [scroller_ addSubview:webview_];
1189
1190 [webview_ setTilingEnabled:YES];
1191 [webview_ setTileSize:CGSizeMake(screenrect.size.width, 500)];
1192 [webview_ setAutoresizes:YES];
1193 [webview_ setDelegate:self];
1194
1195 url_ = [NSURL URLWithString:@"http://cydia.saurik.com/"];
1196 [self loadNews];
1197
1198 NSArray *buttonitems = [NSArray arrayWithObjects:
1199 [NSDictionary dictionaryWithObjectsAndKeys:
1200 @"buttonBarItemTapped:", kUIButtonBarButtonAction,
1201 @"featured-up.png", kUIButtonBarButtonInfo,
1202 @"featured-dn.png", kUIButtonBarButtonSelectedInfo,
1203 [NSNumber numberWithInt:1], kUIButtonBarButtonTag,
1204 self, kUIButtonBarButtonTarget,
1205 @"Featured", kUIButtonBarButtonTitle,
1206 @"0", kUIButtonBarButtonType,
1207 nil],
1208
1209 [NSDictionary dictionaryWithObjectsAndKeys:
1210 @"buttonBarItemTapped:", kUIButtonBarButtonAction,
1211 @"install-up.png", kUIButtonBarButtonInfo,
1212 @"install-dn.png", kUIButtonBarButtonSelectedInfo,
1213 [NSNumber numberWithInt:2], kUIButtonBarButtonTag,
1214 self, kUIButtonBarButtonTarget,
1215 @"Install", kUIButtonBarButtonTitle,
1216 @"0", kUIButtonBarButtonType,
1217 nil],
1218
1219 [NSDictionary dictionaryWithObjectsAndKeys:
1220 @"buttonBarItemTapped:", kUIButtonBarButtonAction,
1221 @"upgrade-up.png", kUIButtonBarButtonInfo,
1222 @"upgrade-dn.png", kUIButtonBarButtonSelectedInfo,
1223 [NSNumber numberWithInt:3], kUIButtonBarButtonTag,
1224 self, kUIButtonBarButtonTarget,
1225 @"Upgrade", kUIButtonBarButtonTitle,
1226 @"0", kUIButtonBarButtonType,
1227 nil],
1228
1229 [NSDictionary dictionaryWithObjectsAndKeys:
1230 @"buttonBarItemTapped:", kUIButtonBarButtonAction,
1231 @"uninstall-up.png", kUIButtonBarButtonInfo,
1232 @"uninstall-dn.png", kUIButtonBarButtonSelectedInfo,
1233 [NSNumber numberWithInt:4], kUIButtonBarButtonTag,
1234 self, kUIButtonBarButtonTarget,
1235 @"Uninstall", kUIButtonBarButtonTitle,
1236 @"0", kUIButtonBarButtonType,
1237 nil],
1238
1239 [NSDictionary dictionaryWithObjectsAndKeys:
1240 @"buttonBarItemTapped:", kUIButtonBarButtonAction,
1241 @"sources-up.png", kUIButtonBarButtonInfo,
1242 @"sources-dn.png", kUIButtonBarButtonSelectedInfo,
1243 [NSNumber numberWithInt:5], kUIButtonBarButtonTag,
1244 self, kUIButtonBarButtonTarget,
1245 @"Sources", kUIButtonBarButtonTitle,
1246 @"0", kUIButtonBarButtonType,
1247 nil],
1248 nil];
1249
1250 UIButtonBar *buttonbar = [[UIButtonBar alloc]
1251 initInView:view
1252 withFrame:CGRectMake(
1253 0, screenrect.size.height - 48,
1254 screenrect.size.width, 48
1255 )
1256 withItemList:buttonitems
1257 ];
1258
1259 [buttonbar setDelegate:self];
1260 [buttonbar setBarStyle:1];
1261 [buttonbar setButtonBarTrackingMode:2];
1262
1263 int buttons[5] = {1, 2, 3, 4, 5};
1264 [buttonbar registerButtonGroup:0 withButtons:buttons withCount:5];
1265 [buttonbar showButtonGroup:0 withDuration:0];
1266
1267 for (int i = 0; i != 5; ++i)
1268 [[buttonbar viewWithTag:(i + 1)] setFrame:CGRectMake(
1269 i * 64 + 2, 1, 60, 48
1270 )];
1271
1272 [buttonbar showSelectionForButton:1];
1273 [transition_ transition:0 toView:featured_];
1274
1275 [view addSubview:buttonbar];
1276
1277 database_ = [[Database alloc] init];
1278
1279 install_ = [[Packages alloc] initWithFrame:[transition_ bounds] title:@"Install" database:database_ filter:&IsNotInstalled selector:@selector(install)];
1280 [install_ setDelegate:self];
1281
1282 uninstall_ = [[Packages alloc] initWithFrame:[transition_ bounds] title:@"Uninstall" database:database_ filter:&IsInstalled selector:@selector(remove)];
1283 [uninstall_ setDelegate:self];
1284
1285 #if 0
1286 UIAlertSheet *alert = [[UIAlertSheet alloc]
1287 initWithTitle:@"Alert Title"
1288 buttons:[NSArray arrayWithObjects:@"Yes", nil]
1289 defaultButtonIndex:0
1290 delegate:self
1291 context:self
1292 ];
1293
1294 NSLog(@"%p\n", [alert table]);
1295 [[alert table] setDelegate:self];
1296 [[alert table] reloadData];
1297
1298 [alert addTextFieldWithValue:@"Title" label:@"Label"];
1299 [alert setShowsOverSpringBoardAlerts:YES];
1300 [alert setBodyText:@"This is an alert."];
1301 [alert presentSheetFromButtonBar:buttonbar];
1302 //[alert popupAlertAnimated:YES];
1303 #endif
1304
1305 [self reloadData];
1306 [progress_ resetView];
1307 //[progress_ detachNewThreadSelector:@selector(reloadData) toTarget:self withObject:nil];
1308 }
1309
1310 @end
1311
1312 int main(int argc, char *argv[]) {
1313 NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
1314 UIApplicationMain(argc, argv, [Cydia class]);
1315 [pool release];
1316 }