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