]> git.saurik.com Git - cydia.git/blame - Cydia.mm
Implemented badges.
[cydia.git] / Cydia.mm
CommitLineData
dc5812ec 1/* #include Directives {{{ */
8da60fb7 2#include <Foundation/NSURL.h>
dc5812ec
JF
3#include <UIKit/UIKit.h>
4#import <GraphicsServices/GraphicsServices.h>
5
2367a917
JF
6#include <sstream>
7#include <ext/stdio_filebuf.h>
8
dc5812ec
JF
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>
3178d79b 14#include <apt-pkg/debmetaindex.h>
dc5812ec
JF
15#include <apt-pkg/error.h>
16#include <apt-pkg/init.h>
17#include <apt-pkg/pkgrecords.h>
18#include <apt-pkg/sourcelist.h>
2367a917 19#include <apt-pkg/sptr.h>
dc5812ec 20
3178d79b
JF
21#include <sys/sysctl.h>
22
2367a917 23#include <errno.h>
dc5812ec
JF
24#include <pcre.h>
25#include <string.h>
26/* }}} */
27/* Extension Keywords {{{ */
2367a917 28#define _trace() fprintf(stderr, "_trace()@%s:%u[%s]\n", __FILE__, __LINE__, __FUNCTION__)
dc5812ec
JF
29
30#define _assert(test) do \
31 if (!(test)) { \
2367a917 32 fprintf(stderr, "_assert(%d:%s)@%s:%u[%s]\n", errno, #test, __FILE__, __LINE__, __FUNCTION__); \
dc5812ec
JF
33 exit(-1); \
34 } \
35while (false)
36/* }}} */
37
3178d79b
JF
38@interface WebView
39- (void) setApplicationNameForUserAgent:(NSString *)applicationName;
40@end
41
42static const int PulseInterval_ = 50000;
43const char *Machine_ = NULL;
44const char *SerialNumber_ = NULL;
45
8da60fb7
JF
46@interface NSString (CydiaBypass)
47- (NSString *) stringByAddingPercentEscapes;
48@end
49
2367a917
JF
50@protocol ProgressDelegate
51- (void) setError:(NSString *)error;
52- (void) setTitle:(NSString *)title;
53- (void) setPercent:(float)percent;
54- (void) addOutput:(NSString *)output;
55@end
56
8fe19fc1
JF
57NSString *SizeString(double size) {
58 unsigned power = 0;
59 while (size > 1024) {
60 size /= 1024;
61 ++power;
62 }
63
64 static const char *powers_[] = {"B", "kB", "MB", "GB"};
65
66 return [NSString stringWithFormat:@"%.1f%s", size, powers_[power]];
67}
68
dc5812ec
JF
69/* Status Delegation {{{ */
70class Status :
71 public pkgAcquireStatus
72{
73 private:
74 id delegate_;
75
76 public:
77 Status() :
78 delegate_(nil)
79 {
80 }
81
82 void setDelegate(id delegate) {
83 delegate_ = delegate;
84 }
85
86 virtual bool MediaChange(std::string media, std::string drive) {
87 return false;
88 }
89
90 virtual void IMSHit(pkgAcquire::ItemDesc &item) {
dc5812ec
JF
91 }
92
93 virtual void Fetch(pkgAcquire::ItemDesc &item) {
8da60fb7 94 [delegate_ setTitle:[NSString stringWithCString:("Downloading " + item.ShortDesc).c_str()]];
dc5812ec
JF
95 }
96
97 virtual void Done(pkgAcquire::ItemDesc &item) {
dc5812ec
JF
98 }
99
100 virtual void Fail(pkgAcquire::ItemDesc &item) {
101 [delegate_ performSelectorOnMainThread:@selector(setStatusFail) withObject:nil waitUntilDone:YES];
102 }
103
104 virtual bool Pulse(pkgAcquire *Owner) {
2367a917
JF
105 bool value = pkgAcquireStatus::Pulse(Owner);
106
107 float percent(
108 double(CurrentBytes + CurrentItems) /
109 double(TotalBytes + TotalItems)
110 );
111
112 [delegate_ setPercent:percent];
113 return value;
dc5812ec
JF
114 }
115
116 virtual void Start() {
dc5812ec
JF
117 }
118
119 virtual void Stop() {
dc5812ec
JF
120 }
121};
122/* }}} */
123/* Progress Delegation {{{ */
124class Progress :
125 public OpProgress
126{
127 private:
128 id delegate_;
129
130 protected:
131 virtual void Update() {
2367a917
JF
132 [delegate_ setTitle:[NSString stringWithCString:Op.c_str()]];
133 [delegate_ setPercent:(Percent / 100)];
dc5812ec
JF
134 }
135
136 public:
137 Progress() :
138 delegate_(nil)
139 {
140 }
141
142 void setDelegate(id delegate) {
143 delegate_ = delegate;
144 }
145
146 virtual void Done() {
2367a917 147 [delegate_ setPercent:1];
dc5812ec
JF
148 }
149};
150/* }}} */
151
152/* External Constants {{{ */
153extern NSString *kUIButtonBarButtonAction;
154extern NSString *kUIButtonBarButtonInfo;
155extern NSString *kUIButtonBarButtonInfoOffset;
156extern NSString *kUIButtonBarButtonSelectedInfo;
157extern NSString *kUIButtonBarButtonStyle;
158extern NSString *kUIButtonBarButtonTag;
159extern NSString *kUIButtonBarButtonTarget;
160extern NSString *kUIButtonBarButtonTitle;
161extern NSString *kUIButtonBarButtonTitleVerticalHeight;
162extern NSString *kUIButtonBarButtonTitleWidth;
163extern NSString *kUIButtonBarButtonType;
164/* }}} */
165/* Mime Addresses {{{ */
166@interface Address : NSObject {
167 NSString *name_;
168 NSString *email_;
169}
170
2367a917
JF
171- (void) dealloc;
172
dc5812ec
JF
173- (NSString *) name;
174- (NSString *) email;
175
176+ (Address *) addressWithString:(NSString *)string;
177- (Address *) initWithString:(NSString *)string;
178@end
179
180@implementation Address
181
2367a917
JF
182- (void) dealloc {
183 [name_ release];
3178d79b
JF
184 if (email_ != nil)
185 [email_ release];
2367a917
JF
186 [super dealloc];
187}
188
dc5812ec
JF
189- (NSString *) name {
190 return name_;
191}
192
193- (NSString *) email {
194 return email_;
195}
196
197+ (Address *) addressWithString:(NSString *)string {
2367a917 198 return [[[Address alloc] initWithString:string] autorelease];
dc5812ec
JF
199}
200
201- (Address *) initWithString:(NSString *)string {
202 if ((self = [super init]) != nil) {
203 const char *error;
204 int offset;
dc5812ec
JF
205 pcre *code = pcre_compile("^\"?(.*)\"? <([^>]*)>$", 0, &error, &offset, NULL);
206
207 if (code == NULL) {
2367a917 208 fprintf(stderr, "%d:%s\n", offset, error);
dc5812ec
JF
209 _assert(false);
210 }
211
212 pcre_extra *study = NULL;
213 int capture;
214 pcre_fullinfo(code, study, PCRE_INFO_CAPTURECOUNT, &capture);
2367a917 215 int matches[(capture + 1) * 3];
dc5812ec
JF
216
217 size_t size = [string length];
218 const char *data = [string UTF8String];
219
3178d79b
JF
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];
223 } else {
224 name_ = [[NSString stringWithCString:data length:size] retain];
225 email_ = nil;
226 }
dc5812ec
JF
227 } return self;
228}
229
230@end
231/* }}} */
232
233/* Right Alignment {{{ */
234@interface UIRightTextLabel : UITextLabel {
235 float _savedRightEdgeX;
236 BOOL _sizedtofit_flag;
237}
238
239- (void) setFrame:(CGRect)frame;
240- (void) setText:(NSString *)text;
241- (void) realignText;
242@end
243
244@implementation UIRightTextLabel
245
246- (void) setFrame:(CGRect)frame {
247 [super setFrame:frame];
248 if (_sizedtofit_flag == NO) {
249 _savedRightEdgeX = frame.origin.x;
250 [self realignText];
251 }
252}
253
254- (void) setText:(NSString *)text {
255 [super setText:text];
256 [self realignText];
257}
258
259- (void) realignText {
260 CGRect oldFrame = [self frame];
261
262 _sizedtofit_flag = YES;
263 [self sizeToFit]; // shrink down size so I can right align it
264
265 CGRect newFrame = [self frame];
266
267 oldFrame.origin.x = _savedRightEdgeX - newFrame.size.width;
268 oldFrame.size.width = newFrame.size.width;
269 [super setFrame:oldFrame];
270 _sizedtofit_flag = NO;
271}
272
273@end
274/* }}} */
2367a917
JF
275/* Linear Algebra {{{ */
276inline float interpolate(float begin, float end, float fraction) {
277 return (end - begin) * fraction + begin;
278}
279/* }}} */
dc5812ec 280
8da60fb7
JF
281/* Reset View {{{ */
282@interface ResetView : UIView {
283 UINavigationBar *navbar_;
284 bool resetting_;
285}
286
3178d79b
JF
287- (void) navigationBar:(UINavigationBar *)navbar poppedItem:(UINavigationItem *)item;
288
8da60fb7
JF
289- (void) dealloc;
290- (void) resetView;
3178d79b
JF
291- (void) _resetView;
292- (NSString *) leftTitle;
293- (NSString *) rightTitle;
8da60fb7
JF
294@end
295
296@implementation ResetView
297
3178d79b
JF
298- (void) navigationBar:(UINavigationBar *)navbar poppedItem:(UINavigationItem *)item {
299 if ([[navbar_ navigationItems] count] == 1)
300 [self _resetView];
301}
302
8da60fb7
JF
303- (void) dealloc {
304 [navbar_ release];
305 [super dealloc];
306}
307
308- (void) resetView {
309 resetting_ = true;
3178d79b
JF
310 if ([[navbar_ navigationItems] count] == 1)
311 [self _resetView];
312 else while ([[navbar_ navigationItems] count] != 1)
8da60fb7
JF
313 [navbar_ popNavigationItem];
314 resetting_ = false;
315}
316
3178d79b
JF
317- (void) _resetView {
318 [navbar_ showButtonsWithLeftTitle:[self leftTitle] rightTitle:[self rightTitle]];
319}
320
321- (NSString *) leftTitle {
322 return nil;
323}
324
325- (NSString *) rightTitle {
326 return nil;
327}
328
8da60fb7
JF
329@end
330/* }}} */
331
3178d79b
JF
332@class Package;
333
dc5812ec
JF
334@interface Database : NSObject {
335 pkgCacheFile cache_;
336 pkgRecords *records_;
337 pkgProblemResolver *resolver_;
8fe19fc1
JF
338 pkgAcquire *fetcher_;
339 FileFd *lock_;
340 SPtr<pkgPackageManager> manager_;
dc5812ec 341
2367a917 342 id delegate_;
dc5812ec
JF
343 Status status_;
344 Progress progress_;
2367a917 345 int statusfd_;
dc5812ec
JF
346}
347
3178d79b
JF
348- (void) _readStatus:(NSNumber *)fd;
349- (void) _readOutput:(NSNumber *)fd;
350
351- (Package *) packageWithName:(NSString *)name;
352
dc5812ec
JF
353- (Database *) init;
354- (pkgCacheFile &) cache;
355- (pkgRecords *) records;
356- (pkgProblemResolver *) resolver;
8fe19fc1 357- (pkgAcquire &) fetcher;
dc5812ec 358- (void) reloadData;
2367a917 359
8fe19fc1 360- (void) prepare;
2367a917 361- (void) perform;
dc5812ec
JF
362- (void) update;
363- (void) upgrade;
2367a917 364
dc5812ec
JF
365- (void) setDelegate:(id)delegate;
366@end
367
368/* Package Class {{{ */
369@interface Package : NSObject {
370 pkgCache::PkgIterator iterator_;
371 Database *database_;
dc5812ec
JF
372 pkgRecords::Parser *parser_;
373 pkgCache::VerIterator version_;
374 pkgCache::VerFileIterator file_;
375}
376
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;
379
380- (NSString *) name;
381- (NSString *) section;
3178d79b
JF
382- (NSString *) latest;
383- (NSString *) installed;
dc5812ec
JF
384- (Address *) maintainer;
385- (size_t) size;
386- (NSString *) tagline;
387- (NSString *) description;
dc5812ec
JF
388- (NSComparisonResult) compareBySectionAndName:(Package *)package;
389
390- (void) install;
391- (void) remove;
392@end
393
394@implementation Package
395
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;
dc5812ec
JF
400
401 version_ = version;
402 file_ = file;
403 parser_ = &[database_ records]->Lookup(file);
404 } return self;
405}
406
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)
2367a917
JF
410 return [[[Package alloc]
411 initWithIterator:iterator
412 database:database
413 version:version
414 file:file]
415 autorelease];
dc5812ec
JF
416 return nil;
417}
418
419- (NSString *) name {
3178d79b 420 return [[NSString stringWithCString:iterator_.Name()] lowercaseString];
dc5812ec
JF
421}
422
423- (NSString *) section {
424 return [NSString stringWithCString:iterator_.Section()];
425}
426
3178d79b
JF
427- (NSString *) latest {
428 return [NSString stringWithCString:version_.VerStr()];
dc5812ec
JF
429}
430
3178d79b
JF
431- (NSString *) installed {
432 return iterator_.CurrentVer().end() ? nil : [NSString stringWithCString:iterator_.CurrentVer().VerStr()];
dc5812ec
JF
433}
434
435- (Address *) maintainer {
436 return [Address addressWithString:[NSString stringWithCString:parser_->Maintainer().c_str()]];
437}
438
439- (size_t) size {
440 return version_->InstalledSize;
441}
442
443- (NSString *) tagline {
444 return [NSString stringWithCString:parser_->ShortDesc().c_str()];
445}
446
447- (NSString *) description {
448 return [NSString stringWithCString:parser_->LongDesc().c_str()];
449}
450
dc5812ec
JF
451- (NSComparisonResult) compareBySectionAndName:(Package *)package {
452 NSComparisonResult result = [[self section] compare:[package section]];
453 if (result != NSOrderedSame)
454 return result;
455 return [[self name] compare:[package name]];
456}
457
458- (void) install {
459 pkgProblemResolver *resolver = [database_ resolver];
460 resolver->Clear(iterator_);
461 resolver->Protect(iterator_);
462 [database_ cache]->MarkInstall(iterator_, false);
463}
464
465- (void) remove {
466 pkgProblemResolver *resolver = [database_ resolver];
467 resolver->Clear(iterator_);
468 resolver->Protect(iterator_);
469 resolver->Remove(iterator_);
2367a917 470 [database_ cache]->MarkDelete(iterator_, true);
dc5812ec
JF
471}
472
473@end
474/* }}} */
475/* Section Class {{{ */
476@interface Section : NSObject {
477 NSString *name_;
478 size_t row_;
479 NSMutableArray *packages_;
480}
481
2367a917
JF
482- (void) dealloc;
483
dc5812ec
JF
484- (Section *) initWithName:(NSString *)name row:(size_t)row;
485- (NSString *) name;
486- (size_t) row;
487- (void) addPackage:(Package *)package;
488@end
489
490@implementation Section
491
2367a917
JF
492- (void) dealloc {
493 [name_ release];
494 [packages_ release];
495 [super dealloc];
496}
497
dc5812ec
JF
498- (Section *) initWithName:(NSString *)name row:(size_t)row {
499 if ((self = [super init]) != nil) {
500 name_ = [name retain];
501 row_ = row;
502 packages_ = [[NSMutableArray arrayWithCapacity:16] retain];
503 } return self;
504}
505
506- (NSString *) name {
507 return name_;
508}
509
510- (size_t) row {
511 return row_;
512}
513
514- (void) addPackage:(Package *)package {
515 [packages_ addObject:package];
516}
517
518@end
519/* }}} */
520
521/* Confirmation View {{{ */
8fe19fc1
JF
522void AddTextView(NSMutableDictionary *fields, NSMutableArray *packages, NSString *key) {
523 if ([packages count] == 0)
524 return;
525
526 CGColorSpaceRef space = CGColorSpaceCreateDeviceRGB();
527 float clear[] = {0, 0, 0, 0};
528 float blue[] = {0, 0, 0.4, 1};
529
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];
537
538 CGRect frame([text frame]);
539 CGSize size([text contentSize]);
540 frame.size.height = size.height;
541 [text setFrame:frame];
542
543 [fields setObject:text forKey:key];
544}
545
3178d79b
JF
546@protocol ConfirmationViewDelegate
547- (void) cancel;
548- (void) confirm;
549@end
550
dc5812ec 551@interface ConfirmationView : UIView {
3178d79b
JF
552 Database *database_;
553 id delegate_;
554 UITransitionView *transition_;
555 UIView *overlay_;
556 UINavigationBar *navbar_;
557 UIPreferencesTable *table_;
8fe19fc1
JF
558 NSMutableDictionary *fields_;
559 UIAlertSheet *essential_;
dc5812ec
JF
560}
561
3178d79b 562- (void) dealloc;
8fe19fc1 563- (void) cancel;
3178d79b
JF
564
565- (void) transitionViewDidComplete:(UITransitionView*)view fromView:(UIView*)from toView:(UIView*)to;
566- (void) navigationBar:(UINavigationBar *)navbar buttonClicked:(int)button;
8fe19fc1
JF
567- (void) alertSheet:(UIAlertSheet *)sheet buttonClicked:(int)button;
568
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;
3178d79b
JF
574
575- (id) initWithView:(UIView *)view database:(Database *)database delegate:(id)delegate;
576
dc5812ec
JF
577@end
578
579@implementation ConfirmationView
3178d79b
JF
580
581- (void) dealloc {
582 [transition_ release];
583 [overlay_ release];
584 [navbar_ release];
585 [table_ release];
8fe19fc1
JF
586 [fields_ release];
587 if (essential_ != nil)
588 [essential_ release];
3178d79b
JF
589 [super dealloc];
590}
591
8fe19fc1
JF
592- (void) cancel {
593 [transition_ transition:7 toView:nil];
594 [delegate_ cancel];
595}
596
3178d79b
JF
597- (void) transitionViewDidComplete:(UITransitionView*)view fromView:(UIView*)from toView:(UIView*)to {
598 if (from != nil && to == nil)
599 [self removeFromSuperview];
600}
601
602- (void) navigationBar:(UINavigationBar *)navbar buttonClicked:(int)button {
603 switch (button) {
604 case 0:
8fe19fc1
JF
605 if (essential_ != nil)
606 [essential_ popupAlertAnimated:YES];
607 else
608 [delegate_ confirm];
3178d79b
JF
609 break;
610
611 case 1:
8fe19fc1 612 [self cancel];
3178d79b
JF
613 break;
614 }
615}
616
8fe19fc1
JF
617- (void) alertSheet:(UIAlertSheet *)sheet buttonClicked:(int)button {
618 [essential_ dismiss];
619 [self cancel];
620}
621
622- (int) numberOfGroupsInPreferencesTable:(UIPreferencesTable *)table {
623 return 2;
624}
625
626- (NSString *) preferencesTable:(UIPreferencesTable *)table titleForGroup:(int)group {
627 switch (group) {
628 case 0: return @"Statistics";
629 case 1: return @"Modifications";
630
631 default: _assert(false);
632 }
633}
634
635- (int) preferencesTable:(UIPreferencesTable *)table numberOfRowsInGroup:(int)group {
636 switch (group) {
637 case 0: return 3;
638 case 1: return [fields_ count];
639
640 default: _assert(false);
641 }
642}
643
644- (float) preferencesTable:(UIPreferencesTable *)table heightForRow:(int)row inGroup:(int)group withProposedHeight:(float)proposed {
645 if (group != 1 || row == -1)
646 return proposed;
647 else {
648 _assert(size_t(row) < [fields_ count]);
8fe19fc1
JF
649 return [[[fields_ allValues] objectAtIndex:row] contentSize].height;
650 }
651}
652
653- (UIPreferencesTableCell *) preferencesTable:(UIPreferencesTable *)table cellForRow:(int)row inGroup:(int)group {
654 UIPreferencesTableCell *cell = [[[UIPreferencesTableCell alloc] init] autorelease];
655 [cell setShowSelection:NO];
656
657 switch (group) {
658 case 0: switch (row) {
659 case 0: {
660 [cell setTitle:@"Downloading"];
661 [cell setValue:SizeString([database_ fetcher].FetchNeeded())];
662 } break;
663
664 case 1: {
665 [cell setTitle:@"Resuming At"];
666 [cell setValue:SizeString([database_ fetcher].PartialPresent())];
667 } break;
668
669 case 2: {
670 double size([database_ cache]->UsrSize());
671
672 if (size < 0) {
673 [cell setTitle:@"Disk Freeing"];
674 [cell setValue:SizeString(-size)];
675 } else {
676 [cell setTitle:@"Disk Using"];
677 [cell setValue:SizeString(size)];
678 }
679 } break;
680
681 default: _assert(false);
682 } break;
683
684 case 1:
685 _assert(size_t(row) < [fields_ count]);
686 [cell setTitle:[[fields_ allKeys] objectAtIndex:row]];
687 [cell addSubview:[[fields_ allValues] objectAtIndex:row]];
688 break;
689
690 default: _assert(false);
691 }
692
693 return cell;
694}
695
3178d79b
JF
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;
700
701 transition_ = [[UITransitionView alloc] initWithFrame:[self bounds]];
702 [self addSubview:transition_];
703
704 overlay_ = [[UIView alloc] initWithFrame:[transition_ bounds]];
705
706 CGSize navsize = [UINavigationBar defaultSize];
707 CGRect navrect = {{0, 0}, navsize};
708 CGRect bounds = [overlay_ bounds];
709
710 navbar_ = [[UINavigationBar alloc] initWithFrame:navrect];
711 [navbar_ setBarStyle:1];
712 [navbar_ setDelegate:self];
713
714 UINavigationItem *navitem = [[[UINavigationItem alloc] initWithTitle:@"Confirm"] autorelease];
715 [navbar_ pushNavigationItem:navitem];
716 [navbar_ showButtonsWithLeftTitle:@"Cancel" rightTitle:@"Confirm"];
717
8fe19fc1
JF
718 fields_ = [[NSMutableDictionary dictionaryWithCapacity:16] retain];
719
720 NSMutableArray *installing = [NSMutableArray arrayWithCapacity:16];
721 NSMutableArray *upgrading = [NSMutableArray arrayWithCapacity:16];
722 NSMutableArray *removing = [NSMutableArray arrayWithCapacity:16];
723
724 bool essential(false);
725
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)
736 essential = true;
737 }
738 }
739
740 if (!essential)
741 essential_ = nil;
742 else {
743 essential_ = [[UIAlertSheet alloc]
744 initWithTitle:@"Unable to Comply"
745 buttons:[NSArray arrayWithObjects:@"Okay", nil]
746 defaultButtonIndex:0
747 delegate:self
748 context:self
749 ];
750
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."];
752 }
753
754 AddTextView(fields_, installing, @"Installing");
755 AddTextView(fields_, upgrading, @"Upgrading");
756 AddTextView(fields_, removing, @"Removing");
757
3178d79b
JF
758 table_ = [[UIPreferencesTable alloc] initWithFrame:CGRectMake(
759 0, navsize.height, bounds.size.width, bounds.size.height - navsize.height
760 )];
761
8fe19fc1 762 [table_ setReusesTableCells:YES];
3178d79b 763 [table_ setDataSource:self];
8fe19fc1 764 [table_ reloadData];
3178d79b
JF
765
766 [overlay_ addSubview:navbar_];
767 [overlay_ addSubview:table_];
768
769 [view addSubview:self];
770
771 [transition_ setDelegate:self];
772
773 UIView *blank = [[[UIView alloc] initWithFrame:[transition_ bounds]] autorelease];
774 [transition_ transition:0 toView:blank];
775 [transition_ transition:3 toView:overlay_];
776 } return self;
777}
778
dc5812ec
JF
779@end
780/* }}} */
781/* Package View {{{ */
8da60fb7
JF
782@interface PackageView : UIView {
783 UIPreferencesTable *table_;
dc5812ec
JF
784 Package *package_;
785 Database *database_;
786 NSMutableArray *cells_;
8da60fb7 787 id delegate_;
dc5812ec
JF
788}
789
2367a917
JF
790- (void) dealloc;
791
dc5812ec 792- (int) numberOfGroupsInPreferencesTable:(UIPreferencesTable *)table;
8fe19fc1 793- (NSString *) preferencesTable:(UIPreferencesTable *)table titleForGroup:(int)group;
dc5812ec
JF
794- (int) preferencesTable:(UIPreferencesTable *)table numberOfRowsInGroup:(int)group;
795- (UIPreferencesTableCell *) preferencesTable:(UIPreferencesTable *)table cellForRow:(int)row inGroup:(int)group;
796
8da60fb7
JF
797- (BOOL) canSelectRow:(int)row;
798- (void) tableRowSelected:(NSNotification *)notification;
799
800- (id) initWithFrame:(struct CGRect)frame database:(Database *)database;
dc5812ec 801- (void) setPackage:(Package *)package;
8da60fb7 802- (void) setDelegate:(id)delegate;
dc5812ec
JF
803@end
804
805@implementation PackageView
806
2367a917
JF
807- (void) dealloc {
808 if (package_ != nil)
809 [package_ release];
8da60fb7 810 [table_ release];
2367a917
JF
811 [database_ release];
812 [cells_ release];
813 [super dealloc];
814}
815
dc5812ec
JF
816- (int) numberOfGroupsInPreferencesTable:(UIPreferencesTable *)table {
817 return 2;
818}
819
820- (NSString *) preferencesTable:(UIPreferencesTable *)table titleForGroup:(int)group {
821 switch (group) {
8fe19fc1
JF
822 case 0: return @"Specifics";
823 case 1: return @"Description";
dc5812ec
JF
824
825 default: _assert(false);
826 }
827}
828
829- (int) preferencesTable:(UIPreferencesTable *)table numberOfRowsInGroup:(int)group {
830 switch (group) {
8fe19fc1
JF
831 case 0: return 6;
832 case 1: return 1;
dc5812ec
JF
833
834 default: _assert(false);
835 }
836}
837
838- (UIPreferencesTableCell *) preferencesTable:(UIPreferencesTable *)table cellForRow:(int)row inGroup:(int)group {
839 UIPreferencesTableCell *cell;
840
841 switch (group) {
842 case 0: switch (row) {
843 case 0:
844 cell = [cells_ objectAtIndex:0];
845 [cell setTitle:@"Name"];
846 [cell setValue:[package_ name]];
847 break;
848
3178d79b 849 case 1: {
dc5812ec 850 cell = [cells_ objectAtIndex:1];
3178d79b
JF
851 [cell setTitle:@"Installed"];
852 NSString *installed([package_ installed]);
853 [cell setValue:(installed == nil ? @"n/a" : installed)];
854 } break;
dc5812ec
JF
855
856 case 2:
857 cell = [cells_ objectAtIndex:2];
3178d79b
JF
858 [cell setTitle:@"Latest"];
859 [cell setValue:[package_ latest]];
860 break;
861
862 case 3:
863 cell = [cells_ objectAtIndex:3];
dc5812ec
JF
864 [cell setTitle:@"Section"];
865 [cell setValue:[package_ section]];
866 break;
867
8fe19fc1 868 case 4:
3178d79b 869 cell = [cells_ objectAtIndex:4];
dc5812ec 870 [cell setTitle:@"Size"];
8fe19fc1
JF
871 [cell setValue:SizeString([package_ size])];
872 break;
dc5812ec 873
3178d79b
JF
874 case 5:
875 cell = [cells_ objectAtIndex:5];
dc5812ec
JF
876 [cell setTitle:@"Maintainer"];
877 [cell setValue:[[package_ maintainer] name]];
878 [cell setShowDisclosure:YES];
879 [cell setShowSelection:YES];
880 break;
881
882 default: _assert(false);
883 } break;
884
885 case 1: switch (row) {
886 case 0:
3178d79b 887 cell = [cells_ objectAtIndex:6];
2367a917 888 [cell setTitle:nil];
dc5812ec
JF
889 [cell setValue:[package_ tagline]];
890 break;
891
892 case 1:
3178d79b 893 cell = [cells_ objectAtIndex:7];
dc5812ec
JF
894 [cell setTitle:@"Description"];
895 [cell setValue:[package_ description]];
896 break;
897 } break;
898
899 default: _assert(false);
900 }
901
902 return cell;
903}
904
8da60fb7
JF
905- (BOOL) canSelectRow:(int)row {
906 return YES;
907}
908
909- (void) tableRowSelected:(NSNotification *)notification {
910 switch ([table_ selectedRow]) {
911 case 5:
912 [delegate_ openURL:[NSURL URLWithString:[NSString stringWithFormat:@"mailto:%@?subject=%@",
913 [[package_ maintainer] email],
914 [[NSString stringWithFormat:@"regarding apt package \"%@\"", [package_ name]] stringByAddingPercentEscapes]
915 ]]];
916 break;
917 }
918}
919
920- (id) initWithFrame:(struct CGRect)frame database:(Database *)database {
dc5812ec 921 if ((self = [super initWithFrame:frame]) != nil) {
2367a917 922 database_ = [database retain];
8da60fb7
JF
923
924 table_ = [[UIPreferencesTable alloc] initWithFrame:[self bounds]];
925 [self addSubview:table_];
926
927 [table_ setDataSource:self];
928 [table_ setDelegate:self];
dc5812ec
JF
929
930 cells_ = [[NSMutableArray arrayWithCapacity:16] retain];
931
3178d79b 932 for (unsigned i = 0; i != 8; ++i) {
2367a917 933 UIPreferencesTableCell *cell = [[[UIPreferencesTableCell alloc] init] autorelease];
dc5812ec
JF
934 [cell setShowSelection:NO];
935 [cells_ addObject:cell];
936 }
937 } return self;
938}
939
940- (void) setPackage:(Package *)package {
2367a917 941 package_ = [package retain];
8da60fb7
JF
942 [table_ reloadData];
943}
944
945- (void) setDelegate:(id)delegate {
946 delegate_ = delegate;
dc5812ec
JF
947}
948
2367a917
JF
949@end
950/* }}} */
951/* Package Cell {{{ */
8fe19fc1
JF
952@protocol PackageCellDelegate
953- (NSString *) versionWithPackage:(Package *)package;
954@end
955
2367a917
JF
956@interface PackageCell : UITableCell {
957 UITextLabel *name_;
958 UIRightTextLabel *version_;
959 UITextLabel *description_;
960}
961
962- (void) dealloc;
963
8fe19fc1 964- (PackageCell *) initWithPackage:(Package *)package delegate:(id)delegate;
2367a917
JF
965
966- (void) _setSelected:(float)fraction;
967- (void) setSelected:(BOOL)selected;
968- (void) setSelected:(BOOL)selected withFade:(BOOL)fade;
969- (void) _setSelectionFadeFraction:(float)fraction;
970
971@end
972
973@implementation PackageCell
974
975- (void) dealloc {
976 [name_ release];
977 [version_ release];
978 [description_ release];
979 [super dealloc];
980}
981
8fe19fc1 982- (PackageCell *) initWithPackage:(Package *)package delegate:(id)delegate {
2367a917
JF
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);
987
988 CGColorSpaceRef space = CGColorSpaceCreateDeviceRGB();
989 float clear[] = {0, 0, 0, 0};
990
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];
995
996 version_ = [[UIRightTextLabel alloc] initWithFrame:CGRectMake(290, 7, 70, 25)];
8fe19fc1 997 [version_ setText:[delegate versionWithPackage:package]];
2367a917
JF
998 [version_ setBackgroundColor:CGColorCreate(space, clear)];
999 [version_ setFont:large];
1000
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];
1005
1006 [self addSubview:name_];
1007 [self addSubview:version_];
1008 [self addSubview:description_];
1009
1010 CFRelease(small);
1011 CFRelease(large);
1012 CFRelease(bold);
1013 } return self;
1014}
1015
1016- (void) _setSelected:(float)fraction {
1017 CGColorSpaceRef space = CGColorSpaceCreateDeviceRGB();
1018
1019 float black[] = {
1020 interpolate(0.0, 1.0, fraction),
1021 interpolate(0.0, 1.0, fraction),
1022 interpolate(0.0, 1.0, fraction),
1023 1.0};
1024
1025 float blue[] = {
1026 interpolate(0.2, 1.0, fraction),
1027 interpolate(0.2, 1.0, fraction),
1028 interpolate(1.0, 1.0, fraction),
1029 1.0};
1030
1031 float gray[] = {
1032 interpolate(0.4, 1.0, fraction),
1033 interpolate(0.4, 1.0, fraction),
1034 interpolate(0.4, 1.0, fraction),
1035 1.0};
1036
1037 [name_ setColor:CGColorCreate(space, black)];
1038 [version_ setColor:CGColorCreate(space, blue)];
1039 [description_ setColor:CGColorCreate(space, gray)];
1040}
1041
1042- (void) setSelected:(BOOL)selected {
1043 [self _setSelected:(selected ? 1.0 : 0.0)];
1044 [super setSelected:selected];
1045}
1046
1047- (void) setSelected:(BOOL)selected withFade:(BOOL)fade {
1048 if (!fade)
1049 [self _setSelected:(selected ? 1.0 : 0.0)];
1050 [super setSelected:selected withFade:fade];
1051}
1052
1053- (void) _setSelectionFadeFraction:(float)fraction {
1054 [self _setSelected:fraction];
1055 [super _setSelectionFadeFraction:fraction];
1056}
1057
8da60fb7
JF
1058@end
1059/* }}} */
1060/* Sources View {{{ */
1061@interface SourcesView : ResetView {
1062 UISectionList *list_;
1063 Database *database_;
1064 id delegate_;
1065 NSMutableArray *sources_;
1066}
1067
1068- (void) navigationBar:(UINavigationBar *)navbar buttonClicked:(int)button;
1069- (void) dealloc;
1070- (id) initWithFrame:(CGRect)frame database:(Database *)database;
1071- (void) setDelegate:(id)delegate;
1072- (void) reloadData;
3178d79b
JF
1073- (NSString *) leftTitle;
1074- (NSString *) rightTitle;
8da60fb7
JF
1075@end
1076
1077@implementation SourcesView
1078
1079- (void) navigationBar:(UINavigationBar *)navbar buttonClicked:(int)button {
1080 switch (button) {
1081 case 0:
1082 break;
1083
1084 case 1:
1085 [delegate_ update];
1086 break;
1087 }
1088}
1089
1090- (void) dealloc {
1091 if (sources_ != nil)
1092 [sources_ release];
1093 [list_ release];
1094 [super dealloc];
1095}
1096
1097- (id) initWithFrame:(CGRect)frame database:(Database *)database {
1098 if ((self = [super initWithFrame:frame]) != nil) {
1099 database_ = database;
1100 sources_ = nil;
1101
1102 CGSize navsize = [UINavigationBar defaultSize];
1103 CGRect navrect = {{0, 0}, navsize};
1104 CGRect bounds = [self bounds];
1105
1106 navbar_ = [[UINavigationBar alloc] initWithFrame:navrect];
1107 [self addSubview:navbar_];
1108
1109 [navbar_ setBarStyle:1];
1110 [navbar_ setDelegate:self];
1111
1112 UINavigationItem *navitem = [[[UINavigationItem alloc] initWithTitle:@"Sources"] autorelease];
1113 [navbar_ pushNavigationItem:navitem];
1114
8da60fb7
JF
1115 list_ = [[UISectionList alloc] initWithFrame:CGRectMake(
1116 0, navsize.height, bounds.size.width, bounds.size.height - navsize.height
1117 )];
1118
1119 [list_ setDataSource:self];
3178d79b 1120 //[list_ setShouldHideHeaderInShortLists:NO];
8da60fb7
JF
1121 } return self;
1122}
1123
1124- (void) setDelegate:(id)delegate {
1125 delegate_ = delegate;
1126}
1127
1128- (void) reloadData {
1129 pkgSourceList list;
1130 _assert(list.ReadMainList());
1131
1132 sources_ = [[NSMutableArray arrayWithCapacity:16] retain];
1133
1134 for (pkgSourceList::const_iterator source = list.begin(); source != list.end(); ++source) {
3178d79b
JF
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");
1137
1138 debReleaseIndex *dindex(dynamic_cast<debReleaseIndex *>(index));
1139 if (dindex == NULL)
1140 continue;
1141
1142 fprintf(stderr, " \"%s\"\n", dindex->MetaIndexFile("Release").c_str());
1143
1144 std::ifstream release(dindex->MetaIndexFile("Release").c_str());
1145 std::string line;
1146 while (std::getline(release, line)) {
1147 std::string::size_type colon(line.find(':'));
1148 if (colon == std::string::npos)
1149 continue;
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;
1155 }
8da60fb7 1156 }
3178d79b
JF
1157
1158 [self resetView];
1159}
1160
1161- (NSString *) leftTitle {
1162 return @"Refresh All";
1163}
1164
1165- (NSString *) rightTitle {
1166 return @"Edit";
8da60fb7
JF
1167}
1168
dc5812ec
JF
1169@end
1170/* }}} */
1171
1172@implementation Database
1173
2367a917
JF
1174- (void) _readStatus:(NSNumber *)fd {
1175 NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
1176
1177 __gnu_cxx::stdio_filebuf<char> ib([fd intValue], std::ios::in);
1178 std::istream is(&ib);
1179 std::string line;
1180
1181 const char *error;
1182 int offset;
1183 pcre *code = pcre_compile("^([^:]*):([^:]*):([^:]*):(.*)$", 0, &error, &offset, NULL);
1184
1185 pcre_extra *study = NULL;
1186 int capture;
1187 pcre_fullinfo(code, study, PCRE_INFO_CAPTURECOUNT, &capture);
1188 int matches[(capture + 1) * 3];
1189
1190 while (std::getline(is, line)) {
1191 const char *data(line.c_str());
2367a917
JF
1192
1193 _assert(pcre_exec(code, study, data, line.size(), 0, 0, matches, sizeof(matches) / sizeof(matches[0])) >= 0);
1194
2367a917
JF
1195 std::istringstream buffer(line.substr(matches[6], matches[7] - matches[6]));
1196 float percent;
1197 buffer >> percent;
1198 [delegate_ setPercent:(percent / 100)];
1199
1200 NSString *string = [NSString stringWithCString:(data + matches[8]) length:(matches[9] - matches[8])];
8da60fb7 1201 std::string type(line.substr(matches[2], matches[3] - matches[2]));
2367a917
JF
1202
1203 if (type == "pmerror")
1204 [delegate_ setError:string];
1205 else if (type == "pmstatus")
1206 [delegate_ setTitle:string];
8da60fb7
JF
1207 else if (type == "pmconffile")
1208 ;
1209 else _assert(false);
2367a917
JF
1210 }
1211
1212 [pool release];
1213}
1214
1215- (void) _readOutput:(NSNumber *)fd {
1216 NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
1217
1218 __gnu_cxx::stdio_filebuf<char> ib([fd intValue], std::ios::in);
1219 std::istream is(&ib);
1220 std::string line;
1221
1222 while (std::getline(is, line))
1223 [delegate_ addOutput:[NSString stringWithCString:line.c_str()]];
1224
1225 [pool release];
1226}
1227
3178d79b
JF
1228- (Package *) packageWithName:(NSString *)name {
1229 pkgCache::PkgIterator iterator(cache_->FindPkg([name cString]));
1230 return iterator.end() ? nil : [Package packageWithIterator:iterator database:self];
1231}
1232
dc5812ec
JF
1233- (Database *) init {
1234 if ((self = [super init]) != nil) {
1235 records_ = NULL;
1236 resolver_ = NULL;
8fe19fc1
JF
1237 fetcher_ = NULL;
1238 lock_ = NULL;
2367a917
JF
1239
1240 int fds[2];
1241
1242 _assert(pipe(fds) != -1);
2367a917
JF
1243 statusfd_ = fds[1];
1244
1245 [NSThread
1246 detachNewThreadSelector:@selector(_readStatus:)
1247 toTarget:self
1248 withObject:[[NSNumber numberWithInt:fds[0]] retain]
1249 ];
1250
1251 _assert(pipe(fds) != -1);
2367a917
JF
1252 _assert(dup2(fds[1], 1) != -1);
1253 _assert(close(fds[1]) != -1);
1254
1255 [NSThread
1256 detachNewThreadSelector:@selector(_readOutput:)
1257 toTarget:self
1258 withObject:[[NSNumber numberWithInt:fds[0]] retain]
1259 ];
dc5812ec
JF
1260 } return self;
1261}
1262
1263- (pkgCacheFile &) cache {
1264 return cache_;
1265}
1266
1267- (pkgRecords *) records {
1268 return records_;
1269}
1270
1271- (pkgProblemResolver *) resolver {
1272 return resolver_;
1273}
1274
8fe19fc1
JF
1275- (pkgAcquire &) fetcher {
1276 return *fetcher_;
1277}
1278
dc5812ec 1279- (void) reloadData {
2367a917 1280 _error->Discard();
8fe19fc1
JF
1281 manager_ = NULL;
1282 delete lock_;
1283 delete fetcher_;
dc5812ec
JF
1284 delete resolver_;
1285 delete records_;
1286 cache_.Close();
1287 cache_.Open(progress_, true);
1288 records_ = new pkgRecords(cache_);
1289 resolver_ = new pkgProblemResolver(cache_);
8fe19fc1
JF
1290 fetcher_ = new pkgAcquire(&status_);
1291 lock_ = NULL;
dc5812ec
JF
1292}
1293
8fe19fc1 1294- (void) prepare {
2367a917
JF
1295 pkgRecords records(cache_);
1296
8fe19fc1
JF
1297 lock_ = new FileFd();
1298 lock_->Fd(GetLock(_config->FindDir("Dir::Cache::Archives") + "lock"));
2367a917
JF
1299 _assert(!_error->PendingError());
1300
2367a917
JF
1301 pkgSourceList list;
1302 _assert(list.ReadMainList());
1303
8fe19fc1
JF
1304 manager_ = (_system->CreatePM(cache_));
1305 _assert(manager_->GetArchives(fetcher_, &list, &records));
2367a917 1306 _assert(!_error->PendingError());
8fe19fc1
JF
1307}
1308
1309- (void) perform {
1310 if (fetcher_->Run(PulseInterval_) != pkgAcquire::Continue)
1311 return;
2367a917 1312
2367a917 1313 _system->UnLock();
8fe19fc1 1314 pkgPackageManager::OrderResult result = manager_->DoInstall(statusfd_);
dc5812ec 1315
2367a917
JF
1316 if (result == pkgPackageManager::Failed)
1317 return;
1318 if (_error->PendingError())
1319 return;
1320 if (result != pkgPackageManager::Completed)
1321 return;
1322}
1323
1324- (void) update {
dc5812ec
JF
1325 pkgSourceList list;
1326 _assert(list.ReadMainList());
1327
1328 FileFd lock;
1329 lock.Fd(GetLock(_config->FindDir("Dir::State::Lists") + "lock"));
1330 _assert(!_error->PendingError());
1331
1332 pkgAcquire fetcher(&status_);
1333 _assert(list.GetIndexes(&fetcher));
3178d79b 1334 _assert(fetcher.Run(PulseInterval_) != pkgAcquire::Failed);
dc5812ec
JF
1335
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();
1340 failed = true;
1341 }
1342
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/"));
1346 }
dc5812ec
JF
1347}
1348
1349- (void) upgrade {
dc5812ec
JF
1350 _assert(cache_->DelCount() == 0 && cache_->InstCount() == 0);
1351 _assert(pkgApplyStatus(cache_));
1352
1353 if (cache_->BrokenCount() != 0) {
1354 _assert(pkgFixBroken(cache_));
1355 _assert(cache_->BrokenCount() == 0);
1356 _assert(pkgMinimizeUpgrade(cache_));
1357 }
1358
1359 _assert(pkgDistUpgrade(cache_));
dc5812ec
JF
1360}
1361
1362- (void) setDelegate:(id)delegate {
2367a917 1363 delegate_ = delegate;
dc5812ec
JF
1364 status_.setDelegate(delegate);
1365 progress_.setDelegate(delegate);
1366}
1367
1368@end
1369
1370/* Progress Data {{{ */
1371@interface ProgressData : NSObject {
1372 SEL selector_;
1373 id target_;
1374 id object_;
1375}
1376
1377- (ProgressData *) initWithSelector:(SEL)selector target:(id)target object:(id)object;
1378
1379- (SEL) selector;
1380- (id) target;
1381- (id) object;
1382@end
1383
1384@implementation ProgressData
1385
1386- (ProgressData *) initWithSelector:(SEL)selector target:(id)target object:(id)object {
1387 if ((self = [super init]) != nil) {
1388 selector_ = selector;
1389 target_ = target;
1390 object_ = object;
1391 } return self;
1392}
1393
1394- (SEL) selector {
1395 return selector_;
1396}
1397
1398- (id) target {
1399 return target_;
1400}
1401
1402- (id) object {
1403 return object_;
1404}
1405
1406@end
1407/* }}} */
2367a917
JF
1408/* Progress View {{{ */
1409@interface ProgressView : UIView <
1410 ProgressDelegate
1411> {
dc5812ec 1412 UIView *view_;
8da60fb7 1413 UIView *background_;
dc5812ec 1414 UITransitionView *transition_;
2367a917 1415 UIView *overlay_;
dc5812ec 1416 UINavigationBar *navbar_;
2367a917
JF
1417 UIProgressBar *progress_;
1418 UITextView *output_;
1419 UITextLabel *status_;
1420 id delegate_;
1421 UIAlertSheet *alert_;
dc5812ec
JF
1422}
1423
2367a917
JF
1424- (void) dealloc;
1425
1426- (ProgressView *) initWithFrame:(struct CGRect)frame delegate:(id)delegate;
dc5812ec
JF
1427- (void) setContentView:(UIView *)view;
1428- (void) resetView;
1429
2367a917
JF
1430- (void) alertSheet:(UIAlertSheet *)sheet buttonClicked:(int)button;
1431
1432- (void) _retachThread;
dc5812ec
JF
1433- (void) _detachNewThreadData:(ProgressData *)data;
1434- (void) detachNewThreadSelector:(SEL)selector toTarget:(id)target withObject:(id)object;
1435
2367a917
JF
1436- (void) setError:(NSString *)error;
1437- (void) _setError:(NSString *)error;
1438
1439- (void) setTitle:(NSString *)title;
1440- (void) _setTitle:(NSString *)title;
1441
1442- (void) setPercent:(float)percent;
1443- (void) _setPercent:(NSNumber *)percent;
1444
1445- (void) addOutput:(NSString *)output;
1446- (void) _addOutput:(NSString *)output;
1447
dc5812ec 1448- (void) setStatusFail;
dc5812ec
JF
1449@end
1450
2367a917
JF
1451@protocol ProgressViewDelegate
1452- (void) progressViewIsComplete:(ProgressView *)sender;
1453@end
1454
dc5812ec
JF
1455@implementation ProgressView
1456
2367a917
JF
1457- (void) dealloc {
1458 [view_ release];
8da60fb7 1459 [background_ release];
2367a917
JF
1460 [transition_ release];
1461 [overlay_ release];
1462 [navbar_ release];
1463 [progress_ release];
1464 [output_ release];
1465 [status_ release];
1466 [super dealloc];
1467}
1468
1469- (ProgressView *) initWithFrame:(struct CGRect)frame delegate:(id)delegate {
dc5812ec 1470 if ((self = [super initWithFrame:frame]) != nil) {
2367a917
JF
1471 delegate_ = delegate;
1472 alert_ = nil;
1473
dc5812ec
JF
1474 CGColorSpaceRef space = CGColorSpaceCreateDeviceRGB();
1475 float black[] = {0.0, 0.0, 0.0, 1.0};
2367a917
JF
1476 float white[] = {1.0, 1.0, 1.0, 1.0};
1477 float clear[] = {0.0, 0.0, 0.0, 0.0};
1478
8da60fb7
JF
1479 background_ = [[UIView alloc] initWithFrame:[self bounds]];
1480 [background_ setBackgroundColor:CGColorCreate(space, black)];
1481 [self addSubview:background_];
1482
1483 transition_ = [[UITransitionView alloc] initWithFrame:[self bounds]];
1484 [self addSubview:transition_];
1485
2367a917 1486 overlay_ = [[UIView alloc] initWithFrame:[transition_ bounds]];
dc5812ec
JF
1487
1488 CGSize navsize = [UINavigationBar defaultSize];
1489 CGRect navrect = {{0, 0}, navsize};
1490
1491 navbar_ = [[UINavigationBar alloc] initWithFrame:navrect];
2367a917 1492 [overlay_ addSubview:navbar_];
dc5812ec
JF
1493
1494 [navbar_ setBarStyle:1];
1495 [navbar_ setDelegate:self];
1496
2367a917 1497 UINavigationItem *navitem = [[[UINavigationItem alloc] initWithTitle:@"Running..."] autorelease];
dc5812ec 1498 [navbar_ pushNavigationItem:navitem];
2367a917
JF
1499
1500 CGRect bounds = [overlay_ bounds];
1501 CGSize prgsize = [UIProgressBar defaultSize];
1502
1503 CGRect prgrect = {{
1504 (bounds.size.width - prgsize.width) / 2,
1505 bounds.size.height - prgsize.height - 20
1506 }, prgsize};
1507
1508 progress_ = [[UIProgressBar alloc] initWithFrame:prgrect];
1509 [overlay_ addSubview:progress_];
1510
1511 status_ = [[UITextLabel alloc] initWithFrame:CGRectMake(
1512 10,
1513 bounds.size.height - prgsize.height - 50,
1514 bounds.size.width - 20,
1515 24
1516 )];
1517
1518 [status_ setColor:CGColorCreate(space, white)];
1519 [status_ setBackgroundColor:CGColorCreate(space, clear)];
1520
1521 [status_ setCentersHorizontally:YES];
8da60fb7 1522 //[status_ setFont:font];
2367a917
JF
1523
1524 output_ = [[UITextView alloc] initWithFrame:CGRectMake(
1525 10,
1526 navrect.size.height + 20,
1527 bounds.size.width - 20,
1528 bounds.size.height - navsize.height - 62 - navrect.size.height
1529 )];
1530
1531 //[output_ setTextFont:@"Courier New"];
1532 [output_ setTextSize:12];
1533
1534 [output_ setTextColor:CGColorCreate(space, white)];
1535 [output_ setBackgroundColor:CGColorCreate(space, clear)];
1536
1537 [output_ setMarginTop:0];
1538 [output_ setAllowsRubberBanding:YES];
1539
1540 [overlay_ addSubview:output_];
1541 [overlay_ addSubview:status_];
1542
1543 [progress_ setStyle:0];
dc5812ec
JF
1544 } return self;
1545}
1546
1547- (void) setContentView:(UIView *)view {
1548 view_ = view;
1549}
1550
1551- (void) resetView {
1552 [transition_ transition:6 toView:view_];
2367a917
JF
1553}
1554
1555- (void) alertSheet:(UIAlertSheet *)sheet buttonClicked:(int)button {
1556 [alert_ dismiss];
1557 [alert_ release];
1558 alert_ = nil;
1559}
1560
1561- (void) _retachThread {
2367a917 1562 [delegate_ progressViewIsComplete:self];
2367a917 1563 [self resetView];
dc5812ec
JF
1564}
1565
1566- (void) _detachNewThreadData:(ProgressData *)data {
1567 NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
1568
1569 [[data target] performSelector:[data selector] withObject:[data object]];
2367a917 1570 [self performSelectorOnMainThread:@selector(_retachThread) withObject:nil waitUntilDone:YES];
dc5812ec 1571
2367a917 1572 [data release];
dc5812ec
JF
1573 [pool release];
1574}
1575
1576- (void) detachNewThreadSelector:(SEL)selector toTarget:(id)target withObject:(id)object {
2367a917
JF
1577 [status_ setText:nil];
1578 [output_ setText:@""];
1579 [progress_ setProgress:0];
1580
1581 [transition_ transition:6 toView:overlay_];
dc5812ec
JF
1582
1583 [NSThread
1584 detachNewThreadSelector:@selector(_detachNewThreadData:)
1585 toTarget:self
1586 withObject:[[ProgressData alloc]
1587 initWithSelector:selector
1588 target:target
1589 object:object
1590 ]
1591 ];
1592}
1593
dc5812ec 1594- (void) setStatusFail {
dc5812ec
JF
1595}
1596
2367a917
JF
1597- (void) setError:(NSString *)error {
1598 [self
1599 performSelectorOnMainThread:@selector(_setError:)
1600 withObject:error
1601 waitUntilDone:YES
1602 ];
1603}
1604
1605- (void) _setError:(NSString *)error {
1606 _assert(alert_ == nil);
1607
1608 alert_ = [[UIAlertSheet alloc]
1609 initWithTitle:@"Package Error"
1610 buttons:[NSArray arrayWithObjects:@"Okay", nil]
1611 defaultButtonIndex:0
1612 delegate:self
1613 context:self
1614 ];
1615
1616 [alert_ setBodyText:error];
1617 [alert_ popupAlertAnimated:YES];
1618}
1619
1620- (void) setTitle:(NSString *)title {
1621 [self
1622 performSelectorOnMainThread:@selector(_setTitle:)
1623 withObject:title
1624 waitUntilDone:YES
1625 ];
1626}
1627
1628- (void) _setTitle:(NSString *)title {
1629 [status_ setText:[title stringByAppendingString:@"..."]];
1630}
1631
1632- (void) setPercent:(float)percent {
1633 [self
1634 performSelectorOnMainThread:@selector(_setPercent:)
1635 withObject:[NSNumber numberWithFloat:percent]
1636 waitUntilDone:YES
1637 ];
1638}
1639
1640- (void) _setPercent:(NSNumber *)percent {
1641 [progress_ setProgress:[percent floatValue]];
1642}
1643
1644- (void) addOutput:(NSString *)output {
1645 [self
1646 performSelectorOnMainThread:@selector(_addOutput:)
1647 withObject:output
1648 waitUntilDone:YES
1649 ];
1650}
1651
1652- (void) _addOutput:(NSString *)output {
1653 [output_ setText:[NSString stringWithFormat:@"%@\n%@", [output_ text], output]];
8da60fb7
JF
1654 CGSize size = [output_ contentSize];
1655 CGRect rect = {{0, size.height}, {size.width, 0}};
1656 [output_ scrollRectToVisible:rect animated:YES];
dc5812ec
JF
1657}
1658
1659@end
2367a917 1660/* }}} */
dc5812ec 1661
3178d79b 1662@protocol PackagesViewDelegate
2367a917 1663- (void) perform;
8da60fb7
JF
1664- (void) update;
1665- (void) openURL:(NSString *)url;
dc5812ec
JF
1666@end
1667
3178d79b 1668/* PackagesView {{{ */
8fe19fc1
JF
1669@interface PackagesView : ResetView <
1670 PackageCellDelegate
1671> {
dc5812ec 1672 Database *database_;
dc5812ec
JF
1673 NSMutableArray *packages_;
1674 NSMutableArray *sections_;
1675 id delegate_;
1676 UISectionList *list_;
dc5812ec
JF
1677 UITransitionView *transition_;
1678 Package *package_;
8fe19fc1 1679 NSString *pkgname_;
dc5812ec 1680 PackageView *pkgview_;
dc5812ec
JF
1681}
1682
1683- (int) numberOfSectionsInSectionList:(UISectionList *)list;
1684- (NSString *) sectionList:(UISectionList *)list titleForSection:(int)section;
1685- (int) sectionList:(UISectionList *)list rowForSection:(int)section;
1686
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;
1692
1693- (void) navigationBar:(UINavigationBar *)navbar buttonClicked:(int)button;
1694- (void) navigationBar:(UINavigationBar *)navbar poppedItem:(UINavigationItem *)item;
1695
3178d79b 1696- (id) initWithFrame:(struct CGRect)frame database:(Database *)database;
dc5812ec 1697- (void) setDelegate:(id)delegate;
2367a917 1698- (void) deselect;
8fe19fc1 1699- (void) reloadData:(BOOL)reset;
3178d79b 1700
c25a610d 1701- (NSMutableArray *) packages;
3178d79b
JF
1702- (NSString *) title;
1703- (void) perform:(Package *)package;
1704- (void) addPackage:(Package *)package;
8fe19fc1 1705- (NSString *) versionWithPackage:(Package *)package;
dc5812ec
JF
1706@end
1707
3178d79b 1708@implementation PackagesView
dc5812ec
JF
1709
1710- (int) numberOfSectionsInSectionList:(UISectionList *)list {
1711 return [sections_ count];
1712}
1713
1714- (NSString *) sectionList:(UISectionList *)list titleForSection:(int)section {
1715 return [[sections_ objectAtIndex:section] name];
1716}
1717
1718- (int) sectionList:(UISectionList *)list rowForSection:(int)section {
1719 return [[sections_ objectAtIndex:section] row];
1720}
1721
1722- (int) numberOfRowsInTable:(UITable *)table {
1723 return [packages_ count];
1724}
1725
1726- (float) table:(UITable *)table heightForRow:(int)row {
1727 return 64;
1728}
1729
1730- (UITableCell *) table:(UITable *)table cellForRow:(int)row column:(UITableColumn *)col {
2367a917 1731 Package *package = [packages_ objectAtIndex:row];
8fe19fc1 1732 PackageCell *cell = [[[PackageCell alloc] initWithPackage:package delegate:self] autorelease];
dc5812ec
JF
1733 return cell;
1734}
1735
1736- (BOOL) table:(UITable *)table showDisclosureForRow:(int)row {
1737 return YES;
1738}
1739
1740- (void) tableRowSelected:(NSNotification*)notification {
1741 int row = [[list_ table] selectedRow];
1742 if (row == INT_MAX)
1743 return;
1744
1745 package_ = [packages_ objectAtIndex:row];
8fe19fc1 1746 pkgname_ = [[package_ name] retain];
dc5812ec
JF
1747
1748 UINavigationItem *navitem = [[UINavigationItem alloc] initWithTitle:[package_ name]];
1749 [navbar_ pushNavigationItem:navitem];
1750
3178d79b 1751 [navbar_ showButtonsWithLeftTitle:nil rightTitle:[self title]];
dc5812ec
JF
1752
1753 [pkgview_ setPackage:package_];
1754 [transition_ transition:1 toView:pkgview_];
dc5812ec
JF
1755}
1756
1757- (void) navigationBar:(UINavigationBar *)navbar buttonClicked:(int)button {
1758 if (button == 0) {
3178d79b 1759 [self perform:package_];
dc5812ec
JF
1760
1761 pkgProblemResolver *resolver = [database_ resolver];
1762
1763 resolver->InstallProtect();
1764 if (!resolver->Resolve(true))
1765 _error->Discard();
1766
2367a917 1767 [delegate_ perform];
dc5812ec
JF
1768 }
1769}
1770
1771- (void) navigationBar:(UINavigationBar *)navbar poppedItem:(UINavigationItem *)item {
2367a917 1772 [self deselect];
3178d79b 1773 [super navigationBar:navbar poppedItem:item];
dc5812ec
JF
1774}
1775
3178d79b 1776- (id) initWithFrame:(struct CGRect)frame database:(Database *)database {
dc5812ec 1777 if ((self = [super initWithFrame:frame]) != nil) {
2367a917 1778 database_ = [database retain];
dc5812ec 1779
dc5812ec
JF
1780 struct CGRect bounds = [self bounds];
1781 CGSize navsize = [UINavigationBar defaultSize];
1782 CGRect navrect = {{0, 0}, navsize};
1783
1784 navbar_ = [[UINavigationBar alloc] initWithFrame:navrect];
1785 [self addSubview:navbar_];
1786
1787 [navbar_ setBarStyle:1];
1788 [navbar_ setDelegate:self];
1789
3178d79b 1790 UINavigationItem *navitem = [[[UINavigationItem alloc] initWithTitle:[self title]] autorelease];
dc5812ec
JF
1791 [navbar_ pushNavigationItem:navitem];
1792 [navitem setBackButtonTitle:@"Packages"];
1793
1794 transition_ = [[UITransitionView alloc] initWithFrame:CGRectMake(
1795 bounds.origin.x, bounds.origin.y + navsize.height, bounds.size.width, bounds.size.height - navsize.height
1796 )];
1797
1798 [self addSubview:transition_];
1799
1800 list_ = [[UISectionList alloc] initWithFrame:[transition_ bounds] showSectionIndex:NO];
1801 [list_ setDataSource:self];
3178d79b 1802 [list_ setShouldHideHeaderInShortLists:NO];
dc5812ec
JF
1803
1804 [transition_ transition:0 toView:list_];
1805
1806 UITableColumn *column = [[UITableColumn alloc]
1807 initWithTitle:@"Name"
1808 identifier:@"name"
1809 width:frame.size.width
1810 ];
1811
1812 UITable *table = [list_ table];
1813 [table setSeparatorStyle:1];
1814 [table addTableColumn:column];
1815 [table setDelegate:self];
1816
1817 pkgview_ = [[PackageView alloc] initWithFrame:[transition_ bounds] database:database_];
1818 } return self;
1819}
1820
1821- (void) setDelegate:(id)delegate {
1822 delegate_ = delegate;
8da60fb7 1823 [pkgview_ setDelegate:delegate];
dc5812ec
JF
1824}
1825
2367a917 1826- (void) deselect {
8da60fb7 1827 [transition_ transition:(resetting_ ? 0 : 2) toView:list_];
2367a917 1828 UITable *table = [list_ table];
8da60fb7 1829 [table selectRow:-1 byExtendingSelection:NO withFade:(resetting_ ? NO : YES)];
2367a917 1830 package_ = nil;
dc5812ec
JF
1831}
1832
8fe19fc1 1833- (void) reloadData:(BOOL)reset {
2367a917
JF
1834 packages_ = [[NSMutableArray arrayWithCapacity:16] retain];
1835
2367a917
JF
1836 if (sections_ != nil) {
1837 [sections_ release];
1838 sections_ = nil;
1839 }
1840
3178d79b
JF
1841 for (pkgCache::PkgIterator iterator = [database_ cache]->PkgBegin(); !iterator.end(); ++iterator)
1842 if (Package *package = [Package packageWithIterator:iterator database:database_])
1843 [self addPackage:package];
dc5812ec
JF
1844
1845 [packages_ sortUsingSelector:@selector(compareBySectionAndName:)];
1846 sections_ = [[NSMutableArray arrayWithCapacity:16] retain];
1847
1848 Section *section = nil;
1849 for (size_t offset = 0, count = [packages_ count]; offset != count; ++offset) {
1850 Package *package = [packages_ objectAtIndex:offset];
1851 NSString *name = [package section];
1852
1853 if (section == nil || ![[section name] isEqual:name]) {
1854 section = [[Section alloc] initWithName:name row:offset];
1855 [sections_ addObject:section];
1856 }
1857
1858 [section addPackage:package];
1859 }
1860
1861 [list_ reloadData];
8fe19fc1
JF
1862 if (reset)
1863 [self resetView];
1864 else if (package_ != nil) {
1865 package_ = [database_ packageWithName:pkgname_];
1866 [pkgview_ setPackage:package_];
1867 }
dc5812ec
JF
1868}
1869
c25a610d
JF
1870- (NSMutableArray *) packages {
1871 return packages_;
1872}
1873
3178d79b
JF
1874- (NSString *) title {
1875 return nil;
1876}
1877
1878- (void) perform:(Package *)package {
1879}
1880
1881- (void) addPackage:(Package *)package {
1882 [packages_ addObject:package];
1883}
1884
8fe19fc1
JF
1885- (NSString *) versionWithPackage:(Package *)package {
1886 return nil;
1887}
1888
3178d79b
JF
1889@end
1890/* }}} */
1891
1892/* InstallView {{{ */
1893@interface InstallView : PackagesView {
1894}
1895
1896- (NSString *) title;
1897- (void) addPackage:(Package *)package;
1898- (void) perform:(Package *)package;
8fe19fc1 1899- (NSString *) versionWithPackage:(Package *)package;
3178d79b
JF
1900@end
1901
1902@implementation InstallView
1903
1904- (NSString *) title {
1905 return @"Install";
1906}
1907
1908- (void) addPackage:(Package *)package {
1909 if ([package installed] == nil)
1910 [super addPackage:package];
1911}
1912
1913- (void) perform:(Package *)package {
1914 [package install];
1915}
1916
8fe19fc1
JF
1917- (NSString *) versionWithPackage:(Package *)package {
1918 return [package latest];
1919}
1920
3178d79b
JF
1921@end
1922/* }}} */
1923/* UpgradeView {{{ */
1924@interface UpgradeView : PackagesView {
1925}
1926
74127566
JF
1927- (void) navigationBar:(UINavigationBar *)navbar buttonClicked:(int)button;
1928
3178d79b
JF
1929- (NSString *) title;
1930- (NSString *) leftTitle;
1931- (void) addPackage:(Package *)package;
1932- (void) perform:(Package *)package;
8fe19fc1 1933- (NSString *) versionWithPackage:(Package *)package;
3178d79b
JF
1934@end
1935
1936@implementation UpgradeView
1937
74127566
JF
1938- (void) navigationBar:(UINavigationBar *)navbar buttonClicked:(int)button {
1939 if (button != 1)
1940 [super navigationBar:navbar buttonClicked:button];
1941 else {
1942 [database_ upgrade];
1943 [delegate_ perform];
1944 }
1945}
1946
3178d79b
JF
1947- (NSString *) title {
1948 return @"Upgrade";
1949}
1950
1951- (NSString *) leftTitle {
1952 return @"Upgrade All";
1953}
1954
1955- (void) addPackage:(Package *)package {
1956 NSString *installed = [package installed];
1957 if (installed != nil && [[package latest] compare:installed] != NSOrderedSame)
1958 [super addPackage:package];
1959}
1960
1961- (void) perform:(Package *)package {
1962 [package install];
1963}
1964
8fe19fc1
JF
1965- (NSString *) versionWithPackage:(Package *)package {
1966 return [package latest];
1967}
1968
3178d79b
JF
1969@end
1970/* }}} */
1971/* UninstallView {{{ */
1972@interface UninstallView : PackagesView {
1973}
1974
1975- (NSString *) title;
1976- (void) addPackage:(Package *)package;
1977- (void) perform:(Package *)package;
8fe19fc1 1978- (NSString *) versionWithPackage:(Package *)package;
dc5812ec
JF
1979@end
1980
3178d79b
JF
1981@implementation UninstallView
1982
1983- (NSString *) title {
1984 return @"Uninstall";
dc5812ec
JF
1985}
1986
3178d79b
JF
1987- (void) addPackage:(Package *)package {
1988 if ([package installed] != nil)
1989 [super addPackage:package];
dc5812ec
JF
1990}
1991
3178d79b
JF
1992- (void) perform:(Package *)package {
1993 [package remove];
1994}
1995
8fe19fc1
JF
1996- (NSString *) versionWithPackage:(Package *)package {
1997 return [package installed];
1998}
1999
3178d79b
JF
2000@end
2001/* }}} */
2002
2367a917 2003@interface Cydia : UIApplication <
3178d79b
JF
2004 ConfirmationViewDelegate,
2005 PackagesViewDelegate,
2367a917
JF
2006 ProgressViewDelegate
2007> {
dc5812ec 2008 UIWindow *window_;
3178d79b
JF
2009 UIView *underlay_;
2010 UIView *overlay_;
dc5812ec 2011 UITransitionView *transition_;
2367a917 2012 UIButtonBar *buttonbar_;
3178d79b 2013
2367a917 2014 UIAlertSheet *alert_;
3178d79b 2015 ConfirmationView *confirm_;
dc5812ec
JF
2016
2017 Database *database_;
2018 ProgressView *progress_;
2019
2020 UIView *featured_;
2021 UINavigationBar *navbar_;
2022 UIScroller *scroller_;
2023 UIWebView *webview_;
2024 NSURL *url_;
2025
3178d79b
JF
2026 InstallView *install_;
2027 UpgradeView *upgrade_;
2028 UninstallView *uninstall_;
8da60fb7 2029 SourcesView *sources_;
dc5812ec
JF
2030}
2031
2032- (void) loadNews;
8fe19fc1 2033- (void) reloadData:(BOOL)reset;
2367a917 2034- (void) perform;
3178d79b
JF
2035- (void) cancel;
2036- (void) confirm;
8da60fb7 2037- (void) update;
2367a917
JF
2038
2039- (void) progressViewIsComplete:(ProgressView *)progress;
dc5812ec
JF
2040
2041- (void) navigationBar:(UINavigationBar *)navbar buttonClicked:(int)button;
2367a917 2042- (void) alertSheet:(UIAlertSheet *)sheet buttonClicked:(int)button;
dc5812ec
JF
2043- (void) buttonBarItemTapped:(id)sender;
2044
2045- (void) view:(UIView *)sender didSetFrame:(CGRect)frame;
2046- (void) view:(UIView *)view didDrawInRect:(CGRect)rect duration:(float)duration;
2047
dc5812ec
JF
2048- (void) applicationDidFinishLaunching:(id)unused;
2049@end
2050
3178d79b
JF
2051#include <objc/objc-class.h>
2052
dc5812ec
JF
2053@implementation Cydia
2054
2055- (void) loadNews {
3178d79b 2056 NSMutableURLRequest *request = [NSMutableURLRequest
dc5812ec
JF
2057 requestWithURL:url_
2058 cachePolicy:NSURLRequestReloadIgnoringCacheData
2059 timeoutInterval:30.0
3178d79b
JF
2060 ];
2061
2062 [request addValue:[NSString stringWithCString:Machine_] forHTTPHeaderField:@"X-Machine"];
2063 [request addValue:[NSString stringWithCString:SerialNumber_] forHTTPHeaderField:@"X-Serial-Number"];
2064
2065 [webview_ loadRequest:request];
dc5812ec
JF
2066}
2067
8fe19fc1 2068- (void) reloadData:(BOOL)reset {
dc5812ec 2069 [database_ reloadData];
8fe19fc1
JF
2070 [install_ reloadData:reset];
2071 [upgrade_ reloadData:reset];
2072 [uninstall_ reloadData:reset];
8da60fb7 2073 [sources_ reloadData];
c25a610d
JF
2074
2075 if (size_t count = [[upgrade_ packages] count]) {
2076 NSString *badge([[NSNumber numberWithInt:count] stringValue]);
2077 [buttonbar_ setBadgeValue:badge forButton:3];
2078 [buttonbar_ setBadgeAnimated:YES forButton:3];
2079 [self setApplicationBadge:badge];
2080 } else {
2081 [buttonbar_ setBadgeValue:nil forButton:3];
2082 [buttonbar_ setBadgeAnimated:NO forButton:3];
2083 [self removeApplicationBadge];
2084 }
2367a917
JF
2085}
2086
2087- (void) perform {
8fe19fc1 2088 [database_ prepare];
3178d79b
JF
2089 confirm_ = [[ConfirmationView alloc] initWithView:underlay_ database:database_ delegate:self];
2090}
2091
2092- (void) cancel {
8fe19fc1 2093 [self reloadData:NO];
3178d79b
JF
2094 [confirm_ release];
2095 confirm_ = nil;
2096}
2097
2098- (void) confirm {
2099 [overlay_ removeFromSuperview];
2100
2367a917
JF
2101 [progress_
2102 detachNewThreadSelector:@selector(perform)
2103 toTarget:database_
2104 withObject:nil
2105 ];
2106}
2107
8da60fb7
JF
2108- (void) update {
2109 [progress_
2110 detachNewThreadSelector:@selector(update)
2111 toTarget:database_
2112 withObject:nil
2113 ];
2114}
2115
2367a917 2116- (void) progressViewIsComplete:(ProgressView *)progress {
8fe19fc1 2117 [self reloadData:YES];
3178d79b
JF
2118
2119 if (confirm_ != nil) {
2120 [underlay_ addSubview:overlay_];
2121 [confirm_ removeFromSuperview];
2122 [confirm_ release];
2123 confirm_ = nil;
2124 }
dc5812ec
JF
2125}
2126
2127- (void) navigationBar:(UINavigationBar *)navbar buttonClicked:(int)button {
2128 switch (button) {
2129 case 0:
2130 [self loadNews];
2131 break;
2132
2133 case 1:
2367a917
JF
2134 _assert(alert_ == nil);
2135
2136 alert_ = [[UIAlertSheet alloc]
2137 initWithTitle:@"About Cydia Packager"
2138 buttons:[NSArray arrayWithObjects:@"Close", nil]
2139 defaultButtonIndex:0
2140 delegate:self
2141 context:self
2142 ];
2143
2144 [alert_ setBodyText:
2145 @"Copyright (C) 2007\n"
2146 "Jay Freeman (saurik)\n"
2147 "saurik@saurik.com\n"
2148 "http://www.saurik.com/\n"
2149 "\n"
2150 "The Okori Group\n"
2151 "http://www.theokorigroup.com/\n"
2152 "\n"
2153 "College of Creative Studies,\n"
2154 "University of California,\n"
2155 "Santa Barbara\n"
2156 "http://www.ccs.ucsb.edu/\n"
2157 "\n"
2158 "Special Thanks:\n"
2159 "bad_, BHSPitMonkey, Cobra, core,\n"
2160 "Corona, cromas, Darken, dtzWill,\n"
2161 "francis, Godores, jerry, Kingstone,\n"
2162 "lounger, rockabilly, tman, Wbiggs"
2163 ];
2164
2165 [alert_ presentSheetFromButtonBar:buttonbar_];
dc5812ec
JF
2166 break;
2167 }
2168}
2169
2367a917
JF
2170- (void) alertSheet:(UIAlertSheet *)sheet buttonClicked:(int)button {
2171 [alert_ dismiss];
2172 [alert_ release];
2173 alert_ = nil;
2174}
2175
dc5812ec
JF
2176- (void) buttonBarItemTapped:(id)sender {
2177 UIView *view;
2178
2179 switch ([sender tag]) {
2180 case 1: view = featured_; break;
2181 case 2: view = install_; break;
3178d79b 2182 case 3: view = upgrade_; break;
dc5812ec 2183 case 4: view = uninstall_; break;
8da60fb7 2184 case 5: view = sources_; break;
dc5812ec
JF
2185
2186 default:
2187 _assert(false);
2188 }
2189
8da60fb7
JF
2190 if ([view respondsToSelector:@selector(resetView)])
2191 [(id) view resetView];
dc5812ec
JF
2192 [transition_ transition:0 toView:view];
2193}
2194
2195- (void) view:(UIView *)view didSetFrame:(CGRect)frame {
2196 [scroller_ setContentSize:frame.size];
2197}
2198
2199- (void) view:(UIView *)view didDrawInRect:(CGRect)rect duration:(float)duration {
2200 [scroller_ setContentSize:[webview_ bounds].size];
2201}
2202
dc5812ec
JF
2203- (void) applicationDidFinishLaunching:(id)unused {
2204 _assert(pkgInitConfig(*_config));
2205 _assert(pkgInitSystem(*_config, _system));
2206
3178d79b
JF
2207 alert_ = nil;
2208 confirm_ = nil;
2209
dc5812ec
JF
2210 CGRect screenrect = [UIHardware fullScreenApplicationContentRect];
2211 window_ = [[UIWindow alloc] initWithContentRect:screenrect];
2212
2213 [window_ orderFront: self];
2214 [window_ makeKey: self];
2215 [window_ _setHidden: NO];
2216
2367a917 2217 progress_ = [[ProgressView alloc] initWithFrame:[window_ bounds] delegate:self];
dc5812ec
JF
2218 [window_ setContentView:progress_];
2219
3178d79b
JF
2220 underlay_ = [[UIView alloc] initWithFrame:[progress_ bounds]];
2221 [progress_ setContentView:underlay_];
2222
2223 overlay_ = [[UIView alloc] initWithFrame:[underlay_ bounds]];
2224 [underlay_ addSubview:overlay_];
dc5812ec
JF
2225
2226 transition_ = [[UITransitionView alloc] initWithFrame:CGRectMake(
2227 0, 0, screenrect.size.width, screenrect.size.height - 48
2228 )];
2229
3178d79b 2230 [overlay_ addSubview:transition_];
dc5812ec
JF
2231
2232 featured_ = [[UIView alloc] initWithFrame:[transition_ bounds]];
2233
2234 CGSize navsize = [UINavigationBar defaultSize];
2235 CGRect navrect = {{0, 0}, navsize};
2236
2237 navbar_ = [[UINavigationBar alloc] initWithFrame:navrect];
2238 [featured_ addSubview:navbar_];
2239
2240 [navbar_ setBarStyle:1];
2241 [navbar_ setDelegate:self];
2242
2243 [navbar_ showButtonsWithLeftTitle:@"About" rightTitle:@"Reload"];
2244
2245 UINavigationItem *navitem = [[UINavigationItem alloc] initWithTitle:@"Featured"];
2246 [navbar_ pushNavigationItem:navitem];
2247
2248 struct CGRect subbounds = [featured_ bounds];
2249 subbounds.origin.y += navsize.height;
2250 subbounds.size.height -= navsize.height;
2251
2252 UIImageView *pinstripe = [[UIImageView alloc] initWithFrame:subbounds];
2253 [pinstripe setImage:[UIImage applicationImageNamed:@"pinstripe.png"]];
2254 [featured_ addSubview:pinstripe];
2255
2256 scroller_ = [[UIScroller alloc] initWithFrame:subbounds];
2257 [featured_ addSubview:scroller_];
2258
2259 [scroller_ setScrollingEnabled:YES];
2260 [scroller_ setAdjustForContentSizeChange:YES];
2261 [scroller_ setClipsSubviews:YES];
2262 [scroller_ setAllowsRubberBanding:YES];
2263 [scroller_ setScrollDecelerationFactor:0.99];
2264 [scroller_ setDelegate:self];
2265
2266 webview_ = [[UIWebView alloc] initWithFrame:[scroller_ bounds]];
2267 [scroller_ addSubview:webview_];
2268
2269 [webview_ setTilingEnabled:YES];
2270 [webview_ setTileSize:CGSizeMake(screenrect.size.width, 500)];
2271 [webview_ setAutoresizes:YES];
2272 [webview_ setDelegate:self];
2273
dc5812ec
JF
2274 NSArray *buttonitems = [NSArray arrayWithObjects:
2275 [NSDictionary dictionaryWithObjectsAndKeys:
2276 @"buttonBarItemTapped:", kUIButtonBarButtonAction,
2277 @"featured-up.png", kUIButtonBarButtonInfo,
2278 @"featured-dn.png", kUIButtonBarButtonSelectedInfo,
2279 [NSNumber numberWithInt:1], kUIButtonBarButtonTag,
2280 self, kUIButtonBarButtonTarget,
2281 @"Featured", kUIButtonBarButtonTitle,
2282 @"0", kUIButtonBarButtonType,
2283 nil],
2284
2285 [NSDictionary dictionaryWithObjectsAndKeys:
2286 @"buttonBarItemTapped:", kUIButtonBarButtonAction,
2287 @"install-up.png", kUIButtonBarButtonInfo,
2288 @"install-dn.png", kUIButtonBarButtonSelectedInfo,
2289 [NSNumber numberWithInt:2], kUIButtonBarButtonTag,
2290 self, kUIButtonBarButtonTarget,
2291 @"Install", kUIButtonBarButtonTitle,
2292 @"0", kUIButtonBarButtonType,
2293 nil],
2294
2295 [NSDictionary dictionaryWithObjectsAndKeys:
2296 @"buttonBarItemTapped:", kUIButtonBarButtonAction,
2297 @"upgrade-up.png", kUIButtonBarButtonInfo,
2298 @"upgrade-dn.png", kUIButtonBarButtonSelectedInfo,
2299 [NSNumber numberWithInt:3], kUIButtonBarButtonTag,
2300 self, kUIButtonBarButtonTarget,
2301 @"Upgrade", kUIButtonBarButtonTitle,
2302 @"0", kUIButtonBarButtonType,
2303 nil],
2304
2305 [NSDictionary dictionaryWithObjectsAndKeys:
2306 @"buttonBarItemTapped:", kUIButtonBarButtonAction,
2307 @"uninstall-up.png", kUIButtonBarButtonInfo,
2308 @"uninstall-dn.png", kUIButtonBarButtonSelectedInfo,
2309 [NSNumber numberWithInt:4], kUIButtonBarButtonTag,
2310 self, kUIButtonBarButtonTarget,
2311 @"Uninstall", kUIButtonBarButtonTitle,
2312 @"0", kUIButtonBarButtonType,
2313 nil],
2314
2315 [NSDictionary dictionaryWithObjectsAndKeys:
2316 @"buttonBarItemTapped:", kUIButtonBarButtonAction,
2317 @"sources-up.png", kUIButtonBarButtonInfo,
2318 @"sources-dn.png", kUIButtonBarButtonSelectedInfo,
2319 [NSNumber numberWithInt:5], kUIButtonBarButtonTag,
2320 self, kUIButtonBarButtonTarget,
2321 @"Sources", kUIButtonBarButtonTitle,
2322 @"0", kUIButtonBarButtonType,
2323 nil],
2324 nil];
2325
2367a917 2326 buttonbar_ = [[UIButtonBar alloc]
3178d79b 2327 initInView:overlay_
dc5812ec
JF
2328 withFrame:CGRectMake(
2329 0, screenrect.size.height - 48,
2330 screenrect.size.width, 48
2331 )
2332 withItemList:buttonitems
2333 ];
2334
2367a917
JF
2335 [buttonbar_ setDelegate:self];
2336 [buttonbar_ setBarStyle:1];
2337 [buttonbar_ setButtonBarTrackingMode:2];
dc5812ec
JF
2338
2339 int buttons[5] = {1, 2, 3, 4, 5};
2367a917
JF
2340 [buttonbar_ registerButtonGroup:0 withButtons:buttons withCount:5];
2341 [buttonbar_ showButtonGroup:0 withDuration:0];
dc5812ec
JF
2342
2343 for (int i = 0; i != 5; ++i)
2367a917 2344 [[buttonbar_ viewWithTag:(i + 1)] setFrame:CGRectMake(
dc5812ec
JF
2345 i * 64 + 2, 1, 60, 48
2346 )];
2347
2367a917 2348 [buttonbar_ showSelectionForButton:1];
dc5812ec
JF
2349 [transition_ transition:0 toView:featured_];
2350
3178d79b 2351 [overlay_ addSubview:buttonbar_];
dc5812ec
JF
2352
2353 database_ = [[Database alloc] init];
2367a917 2354 [database_ setDelegate:progress_];
dc5812ec 2355
3178d79b 2356 install_ = [[InstallView alloc] initWithFrame:[transition_ bounds] database:database_];
dc5812ec
JF
2357 [install_ setDelegate:self];
2358
3178d79b
JF
2359 upgrade_ = [[UpgradeView alloc] initWithFrame:[transition_ bounds] database:database_];
2360 [upgrade_ setDelegate:self];
2361
2362 uninstall_ = [[UninstallView alloc] initWithFrame:[transition_ bounds] database:database_];
dc5812ec
JF
2363 [uninstall_ setDelegate:self];
2364
8da60fb7
JF
2365 sources_ = [[SourcesView alloc] initWithFrame:[transition_ bounds] database:database_];
2366 [sources_ setDelegate:self];
2367
dc5812ec 2368#if 0
2367a917 2369
dc5812ec
JF
2370 UIAlertSheet *alert = [[UIAlertSheet alloc]
2371 initWithTitle:@"Alert Title"
2372 buttons:[NSArray arrayWithObjects:@"Yes", nil]
2373 defaultButtonIndex:0
2374 delegate:self
2375 context:self
2376 ];
2377
2378 NSLog(@"%p\n", [alert table]);
2379 [[alert table] setDelegate:self];
2380 [[alert table] reloadData];
2381
2382 [alert addTextFieldWithValue:@"Title" label:@"Label"];
2383 [alert setShowsOverSpringBoardAlerts:YES];
2384 [alert setBodyText:@"This is an alert."];
2367a917 2385 [alert presentSheetFromButtonBar:buttonbar_];
dc5812ec 2386 //[alert popupAlertAnimated:YES];
2367a917 2387
dc5812ec
JF
2388#endif
2389
8fe19fc1 2390 [self reloadData:NO];
dc5812ec 2391 [progress_ resetView];
3178d79b
JF
2392
2393 Package *package([database_ packageWithName:@"cydia"]);
2394 NSString *application = package == nil ? @"Cydia" : [NSString stringWithFormat:@"Cydia/%@", [package installed]];
2395 WebView *webview = [webview_ webView];
2396 [webview setApplicationNameForUserAgent:application];
2397
2398 url_ = [NSURL URLWithString:@"http://cydia.saurik.com/"];
2399 [self loadNews];
dc5812ec
JF
2400}
2401
2402@end
2403
2404int main(int argc, char *argv[]) {
2405 NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
3178d79b
JF
2406
2407 size_t size;
2408 sysctlbyname("hw.machine", NULL, &size, NULL, 0);
2409 char *machine = new char[size];
2410 sysctlbyname("hw.machine", machine, &size, NULL, 0);
2411 Machine_ = machine;
2412
2413 if (CFMutableDictionaryRef dict = IOServiceMatching("IOPlatformExpertDevice"))
2414 if (io_service_t service = IOServiceGetMatchingService(kIOMasterPortDefault, dict)) {
2415 if (CFTypeRef serial = IORegistryEntryCreateCFProperty(service, CFSTR(kIOPlatformSerialNumberKey), kCFAllocatorDefault, 0)) {
2416 SerialNumber_ = strdup(CFStringGetCStringPtr((CFStringRef) serial, CFStringGetSystemEncoding()));
2417 CFRelease(serial);
2418 }
2419
2420 IOObjectRelease(service);
2421 }
2422
dc5812ec
JF
2423 UIApplicationMain(argc, argv, [Cydia class]);
2424 [pool release];
2425}