]>
Commit | Line | Data |
---|---|---|
36bb2ca2 JF |
1 | /* Cydia - iPhone UIKit Front-End for Debian APT |
2 | * Copyright (C) 2008 Jay Freeman (saurik) | |
3 | */ | |
4 | ||
5 | /* | |
6 | * Redistribution and use in source and binary | |
7 | * forms, with or without modification, are permitted | |
8 | * provided that the following conditions are met: | |
9 | * | |
10 | * 1. Redistributions of source code must retain the | |
11 | * above copyright notice, this list of conditions | |
12 | * and the following disclaimer. | |
13 | * 2. Redistributions in binary form must reproduce the | |
14 | * above copyright notice, this list of conditions | |
15 | * and the following disclaimer in the documentation | |
16 | * and/or other materials provided with the | |
17 | * distribution. | |
18 | * 3. The name of the author may not be used to endorse | |
19 | * or promote products derived from this software | |
20 | * without specific prior written permission. | |
21 | * | |
22 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' | |
23 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, | |
24 | * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF | |
25 | * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | |
26 | * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE | |
27 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, | |
28 | * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT | |
29 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR | |
30 | * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | |
31 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF | |
32 | * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR | |
33 | * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN | |
34 | * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF | |
35 | * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
36 | */ | |
37 | ||
dc5812ec | 38 | /* #include Directives {{{ */ |
5f6bff8c | 39 | #include <CoreGraphics/CoreGraphics.h> |
9743c015 | 40 | #include <GraphicsServices/GraphicsServices.h> |
5f6bff8c JF |
41 | #include <Foundation/Foundation.h> |
42 | #include <UIKit/UIKit.h> | |
36bb2ca2 JF |
43 | #include <WebCore/DOMHTML.h> |
44 | ||
45 | #include <WebKit/WebFrame.h> | |
46 | #include <WebKit/WebView.h> | |
9743c015 JF |
47 | |
48 | #include <objc/objc.h> | |
1e7a90f5 | 49 | #include <objc/runtime.h> |
dc5812ec | 50 | |
2367a917 | 51 | #include <sstream> |
a0be02eb JF |
52 | #include <string> |
53 | ||
2367a917 JF |
54 | #include <ext/stdio_filebuf.h> |
55 | ||
dc5812ec JF |
56 | #include <apt-pkg/acquire.h> |
57 | #include <apt-pkg/acquire-item.h> | |
58 | #include <apt-pkg/algorithms.h> | |
59 | #include <apt-pkg/cachefile.h> | |
60 | #include <apt-pkg/configuration.h> | |
3178d79b | 61 | #include <apt-pkg/debmetaindex.h> |
dc5812ec JF |
62 | #include <apt-pkg/error.h> |
63 | #include <apt-pkg/init.h> | |
64 | #include <apt-pkg/pkgrecords.h> | |
65 | #include <apt-pkg/sourcelist.h> | |
2367a917 | 66 | #include <apt-pkg/sptr.h> |
dc5812ec | 67 | |
3178d79b | 68 | #include <sys/sysctl.h> |
2a8d9add | 69 | #include <notify.h> |
3178d79b | 70 | |
b4d89997 JF |
71 | extern "C" { |
72 | #include <mach-o/nlist.h> | |
73 | } | |
74 | ||
a0be02eb JF |
75 | #include <cstdio> |
76 | #include <cstdlib> | |
77 | #include <cstring> | |
b4d89997 | 78 | |
2367a917 | 79 | #include <errno.h> |
dc5812ec | 80 | #include <pcre.h> |
dc5812ec JF |
81 | /* }}} */ |
82 | /* Extension Keywords {{{ */ | |
2367a917 | 83 | #define _trace() fprintf(stderr, "_trace()@%s:%u[%s]\n", __FILE__, __LINE__, __FUNCTION__) |
dc5812ec JF |
84 | |
85 | #define _assert(test) do \ | |
86 | if (!(test)) { \ | |
2367a917 | 87 | fprintf(stderr, "_assert(%d:%s)@%s:%u[%s]\n", errno, #test, __FILE__, __LINE__, __FUNCTION__); \ |
dc5812ec JF |
88 | exit(-1); \ |
89 | } \ | |
90 | while (false) | |
68a238ec JF |
91 | |
92 | #define _not(type) ((type) ~ (type) 0) | |
36bb2ca2 JF |
93 | |
94 | #define _transient | |
dc5812ec | 95 | /* }}} */ |
3178d79b | 96 | |
36bb2ca2 | 97 | /* Miscellaneous Messages {{{ */ |
b4d89997 JF |
98 | @interface NSString (Cydia) |
99 | - (NSString *) stringByAddingPercentEscapes; | |
100 | - (NSString *) stringByReplacingCharacter:(unsigned short)arg0 withCharacter:(unsigned short)arg1; | |
101 | @end | |
102 | /* }}} */ | |
36bb2ca2 JF |
103 | /* External Constants {{{ */ |
104 | extern NSString *kUIButtonBarButtonAction; | |
105 | extern NSString *kUIButtonBarButtonInfo; | |
106 | extern NSString *kUIButtonBarButtonInfoOffset; | |
107 | extern NSString *kUIButtonBarButtonSelectedInfo; | |
108 | extern NSString *kUIButtonBarButtonStyle; | |
109 | extern NSString *kUIButtonBarButtonTag; | |
110 | extern NSString *kUIButtonBarButtonTarget; | |
111 | extern NSString *kUIButtonBarButtonTitle; | |
112 | extern NSString *kUIButtonBarButtonTitleVerticalHeight; | |
113 | extern NSString *kUIButtonBarButtonTitleWidth; | |
114 | extern NSString *kUIButtonBarButtonType; | |
115 | /* }}} */ | |
116 | ||
117 | #if 1 | |
118 | #define $_ | |
119 | #define _$ | |
120 | #else | |
121 | #define $_ fprintf(stderr, "+");_trace(); | |
122 | #define _$ fprintf(stderr, "-");_trace(); | |
123 | #endif | |
b4d89997 | 124 | |
1e7a90f5 JF |
125 | /* iPhoneOS 2.0 Compatibility {{{ */ |
126 | #ifdef __OBJC2__ | |
127 | @interface UICGColor : NSObject { | |
128 | } | |
129 | ||
130 | - (id) initWithCGColor:(CGColorRef)color; | |
131 | @end | |
132 | ||
133 | @interface UIFont { | |
134 | } | |
135 | ||
136 | - (UIFont *) fontWithSize:(CGFloat)size; | |
137 | @end | |
138 | ||
139 | @interface NSObject (iPhoneOS) | |
140 | - (CGColorRef) cgColor; | |
ffdee4ec | 141 | - (CGColorRef) CGColor; |
1e7a90f5 JF |
142 | - (void) set; |
143 | @end | |
144 | ||
145 | @implementation NSObject (iPhoneOS) | |
146 | ||
147 | - (CGColorRef) cgColor { | |
ffdee4ec JF |
148 | return [self CGColor]; |
149 | } | |
150 | ||
151 | - (CGColorRef) CGColor { | |
1e7a90f5 JF |
152 | return (CGColorRef) self; |
153 | } | |
154 | ||
155 | - (void) set { | |
ffdee4ec | 156 | [[[[objc_getClass("UICGColor") alloc] initWithCGColor:[self CGColor]] autorelease] set]; |
1e7a90f5 JF |
157 | } |
158 | ||
159 | @end | |
160 | ||
161 | @interface UITextView (iPhoneOS) | |
162 | - (void) setTextSize:(float)size; | |
163 | @end | |
164 | ||
165 | @implementation UITextView (iPhoneOS) | |
166 | ||
167 | - (void) setTextSize:(float)size { | |
168 | [self setFont:[[self font] fontWithSize:size]]; | |
169 | } | |
170 | ||
171 | @end | |
49048579 | 172 | #endif |
1e7a90f5 | 173 | /* }}} */ |
49048579 | 174 | |
9743c015 JF |
175 | OBJC_EXPORT const char *class_getName(Class cls); |
176 | ||
b4d89997 | 177 | /* Reset View (UIView) {{{ */ |
36bb2ca2 | 178 | @interface UIView (RVBook) |
b4d89997 | 179 | - (void) resetViewAnimated:(BOOL)animated; |
36bb2ca2 | 180 | - (void) clearView; |
b4d89997 JF |
181 | @end |
182 | ||
36bb2ca2 | 183 | @implementation UIView (RVBook) |
b4d89997 JF |
184 | |
185 | - (void) resetViewAnimated:(BOOL)animated { | |
9743c015 | 186 | fprintf(stderr, "%s\n", class_getName(self->isa)); |
b4d89997 JF |
187 | _assert(false); |
188 | } | |
189 | ||
36bb2ca2 JF |
190 | - (void) clearView { |
191 | fprintf(stderr, "%s\n", class_getName(self->isa)); | |
192 | _assert(false); | |
193 | } | |
194 | ||
b4d89997 JF |
195 | @end |
196 | /* }}} */ | |
197 | /* Reset View (UITable) {{{ */ | |
36bb2ca2 | 198 | @interface UITable (RVBook) |
b4d89997 | 199 | - (void) resetViewAnimated:(BOOL)animated; |
36bb2ca2 | 200 | - (void) clearView; |
b4d89997 JF |
201 | @end |
202 | ||
36bb2ca2 | 203 | @implementation UITable (RVBook) |
b4d89997 JF |
204 | |
205 | - (void) resetViewAnimated:(BOOL)animated { | |
206 | [self selectRow:-1 byExtendingSelection:NO withFade:animated]; | |
207 | } | |
208 | ||
36bb2ca2 JF |
209 | - (void) clearView { |
210 | [self clearAllData]; | |
211 | } | |
212 | ||
b4d89997 JF |
213 | @end |
214 | /* }}} */ | |
215 | /* Reset View (UISectionList) {{{ */ | |
36bb2ca2 | 216 | @interface UISectionList (RVBook) |
b4d89997 | 217 | - (void) resetViewAnimated:(BOOL)animated; |
36bb2ca2 | 218 | - (void) clearView; |
b4d89997 JF |
219 | @end |
220 | ||
36bb2ca2 | 221 | @implementation UISectionList (RVBook) |
b4d89997 JF |
222 | |
223 | - (void) resetViewAnimated:(BOOL)animated { | |
224 | [[self table] resetViewAnimated:animated]; | |
225 | } | |
226 | ||
36bb2ca2 JF |
227 | - (void) clearView { |
228 | [[self table] clearView]; | |
229 | } | |
230 | ||
b4d89997 JF |
231 | @end |
232 | /* }}} */ | |
233 | ||
234 | /* Perl-Compatible RegEx {{{ */ | |
235 | class Pcre { | |
236 | private: | |
237 | pcre *code_; | |
238 | pcre_extra *study_; | |
239 | int capture_; | |
240 | int *matches_; | |
241 | const char *data_; | |
242 | ||
243 | public: | |
244 | Pcre(const char *regex) : | |
245 | study_(NULL) | |
246 | { | |
247 | const char *error; | |
248 | int offset; | |
249 | code_ = pcre_compile(regex, 0, &error, &offset, NULL); | |
250 | ||
251 | if (code_ == NULL) { | |
252 | fprintf(stderr, "%d:%s\n", offset, error); | |
253 | _assert(false); | |
254 | } | |
255 | ||
256 | pcre_fullinfo(code_, study_, PCRE_INFO_CAPTURECOUNT, &capture_); | |
257 | matches_ = new int[(capture_ + 1) * 3]; | |
258 | } | |
259 | ||
260 | ~Pcre() { | |
261 | pcre_free(code_); | |
262 | delete matches_; | |
263 | } | |
264 | ||
265 | NSString *operator [](size_t match) { | |
266 | return [NSString | |
267 | stringWithCString:(data_ + matches_[match * 2]) | |
268 | length:(matches_[match * 2 + 1] - matches_[match * 2]) | |
269 | ]; | |
270 | } | |
271 | ||
272 | bool operator ()(const char *data, size_t size) { | |
273 | data_ = data; | |
274 | return pcre_exec(code_, study_, data, size, 0, 0, matches_, (capture_ + 1) * 3) >= 0; | |
275 | } | |
276 | }; | |
277 | /* }}} */ | |
36bb2ca2 JF |
278 | /* Mime Addresses {{{ */ |
279 | Pcre email_r("^\"?(.*)\"? <([^>]*)>$"); | |
280 | ||
281 | @interface Address : NSObject { | |
282 | NSString *name_; | |
283 | NSString *email_; | |
284 | } | |
285 | ||
286 | - (NSString *) name; | |
287 | - (NSString *) email; | |
288 | ||
289 | + (Address *) addressWithString:(NSString *)string; | |
290 | - (Address *) initWithString:(NSString *)string; | |
291 | @end | |
292 | ||
293 | @implementation Address | |
294 | ||
295 | - (void) dealloc { | |
296 | [name_ release]; | |
297 | if (email_ != nil) | |
298 | [email_ release]; | |
299 | [super dealloc]; | |
300 | } | |
301 | ||
302 | - (NSString *) name { | |
303 | return name_; | |
304 | } | |
305 | ||
306 | - (NSString *) email { | |
307 | return email_; | |
308 | } | |
309 | ||
310 | + (Address *) addressWithString:(NSString *)string { | |
311 | return [[[Address alloc] initWithString:string] autorelease]; | |
312 | } | |
313 | ||
314 | - (Address *) initWithString:(NSString *)string { | |
315 | if ((self = [super init]) != nil) { | |
316 | const char *data = [string UTF8String]; | |
317 | size_t size = [string length]; | |
318 | ||
319 | if (email_r(data, size)) { | |
320 | name_ = [email_r[1] retain]; | |
321 | email_ = [email_r[2] retain]; | |
322 | } else { | |
323 | name_ = [[NSString stringWithCString:data length:size] retain]; | |
324 | email_ = nil; | |
325 | } | |
326 | } return self; | |
327 | } | |
328 | ||
329 | @end | |
330 | /* }}} */ | |
5f6bff8c | 331 | /* CoreGraphics Primitives {{{ */ |
b4d89997 JF |
332 | class CGColor { |
333 | private: | |
334 | CGColorRef color_; | |
335 | ||
336 | public: | |
36bb2ca2 JF |
337 | CGColor() : |
338 | color_(NULL) | |
339 | { | |
340 | } | |
341 | ||
342 | CGColor(CGColorSpaceRef space, float red, float green, float blue, float alpha) : | |
343 | color_(NULL) | |
344 | { | |
345 | Set(space, red, green, blue, alpha); | |
346 | } | |
347 | ||
348 | void Clear() { | |
349 | if (color_ != NULL) | |
350 | CGColorRelease(color_); | |
b4d89997 JF |
351 | } |
352 | ||
353 | ~CGColor() { | |
36bb2ca2 JF |
354 | Clear(); |
355 | } | |
356 | ||
357 | void Set(CGColorSpaceRef space, float red, float green, float blue, float alpha) { | |
358 | Clear(); | |
359 | float color[] = {red, green, blue, alpha}; | |
360 | color_ = CGColorCreate(space, color); | |
b4d89997 JF |
361 | } |
362 | ||
363 | operator CGColorRef() { | |
364 | return color_; | |
365 | } | |
366 | }; | |
367 | ||
368 | class GSFont { | |
369 | private: | |
370 | GSFontRef font_; | |
371 | ||
372 | public: | |
373 | ~GSFont() { | |
b4d89997 JF |
374 | CFRelease(font_); |
375 | } | |
376 | }; | |
377 | /* }}} */ | |
36bb2ca2 JF |
378 | /* Right Alignment {{{ */ |
379 | @interface UIRightTextLabel : UITextLabel { | |
380 | float _savedRightEdgeX; | |
381 | BOOL _sizedtofit_flag; | |
382 | } | |
383 | ||
384 | - (void) setFrame:(CGRect)frame; | |
385 | - (void) setText:(NSString *)text; | |
386 | - (void) realignText; | |
387 | @end | |
388 | ||
389 | @implementation UIRightTextLabel | |
390 | ||
391 | - (void) setFrame:(CGRect)frame { | |
392 | [super setFrame:frame]; | |
393 | if (_sizedtofit_flag == NO) { | |
394 | _savedRightEdgeX = frame.origin.x; | |
395 | [self realignText]; | |
396 | } | |
397 | } | |
398 | ||
399 | - (void) setText:(NSString *)text { | |
400 | [super setText:text]; | |
401 | [self realignText]; | |
402 | } | |
403 | ||
404 | - (void) realignText { | |
405 | CGRect oldFrame = [self frame]; | |
406 | ||
407 | _sizedtofit_flag = YES; | |
408 | [self sizeToFit]; // shrink down size so I can right align it | |
409 | ||
410 | CGRect newFrame = [self frame]; | |
411 | ||
412 | oldFrame.origin.x = _savedRightEdgeX - newFrame.size.width; | |
413 | oldFrame.size.width = newFrame.size.width; | |
414 | [super setFrame:oldFrame]; | |
415 | _sizedtofit_flag = NO; | |
416 | } | |
417 | ||
418 | @end | |
419 | /* }}} */ | |
b4d89997 | 420 | |
36bb2ca2 | 421 | /* Random Global Variables {{{ */ |
3178d79b | 422 | static const int PulseInterval_ = 50000; |
2a8d9add | 423 | |
36bb2ca2 JF |
424 | static CGColor Black_; |
425 | static CGColor Clear_; | |
426 | static CGColor Red_; | |
427 | static CGColor White_; | |
428 | ||
d73cede2 JF |
429 | static NSString *Home_; |
430 | static BOOL Sounds_Keyboard_; | |
431 | ||
2a8d9add | 432 | const char *Firmware_ = NULL; |
3178d79b JF |
433 | const char *Machine_ = NULL; |
434 | const char *SerialNumber_ = NULL; | |
435 | ||
2a8d9add JF |
436 | unsigned Major_; |
437 | unsigned Minor_; | |
438 | unsigned BugFix_; | |
439 | ||
36bb2ca2 JF |
440 | CGColorSpaceRef space_; |
441 | ||
2a8d9add | 442 | #define FW_LEAST(major, minor, bugfix) \ |
51a1ffdf JF |
443 | (major < Major_ || major == Major_ && \ |
444 | (minor < Minor_ || minor == Minor_ && \ | |
445 | bugfix <= BugFix_)) | |
2a8d9add | 446 | |
36bb2ca2 JF |
447 | bool bootstrap_; |
448 | bool restart_; | |
b31b87cc | 449 | |
b4d89997 JF |
450 | static NSMutableDictionary *Metadata_; |
451 | static NSMutableDictionary *Packages_; | |
452 | static NSDate *now_; | |
8da60fb7 | 453 | |
23672b39 JF |
454 | NSString *GetLastUpdate() { |
455 | NSDate *update = [Metadata_ objectForKey:@"LastUpdate"]; | |
456 | ||
457 | if (update == nil) | |
458 | return @"Never or Unknown"; | |
459 | ||
460 | CFLocaleRef locale = CFLocaleCopyCurrent(); | |
461 | CFDateFormatterRef formatter = CFDateFormatterCreate(NULL, locale, kCFDateFormatterMediumStyle, kCFDateFormatterMediumStyle); | |
462 | CFStringRef formatted = CFDateFormatterCreateStringWithDate(NULL, formatter, (CFDateRef) update); | |
463 | ||
464 | CFRelease(formatter); | |
23672b39 JF |
465 | CFRelease(locale); |
466 | ||
467 | return [(NSString *) formatted autorelease]; | |
468 | } | |
36bb2ca2 JF |
469 | /* }}} */ |
470 | /* Display Helpers {{{ */ | |
471 | inline float Interpolate(float begin, float end, float fraction) { | |
472 | return (end - begin) * fraction + begin; | |
473 | } | |
2367a917 | 474 | |
8fe19fc1 JF |
475 | NSString *SizeString(double size) { |
476 | unsigned power = 0; | |
477 | while (size > 1024) { | |
478 | size /= 1024; | |
479 | ++power; | |
480 | } | |
481 | ||
482 | static const char *powers_[] = {"B", "kB", "MB", "GB"}; | |
483 | ||
484 | return [NSString stringWithFormat:@"%.1f%s", size, powers_[power]]; | |
485 | } | |
486 | ||
b4d89997 JF |
487 | static const float TextViewOffset_ = 22; |
488 | ||
489 | UITextView *GetTextView(NSString *value, float left, bool html) { | |
490 | UITextView *text([[[UITextView alloc] initWithFrame:CGRectMake(left, 3, 310 - left, 1000)] autorelease]); | |
491 | [text setEditable:NO]; | |
492 | [text setTextSize:16]; | |
1e7a90f5 | 493 | /*if (html) |
b4d89997 | 494 | [text setHTML:value]; |
1e7a90f5 | 495 | else*/ |
b4d89997 JF |
496 | [text setText:value]; |
497 | [text setEnabled:NO]; | |
498 | ||
36bb2ca2 | 499 | [text setBackgroundColor:Clear_]; |
b4d89997 JF |
500 | |
501 | CGRect frame = [text frame]; | |
502 | [text setFrame:frame]; | |
503 | CGRect rect = [text visibleTextRect]; | |
504 | frame.size.height = rect.size.height; | |
505 | [text setFrame:frame]; | |
506 | ||
507 | return text; | |
508 | } | |
4cf4165e JF |
509 | |
510 | NSString *Simplify(NSString *title) { | |
511 | const char *data = [title UTF8String]; | |
512 | size_t size = [title length]; | |
513 | ||
514 | Pcre title_r("^(.*?)( \\(.*\\))?$"); | |
515 | if (title_r(data, size)) | |
516 | return title_r[1]; | |
517 | else | |
518 | return title; | |
519 | } | |
36bb2ca2 JF |
520 | /* }}} */ |
521 | ||
522 | @class Package; | |
523 | @class Source; | |
524 | ||
525 | @protocol ProgressDelegate | |
526 | - (void) setProgressError:(NSString *)error; | |
527 | - (void) setProgressTitle:(NSString *)title; | |
528 | - (void) setProgressPercent:(float)percent; | |
529 | - (void) addProgressOutput:(NSString *)output; | |
530 | @end | |
531 | ||
532 | @protocol CydiaDelegate | |
533 | - (void) installPackage:(Package *)package; | |
534 | - (void) removePackage:(Package *)package; | |
535 | - (void) slideUp:(UIAlertSheet *)alert; | |
536 | - (void) distUpgrade; | |
537 | @end | |
b4d89997 | 538 | |
dc5812ec JF |
539 | /* Status Delegation {{{ */ |
540 | class Status : | |
541 | public pkgAcquireStatus | |
542 | { | |
543 | private: | |
36bb2ca2 | 544 | _transient id<ProgressDelegate> delegate_; |
dc5812ec JF |
545 | |
546 | public: | |
547 | Status() : | |
548 | delegate_(nil) | |
549 | { | |
550 | } | |
551 | ||
552 | void setDelegate(id delegate) { | |
553 | delegate_ = delegate; | |
554 | } | |
555 | ||
556 | virtual bool MediaChange(std::string media, std::string drive) { | |
557 | return false; | |
558 | } | |
559 | ||
560 | virtual void IMSHit(pkgAcquire::ItemDesc &item) { | |
dc5812ec JF |
561 | } |
562 | ||
563 | virtual void Fetch(pkgAcquire::ItemDesc &item) { | |
36bb2ca2 | 564 | [delegate_ setProgressTitle:[NSString stringWithCString:("Downloading " + item.ShortDesc).c_str()]]; |
dc5812ec JF |
565 | } |
566 | ||
567 | virtual void Done(pkgAcquire::ItemDesc &item) { | |
dc5812ec JF |
568 | } |
569 | ||
570 | virtual void Fail(pkgAcquire::ItemDesc &item) { | |
1d80f6b9 JF |
571 | if ( |
572 | item.Owner->Status == pkgAcquire::Item::StatIdle || | |
573 | item.Owner->Status == pkgAcquire::Item::StatDone | |
574 | ) | |
575 | return; | |
576 | ||
36bb2ca2 | 577 | [delegate_ setProgressError:[NSString stringWithCString:item.Owner->ErrorText.c_str()]]; |
dc5812ec JF |
578 | } |
579 | ||
580 | virtual bool Pulse(pkgAcquire *Owner) { | |
2367a917 JF |
581 | bool value = pkgAcquireStatus::Pulse(Owner); |
582 | ||
583 | float percent( | |
584 | double(CurrentBytes + CurrentItems) / | |
585 | double(TotalBytes + TotalItems) | |
586 | ); | |
587 | ||
36bb2ca2 | 588 | [delegate_ setProgressPercent:percent]; |
2367a917 | 589 | return value; |
dc5812ec JF |
590 | } |
591 | ||
592 | virtual void Start() { | |
dc5812ec JF |
593 | } |
594 | ||
595 | virtual void Stop() { | |
dc5812ec JF |
596 | } |
597 | }; | |
598 | /* }}} */ | |
599 | /* Progress Delegation {{{ */ | |
600 | class Progress : | |
601 | public OpProgress | |
602 | { | |
603 | private: | |
36bb2ca2 | 604 | _transient id<ProgressDelegate> delegate_; |
dc5812ec JF |
605 | |
606 | protected: | |
607 | virtual void Update() { | |
36bb2ca2 JF |
608 | [delegate_ setProgressTitle:[NSString stringWithCString:Op.c_str()]]; |
609 | [delegate_ setProgressPercent:(Percent / 100)]; | |
dc5812ec JF |
610 | } |
611 | ||
612 | public: | |
613 | Progress() : | |
614 | delegate_(nil) | |
615 | { | |
616 | } | |
617 | ||
618 | void setDelegate(id delegate) { | |
619 | delegate_ = delegate; | |
620 | } | |
621 | ||
622 | virtual void Done() { | |
36bb2ca2 | 623 | [delegate_ setProgressPercent:1]; |
dc5812ec JF |
624 | } |
625 | }; | |
626 | /* }}} */ | |
627 | ||
36bb2ca2 JF |
628 | /* Database Interface {{{ */ |
629 | @interface Database : NSObject { | |
630 | pkgCacheFile cache_; | |
631 | pkgRecords *records_; | |
632 | pkgProblemResolver *resolver_; | |
633 | pkgAcquire *fetcher_; | |
634 | FileFd *lock_; | |
635 | SPtr<pkgPackageManager> manager_; | |
636 | pkgSourceList *list_; | |
5f6bff8c | 637 | |
36bb2ca2 JF |
638 | NSMutableDictionary *sources_; |
639 | NSMutableArray *packages_; | |
b4d89997 | 640 | |
36bb2ca2 JF |
641 | _transient id delegate_; |
642 | Status status_; | |
643 | Progress progress_; | |
644 | int statusfd_; | |
dc5812ec JF |
645 | } |
646 | ||
36bb2ca2 JF |
647 | - (void) _readStatus:(NSNumber *)fd; |
648 | - (void) _readOutput:(NSNumber *)fd; | |
2367a917 | 649 | |
36bb2ca2 | 650 | - (Package *) packageWithName:(NSString *)name; |
dc5812ec | 651 | |
36bb2ca2 JF |
652 | - (Database *) init; |
653 | - (pkgCacheFile &) cache; | |
654 | - (pkgRecords *) records; | |
655 | - (pkgProblemResolver *) resolver; | |
656 | - (pkgAcquire &) fetcher; | |
657 | - (NSArray *) packages; | |
658 | - (void) reloadData; | |
659 | ||
660 | - (void) prepare; | |
661 | - (void) perform; | |
662 | - (void) upgrade; | |
663 | - (void) update; | |
664 | ||
665 | - (void) updateWithStatus:(Status &)status; | |
666 | ||
667 | - (void) setDelegate:(id)delegate; | |
668 | - (Source *) getSource:(const pkgCache::PkgFileIterator &)file; | |
dc5812ec | 669 | @end |
36bb2ca2 | 670 | /* }}} */ |
dc5812ec | 671 | |
36bb2ca2 JF |
672 | /* Source Class {{{ */ |
673 | @interface Source : NSObject { | |
674 | NSString *description_; | |
675 | NSString *label_; | |
676 | NSString *origin_; | |
dc5812ec | 677 | |
36bb2ca2 JF |
678 | NSString *uri_; |
679 | NSString *distribution_; | |
680 | NSString *type_; | |
681 | NSString *version_; | |
2367a917 | 682 | |
36bb2ca2 | 683 | NSString *defaultIcon_; |
dc5812ec | 684 | |
36bb2ca2 | 685 | BOOL trusted_; |
dc5812ec JF |
686 | } |
687 | ||
36bb2ca2 | 688 | - (Source *) initWithMetaIndex:(metaIndex *)index; |
dc5812ec | 689 | |
36bb2ca2 | 690 | - (BOOL) trusted; |
dc5812ec | 691 | |
36bb2ca2 JF |
692 | - (NSString *) uri; |
693 | - (NSString *) distribution; | |
694 | - (NSString *) type; | |
695 | ||
696 | - (NSString *) description; | |
697 | - (NSString *) label; | |
698 | - (NSString *) origin; | |
699 | - (NSString *) version; | |
dc5812ec | 700 | |
36bb2ca2 | 701 | - (NSString *) defaultIcon; |
dc5812ec | 702 | @end |
dc5812ec | 703 | |
36bb2ca2 | 704 | @implementation Source |
dc5812ec | 705 | |
36bb2ca2 JF |
706 | - (void) dealloc { |
707 | [uri_ release]; | |
708 | [distribution_ release]; | |
709 | [type_ release]; | |
dc5812ec | 710 | |
36bb2ca2 JF |
711 | if (description_ != nil) |
712 | [description_ release]; | |
713 | if (label_ != nil) | |
714 | [label_ release]; | |
715 | if (origin_ != nil) | |
716 | [origin_ release]; | |
717 | if (version_ != nil) | |
718 | [version_ release]; | |
719 | if (defaultIcon_ != nil) | |
720 | [defaultIcon_ release]; | |
dc5812ec | 721 | |
36bb2ca2 | 722 | [super dealloc]; |
dc5812ec JF |
723 | } |
724 | ||
36bb2ca2 JF |
725 | - (Source *) initWithMetaIndex:(metaIndex *)index { |
726 | if ((self = [super init]) != nil) { | |
727 | trusted_ = index->IsTrusted(); | |
dc5812ec | 728 | |
36bb2ca2 JF |
729 | uri_ = [[NSString stringWithCString:index->GetURI().c_str()] retain]; |
730 | distribution_ = [[NSString stringWithCString:index->GetDist().c_str()] retain]; | |
731 | type_ = [[NSString stringWithCString:index->GetType()] retain]; | |
dc5812ec | 732 | |
36bb2ca2 JF |
733 | description_ = nil; |
734 | label_ = nil; | |
735 | origin_ = nil; | |
736 | version_ = nil; | |
737 | defaultIcon_ = nil; | |
dc5812ec | 738 | |
36bb2ca2 JF |
739 | debReleaseIndex *dindex(dynamic_cast<debReleaseIndex *>(index)); |
740 | if (dindex != NULL) { | |
741 | std::ifstream release(dindex->MetaIndexFile("Release").c_str()); | |
742 | std::string line; | |
743 | while (std::getline(release, line)) { | |
744 | std::string::size_type colon(line.find(':')); | |
745 | if (colon == std::string::npos) | |
746 | continue; | |
dc5812ec | 747 | |
36bb2ca2 JF |
748 | std::string name(line.substr(0, colon)); |
749 | std::string value(line.substr(colon + 1)); | |
750 | while (!value.empty() && value[0] == ' ') | |
751 | value = value.substr(1); | |
dc5812ec | 752 | |
36bb2ca2 JF |
753 | if (name == "Default-Icon") |
754 | defaultIcon_ = [[NSString stringWithCString:value.c_str()] retain]; | |
755 | else if (name == "Description") | |
756 | description_ = [[NSString stringWithCString:value.c_str()] retain]; | |
757 | else if (name == "Label") | |
758 | label_ = [[NSString stringWithCString:value.c_str()] retain]; | |
759 | else if (name == "Origin") | |
760 | origin_ = [[NSString stringWithCString:value.c_str()] retain]; | |
761 | else if (name == "Version") | |
762 | version_ = [[NSString stringWithCString:value.c_str()] retain]; | |
763 | } | |
764 | } | |
765 | } return self; | |
2367a917 | 766 | } |
dc5812ec | 767 | |
36bb2ca2 JF |
768 | - (BOOL) trusted { |
769 | return trusted_; | |
770 | } | |
3178d79b | 771 | |
36bb2ca2 JF |
772 | - (NSString *) uri { |
773 | return uri_; | |
774 | } | |
ec97ef06 | 775 | |
36bb2ca2 JF |
776 | - (NSString *) distribution { |
777 | return distribution_; | |
778 | } | |
dc5812ec | 779 | |
36bb2ca2 JF |
780 | - (NSString *) type { |
781 | return type_; | |
dc5812ec JF |
782 | } |
783 | ||
36bb2ca2 JF |
784 | - (NSString *) description { |
785 | return description_; | |
786 | } | |
b4d89997 | 787 | |
36bb2ca2 JF |
788 | - (NSString *) label { |
789 | return label_; | |
790 | } | |
3178d79b | 791 | |
36bb2ca2 JF |
792 | - (NSString *) origin { |
793 | return origin_; | |
794 | } | |
3178d79b | 795 | |
36bb2ca2 JF |
796 | - (NSString *) version { |
797 | return version_; | |
798 | } | |
2367a917 | 799 | |
36bb2ca2 JF |
800 | - (NSString *) defaultIcon { |
801 | return defaultIcon_; | |
802 | } | |
2367a917 | 803 | |
dc5812ec | 804 | @end |
b4d89997 | 805 | /* }}} */ |
36bb2ca2 JF |
806 | /* Package Class {{{ */ |
807 | NSString *Scour(const char *field, const char *begin, const char *end) { | |
808 | size_t i(0), l(strlen(field)); | |
dc5812ec | 809 | |
36bb2ca2 JF |
810 | for (;;) { |
811 | const char *name = begin + i; | |
812 | const char *colon = name + l; | |
813 | const char *value = colon + 1; | |
06aa974d | 814 | |
36bb2ca2 JF |
815 | if ( |
816 | value < end && | |
817 | *colon == ':' && | |
818 | memcmp(name, field, l) == 0 | |
819 | ) { | |
820 | while (value != end && value[0] == ' ') | |
821 | ++value; | |
822 | const char *line = std::find(value, end, '\n'); | |
823 | while (line != value && line[-1] == ' ') | |
824 | --line; | |
825 | return [NSString stringWithCString:value length:(line - value)]; | |
826 | } else { | |
827 | begin = std::find(begin, end, '\n'); | |
828 | if (begin == end) | |
829 | return nil; | |
830 | ++begin; | |
831 | } | |
832 | } | |
833 | } | |
b4d89997 | 834 | |
36bb2ca2 JF |
835 | @interface Package : NSObject { |
836 | pkgCache::PkgIterator iterator_; | |
837 | _transient Database *database_; | |
838 | pkgCache::VerIterator version_; | |
839 | pkgCache::VerFileIterator file_; | |
840 | Source *source_; | |
dc5812ec | 841 | |
36bb2ca2 JF |
842 | NSString *latest_; |
843 | NSString *installed_; | |
dc5812ec | 844 | |
36bb2ca2 JF |
845 | NSString *id_; |
846 | NSString *name_; | |
847 | NSString *tagline_; | |
848 | NSString *icon_; | |
849 | NSString *website_; | |
b4d89997 JF |
850 | } |
851 | ||
36bb2ca2 JF |
852 | - (Package *) initWithIterator:(pkgCache::PkgIterator)iterator database:(Database *)database version:(pkgCache::VerIterator)version file:(pkgCache::VerFileIterator)file; |
853 | + (Package *) packageWithIterator:(pkgCache::PkgIterator)iterator database:(Database *)database; | |
b4d89997 | 854 | |
36bb2ca2 JF |
855 | - (NSString *) section; |
856 | - (Address *) maintainer; | |
857 | - (size_t) size; | |
858 | - (NSString *) description; | |
859 | - (NSString *) index; | |
dc5812ec | 860 | |
36bb2ca2 | 861 | - (NSDate *) seen; |
9e98e020 | 862 | |
36bb2ca2 JF |
863 | - (NSString *) latest; |
864 | - (NSString *) installed; | |
865 | - (BOOL) upgradable; | |
866 | - (BOOL) essential; | |
867 | - (BOOL) broken; | |
b4d89997 | 868 | |
36bb2ca2 JF |
869 | - (NSString *) id; |
870 | - (NSString *) name; | |
871 | - (NSString *) tagline; | |
872 | - (NSString *) icon; | |
873 | - (NSString *) website; | |
b4d89997 | 874 | |
36bb2ca2 | 875 | - (Source *) source; |
b4d89997 | 876 | |
36bb2ca2 | 877 | - (BOOL) matches:(NSString *)text; |
b4d89997 | 878 | |
36bb2ca2 JF |
879 | - (NSComparisonResult) compareByName:(Package *)package; |
880 | - (NSComparisonResult) compareBySection:(Package *)package; | |
881 | - (NSComparisonResult) compareBySectionAndName:(Package *)package; | |
882 | - (NSComparisonResult) compareForChanges:(Package *)package; | |
b4d89997 | 883 | |
36bb2ca2 JF |
884 | - (void) install; |
885 | - (void) remove; | |
06aa974d | 886 | |
36bb2ca2 JF |
887 | - (NSNumber *) isSearchedForBy:(NSString *)search; |
888 | - (NSNumber *) isInstalledInSection:(NSString *)section; | |
889 | - (NSNumber *) isUninstalledInSection:(NSString *)section; | |
b4d89997 | 890 | |
36bb2ca2 | 891 | @end |
b4d89997 | 892 | |
36bb2ca2 | 893 | @implementation Package |
b4d89997 | 894 | |
36bb2ca2 JF |
895 | - (void) dealloc { |
896 | [latest_ release]; | |
897 | if (installed_ != nil) | |
898 | [installed_ release]; | |
b4d89997 | 899 | |
36bb2ca2 JF |
900 | [id_ release]; |
901 | if (name_ != nil) | |
902 | [name_ release]; | |
903 | [tagline_ release]; | |
904 | if (icon_ != nil) | |
905 | [icon_ release]; | |
906 | if (website_ != nil) | |
907 | [website_ release]; | |
9e98e020 | 908 | |
36bb2ca2 | 909 | [source_ release]; |
06aa974d | 910 | |
36bb2ca2 | 911 | [super dealloc]; |
b4d89997 JF |
912 | } |
913 | ||
36bb2ca2 JF |
914 | - (Package *) initWithIterator:(pkgCache::PkgIterator)iterator database:(Database *)database version:(pkgCache::VerIterator)version file:(pkgCache::VerFileIterator)file { |
915 | if ((self = [super init]) != nil) { | |
916 | iterator_ = iterator; | |
917 | database_ = database; | |
b4d89997 | 918 | |
36bb2ca2 JF |
919 | version_ = version; |
920 | file_ = file; | |
b4d89997 | 921 | |
36bb2ca2 | 922 | pkgRecords::Parser *parser = &[database_ records]->Lookup(file_); |
b4d89997 | 923 | |
36bb2ca2 JF |
924 | const char *begin, *end; |
925 | parser->GetRec(begin, end); | |
b4d89997 | 926 | |
36bb2ca2 JF |
927 | latest_ = [[NSString stringWithCString:version_.VerStr()] retain]; |
928 | installed_ = iterator_.CurrentVer().end() ? nil : [[NSString stringWithCString:iterator_.CurrentVer().VerStr()] retain]; | |
2367a917 | 929 | |
36bb2ca2 JF |
930 | id_ = [[[NSString stringWithCString:iterator_.Name()] lowercaseString] retain]; |
931 | name_ = Scour("Name", begin, end); | |
932 | if (name_ != nil) | |
933 | name_ = [name_ retain]; | |
934 | tagline_ = [[NSString stringWithCString:parser->ShortDesc().c_str()] retain]; | |
935 | icon_ = Scour("Icon", begin, end); | |
936 | if (icon_ != nil) | |
937 | icon_ = [icon_ retain]; | |
938 | website_ = Scour("Website", begin, end); | |
939 | if (website_ != nil) | |
940 | website_ = [website_ retain]; | |
06aa974d | 941 | |
36bb2ca2 | 942 | source_ = [[database_ getSource:file_.File()] retain]; |
06aa974d | 943 | |
36bb2ca2 JF |
944 | NSMutableDictionary *metadata = [Packages_ objectForKey:id_]; |
945 | if (metadata == nil || [metadata count] == 0) { | |
946 | metadata = [NSMutableDictionary dictionaryWithObjectsAndKeys: | |
947 | now_, @"FirstSeen", | |
948 | nil]; | |
b4d89997 | 949 | |
36bb2ca2 JF |
950 | [Packages_ setObject:metadata forKey:id_]; |
951 | } | |
952 | } return self; | |
dc5812ec JF |
953 | } |
954 | ||
36bb2ca2 JF |
955 | + (Package *) packageWithIterator:(pkgCache::PkgIterator)iterator database:(Database *)database { |
956 | for (pkgCache::VerIterator version = iterator.VersionList(); !version.end(); ++version) | |
957 | for (pkgCache::VerFileIterator file = version.FileList(); !file.end(); ++file) | |
958 | return [[[Package alloc] | |
959 | initWithIterator:iterator | |
960 | database:database | |
961 | version:version | |
962 | file:file] | |
963 | autorelease]; | |
964 | return nil; | |
dc5812ec JF |
965 | } |
966 | ||
36bb2ca2 JF |
967 | - (NSString *) section { |
968 | const char *section = iterator_.Section(); | |
969 | return section == NULL ? nil : [[NSString stringWithCString:section] stringByReplacingCharacter:'_' withCharacter:' ']; | |
dc5812ec JF |
970 | } |
971 | ||
36bb2ca2 JF |
972 | - (Address *) maintainer { |
973 | pkgRecords::Parser *parser = &[database_ records]->Lookup(file_); | |
974 | return [Address addressWithString:[NSString stringWithCString:parser->Maintainer().c_str()]]; | |
8fe19fc1 JF |
975 | } |
976 | ||
36bb2ca2 JF |
977 | - (size_t) size { |
978 | return version_->InstalledSize; | |
dc5812ec JF |
979 | } |
980 | ||
36bb2ca2 JF |
981 | - (NSString *) description { |
982 | pkgRecords::Parser *parser = &[database_ records]->Lookup(file_); | |
983 | NSString *description([NSString stringWithCString:parser->LongDesc().c_str()]); | |
8fe19fc1 | 984 | |
36bb2ca2 JF |
985 | NSArray *lines = [description componentsSeparatedByString:@"\n"]; |
986 | NSMutableArray *trimmed = [NSMutableArray arrayWithCapacity:([lines count] - 1)]; | |
987 | if ([lines count] < 2) | |
988 | return nil; | |
3178d79b | 989 | |
36bb2ca2 JF |
990 | NSCharacterSet *whitespace = [NSCharacterSet whitespaceCharacterSet]; |
991 | for (size_t i(1); i != [lines count]; ++i) { | |
992 | NSString *trim = [[lines objectAtIndex:i] stringByTrimmingCharactersInSet:whitespace]; | |
993 | [trimmed addObject:trim]; | |
994 | } | |
3178d79b | 995 | |
36bb2ca2 JF |
996 | return [trimmed componentsJoinedByString:@"\n"]; |
997 | } | |
dc5812ec | 998 | |
36bb2ca2 JF |
999 | - (NSString *) index { |
1000 | NSString *index = [[[self name] substringToIndex:1] uppercaseString]; | |
1001 | return [index length] != 0 && isalpha([index characterAtIndex:0]) ? index : @"123"; | |
1002 | } | |
3178d79b | 1003 | |
36bb2ca2 JF |
1004 | - (NSDate *) seen { |
1005 | return [[Packages_ objectForKey:id_] objectForKey:@"FirstSeen"]; | |
3178d79b JF |
1006 | } |
1007 | ||
36bb2ca2 JF |
1008 | - (NSString *) latest { |
1009 | return latest_; | |
8fe19fc1 JF |
1010 | } |
1011 | ||
36bb2ca2 JF |
1012 | - (NSString *) installed { |
1013 | return installed_; | |
3178d79b JF |
1014 | } |
1015 | ||
36bb2ca2 JF |
1016 | - (BOOL) upgradable { |
1017 | if (NSString *installed = [self installed]) | |
1018 | return [[self latest] compare:installed] != NSOrderedSame ? YES : NO; | |
1019 | else | |
1020 | return [self essential]; | |
1021 | } | |
3178d79b | 1022 | |
36bb2ca2 JF |
1023 | - (BOOL) essential { |
1024 | return (iterator_->Flags & pkgCache::Flag::Essential) == 0 ? NO : YES; | |
3178d79b JF |
1025 | } |
1026 | ||
36bb2ca2 JF |
1027 | - (BOOL) broken { |
1028 | return (*[database_ cache])[iterator_].InstBroken(); | |
8fe19fc1 JF |
1029 | } |
1030 | ||
36bb2ca2 JF |
1031 | - (NSString *) id { |
1032 | return id_; | |
8fe19fc1 JF |
1033 | } |
1034 | ||
36bb2ca2 JF |
1035 | - (NSString *) name { |
1036 | return name_ == nil ? id_ : name_; | |
1037 | } | |
8fe19fc1 | 1038 | |
36bb2ca2 JF |
1039 | - (NSString *) tagline { |
1040 | return tagline_; | |
8fe19fc1 JF |
1041 | } |
1042 | ||
36bb2ca2 JF |
1043 | - (NSString *) icon { |
1044 | return icon_; | |
1045 | } | |
8fe19fc1 | 1046 | |
36bb2ca2 JF |
1047 | - (NSString *) website { |
1048 | return website_; | |
8fe19fc1 JF |
1049 | } |
1050 | ||
36bb2ca2 JF |
1051 | - (Source *) source { |
1052 | return source_; | |
8fe19fc1 JF |
1053 | } |
1054 | ||
36bb2ca2 JF |
1055 | - (BOOL) matches:(NSString *)text { |
1056 | if (text == nil) | |
1057 | return NO; | |
8fe19fc1 | 1058 | |
36bb2ca2 | 1059 | NSRange range; |
8fe19fc1 | 1060 | |
36bb2ca2 JF |
1061 | range = [[self id] rangeOfString:text options:NSCaseInsensitiveSearch]; |
1062 | if (range.location != NSNotFound) | |
1063 | return YES; | |
8fe19fc1 | 1064 | |
36bb2ca2 JF |
1065 | range = [[self name] rangeOfString:text options:NSCaseInsensitiveSearch]; |
1066 | if (range.location != NSNotFound) | |
1067 | return YES; | |
8fe19fc1 | 1068 | |
36bb2ca2 JF |
1069 | range = [[self tagline] rangeOfString:text options:NSCaseInsensitiveSearch]; |
1070 | if (range.location != NSNotFound) | |
1071 | return YES; | |
8fe19fc1 | 1072 | |
36bb2ca2 JF |
1073 | return NO; |
1074 | } | |
8fe19fc1 | 1075 | |
36bb2ca2 JF |
1076 | - (NSComparisonResult) compareByName:(Package *)package { |
1077 | NSString *lhs = [self name]; | |
1078 | NSString *rhs = [package name]; | |
8fe19fc1 | 1079 | |
36bb2ca2 JF |
1080 | if ([lhs length] != 0 && [rhs length] != 0) { |
1081 | unichar lhc = [lhs characterAtIndex:0]; | |
1082 | unichar rhc = [rhs characterAtIndex:0]; | |
1083 | ||
1084 | if (isalpha(lhc) && !isalpha(rhc)) | |
1085 | return NSOrderedAscending; | |
1086 | else if (!isalpha(lhc) && isalpha(rhc)) | |
1087 | return NSOrderedDescending; | |
8fe19fc1 JF |
1088 | } |
1089 | ||
36bb2ca2 | 1090 | return [lhs caseInsensitiveCompare:rhs]; |
8fe19fc1 JF |
1091 | } |
1092 | ||
36bb2ca2 JF |
1093 | - (NSComparisonResult) compareBySection:(Package *)package { |
1094 | NSString *lhs = [self section]; | |
1095 | NSString *rhs = [package section]; | |
3178d79b | 1096 | |
36bb2ca2 JF |
1097 | if (lhs == NULL && rhs != NULL) |
1098 | return NSOrderedAscending; | |
1099 | else if (lhs != NULL && rhs == NULL) | |
1100 | return NSOrderedDescending; | |
1101 | else if (lhs != NULL && rhs != NULL) { | |
a72074b2 | 1102 | NSComparisonResult result = [lhs caseInsensitiveCompare:rhs]; |
36bb2ca2 JF |
1103 | if (result != NSOrderedSame) |
1104 | return result; | |
1105 | } | |
3178d79b | 1106 | |
36bb2ca2 JF |
1107 | return NSOrderedSame; |
1108 | } | |
3178d79b | 1109 | |
36bb2ca2 JF |
1110 | - (NSComparisonResult) compareBySectionAndName:(Package *)package { |
1111 | NSString *lhs = [self section]; | |
1112 | NSString *rhs = [package section]; | |
3178d79b | 1113 | |
36bb2ca2 JF |
1114 | if (lhs == NULL && rhs != NULL) |
1115 | return NSOrderedAscending; | |
1116 | else if (lhs != NULL && rhs == NULL) | |
1117 | return NSOrderedDescending; | |
1118 | else if (lhs != NULL && rhs != NULL) { | |
1119 | NSComparisonResult result = [lhs compare:rhs]; | |
1120 | if (result != NSOrderedSame) | |
1121 | return result; | |
1122 | } | |
3178d79b | 1123 | |
36bb2ca2 JF |
1124 | return [self compareByName:package]; |
1125 | } | |
3178d79b | 1126 | |
36bb2ca2 JF |
1127 | - (NSComparisonResult) compareForChanges:(Package *)package { |
1128 | BOOL lhs = [self upgradable]; | |
1129 | BOOL rhs = [package upgradable]; | |
8fe19fc1 | 1130 | |
36bb2ca2 JF |
1131 | if (lhs != rhs) |
1132 | return lhs ? NSOrderedAscending : NSOrderedDescending; | |
1133 | else if (!lhs) { | |
1134 | switch ([[self seen] compare:[package seen]]) { | |
1135 | case NSOrderedAscending: | |
1136 | return NSOrderedDescending; | |
1137 | case NSOrderedSame: | |
1138 | break; | |
1139 | case NSOrderedDescending: | |
1140 | return NSOrderedAscending; | |
1141 | default: | |
1142 | _assert(false); | |
1143 | } | |
1144 | } | |
8fe19fc1 | 1145 | |
36bb2ca2 JF |
1146 | return [self compareByName:package]; |
1147 | } | |
8fe19fc1 | 1148 | |
36bb2ca2 JF |
1149 | - (void) install { |
1150 | pkgProblemResolver *resolver = [database_ resolver]; | |
1151 | resolver->Clear(iterator_); | |
1152 | resolver->Protect(iterator_); | |
1153 | pkgCacheFile &cache([database_ cache]); | |
1154 | cache->MarkInstall(iterator_, false); | |
1155 | pkgDepCache::StateCache &state((*cache)[iterator_]); | |
1156 | if (!state.Install()) | |
1157 | cache->SetReInstall(iterator_, true); | |
1158 | } | |
68a238ec | 1159 | |
36bb2ca2 JF |
1160 | - (void) remove { |
1161 | pkgProblemResolver *resolver = [database_ resolver]; | |
1162 | resolver->Clear(iterator_); | |
1163 | resolver->Protect(iterator_); | |
1164 | resolver->Remove(iterator_); | |
1165 | [database_ cache]->MarkDelete(iterator_, true); | |
1166 | } | |
8fe19fc1 | 1167 | |
36bb2ca2 JF |
1168 | - (NSNumber *) isSearchedForBy:(NSString *)search { |
1169 | return [NSNumber numberWithBool:[self matches:search]]; | |
1170 | } | |
8fe19fc1 | 1171 | |
36bb2ca2 JF |
1172 | - (NSNumber *) isInstalledInSection:(NSString *)section { |
1173 | return [NSNumber numberWithBool:([self installed] != nil && (section == nil || [section isEqualToString:[self section]]))]; | |
1174 | } | |
8fe19fc1 | 1175 | |
36bb2ca2 JF |
1176 | - (NSNumber *) isUninstalledInSection:(NSString *)section { |
1177 | return [NSNumber numberWithBool:([self installed] == nil && (section == nil || [section isEqualToString:[self section]]))]; | |
1178 | } | |
8fe19fc1 | 1179 | |
36bb2ca2 JF |
1180 | @end |
1181 | /* }}} */ | |
1182 | /* Section Class {{{ */ | |
1183 | @interface Section : NSObject { | |
1184 | NSString *name_; | |
1185 | size_t row_; | |
1186 | size_t count_; | |
1187 | } | |
3178d79b | 1188 | |
36bb2ca2 JF |
1189 | - (Section *) initWithName:(NSString *)name row:(size_t)row; |
1190 | - (NSString *) name; | |
1191 | - (size_t) row; | |
1192 | - (size_t) count; | |
1193 | - (void) addToCount; | |
b19871dd | 1194 | |
36bb2ca2 | 1195 | @end |
b19871dd | 1196 | |
36bb2ca2 | 1197 | @implementation Section |
b19871dd | 1198 | |
36bb2ca2 JF |
1199 | - (void) dealloc { |
1200 | [name_ release]; | |
1201 | [super dealloc]; | |
1202 | } | |
b19871dd | 1203 | |
36bb2ca2 JF |
1204 | - (Section *) initWithName:(NSString *)name row:(size_t)row { |
1205 | if ((self = [super init]) != nil) { | |
1206 | name_ = [name retain]; | |
1207 | row_ = row; | |
b19871dd JF |
1208 | } return self; |
1209 | } | |
1210 | ||
36bb2ca2 JF |
1211 | - (NSString *) name { |
1212 | return name_; | |
1213 | } | |
1214 | ||
1215 | - (size_t) row { | |
1216 | return row_; | |
1217 | } | |
1218 | ||
1219 | - (size_t) count { | |
1220 | return count_; | |
1221 | } | |
1222 | ||
1223 | - (void) addToCount { | |
1224 | ++count_; | |
1225 | } | |
1226 | ||
b19871dd JF |
1227 | @end |
1228 | /* }}} */ | |
1229 | ||
36bb2ca2 JF |
1230 | /* Database Implementation {{{ */ |
1231 | @implementation Database | |
ec97ef06 | 1232 | |
36bb2ca2 JF |
1233 | - (void) dealloc { |
1234 | _assert(false); | |
1235 | [super dealloc]; | |
1236 | } | |
ec97ef06 | 1237 | |
36bb2ca2 JF |
1238 | - (void) _readStatus:(NSNumber *)fd { |
1239 | NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; | |
c7c6384e | 1240 | |
36bb2ca2 JF |
1241 | __gnu_cxx::stdio_filebuf<char> ib([fd intValue], std::ios::in); |
1242 | std::istream is(&ib); | |
1243 | std::string line; | |
ec97ef06 | 1244 | |
36bb2ca2 JF |
1245 | const char *error; |
1246 | int offset; | |
1247 | pcre *code = pcre_compile("^([^:]*):([^:]*):([^:]*):(.*)$", 0, &error, &offset, NULL); | |
ec97ef06 | 1248 | |
36bb2ca2 JF |
1249 | pcre_extra *study = NULL; |
1250 | int capture; | |
1251 | pcre_fullinfo(code, study, PCRE_INFO_CAPTURECOUNT, &capture); | |
1252 | int matches[(capture + 1) * 3]; | |
ec97ef06 | 1253 | |
36bb2ca2 JF |
1254 | while (std::getline(is, line)) { |
1255 | const char *data(line.c_str()); | |
ec97ef06 | 1256 | |
36bb2ca2 | 1257 | _assert(pcre_exec(code, study, data, line.size(), 0, 0, matches, sizeof(matches) / sizeof(matches[0])) >= 0); |
ec97ef06 | 1258 | |
36bb2ca2 JF |
1259 | std::istringstream buffer(line.substr(matches[6], matches[7] - matches[6])); |
1260 | float percent; | |
1261 | buffer >> percent; | |
1262 | [delegate_ setProgressPercent:(percent / 100)]; | |
c7c6384e | 1263 | |
36bb2ca2 JF |
1264 | NSString *string = [NSString stringWithCString:(data + matches[8]) length:(matches[9] - matches[8])]; |
1265 | std::string type(line.substr(matches[2], matches[3] - matches[2])); | |
ec97ef06 | 1266 | |
36bb2ca2 JF |
1267 | if (type == "pmerror") |
1268 | [delegate_ setProgressError:string]; | |
1269 | else if (type == "pmstatus") | |
1270 | [delegate_ setProgressTitle:string]; | |
1271 | else if (type == "pmconffile") | |
1272 | ; | |
1273 | else _assert(false); | |
1274 | } | |
ec97ef06 | 1275 | |
36bb2ca2 JF |
1276 | [pool release]; |
1277 | _assert(false); | |
1278 | } | |
ec97ef06 | 1279 | |
36bb2ca2 JF |
1280 | - (void) _readOutput:(NSNumber *)fd { |
1281 | NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; | |
ec97ef06 | 1282 | |
36bb2ca2 JF |
1283 | __gnu_cxx::stdio_filebuf<char> ib([fd intValue], std::ios::in); |
1284 | std::istream is(&ib); | |
1285 | std::string line; | |
1286 | ||
1287 | while (std::getline(is, line)) | |
1288 | [delegate_ addProgressOutput:[NSString stringWithCString:line.c_str()]]; | |
1289 | ||
1290 | [pool release]; | |
1291 | _assert(false); | |
ec97ef06 JF |
1292 | } |
1293 | ||
36bb2ca2 JF |
1294 | - (Package *) packageWithName:(NSString *)name { |
1295 | pkgCache::PkgIterator iterator(cache_->FindPkg([name UTF8String])); | |
1296 | return iterator.end() ? nil : [Package packageWithIterator:iterator database:self]; | |
1297 | } | |
1298 | ||
1299 | - (Database *) init { | |
ec97ef06 | 1300 | if ((self = [super init]) != nil) { |
36bb2ca2 JF |
1301 | records_ = NULL; |
1302 | resolver_ = NULL; | |
1303 | fetcher_ = NULL; | |
1304 | lock_ = NULL; | |
ec97ef06 | 1305 | |
36bb2ca2 JF |
1306 | sources_ = [[NSMutableDictionary dictionaryWithCapacity:16] retain]; |
1307 | packages_ = [[NSMutableArray arrayWithCapacity:16] retain]; | |
ec97ef06 | 1308 | |
36bb2ca2 | 1309 | int fds[2]; |
ec97ef06 | 1310 | |
36bb2ca2 JF |
1311 | _assert(pipe(fds) != -1); |
1312 | statusfd_ = fds[1]; | |
ec97ef06 | 1313 | |
36bb2ca2 JF |
1314 | [NSThread |
1315 | detachNewThreadSelector:@selector(_readStatus:) | |
1316 | toTarget:self | |
1317 | withObject:[[NSNumber numberWithInt:fds[0]] retain] | |
1318 | ]; | |
ec97ef06 | 1319 | |
36bb2ca2 JF |
1320 | _assert(pipe(fds) != -1); |
1321 | _assert(dup2(fds[1], 1) != -1); | |
1322 | _assert(close(fds[1]) != -1); | |
1323 | ||
1324 | [NSThread | |
1325 | detachNewThreadSelector:@selector(_readOutput:) | |
1326 | toTarget:self | |
1327 | withObject:[[NSNumber numberWithInt:fds[0]] retain] | |
1328 | ]; | |
ec97ef06 JF |
1329 | } return self; |
1330 | } | |
1331 | ||
36bb2ca2 JF |
1332 | - (pkgCacheFile &) cache { |
1333 | return cache_; | |
ec97ef06 JF |
1334 | } |
1335 | ||
36bb2ca2 JF |
1336 | - (pkgRecords *) records { |
1337 | return records_; | |
ec97ef06 JF |
1338 | } |
1339 | ||
36bb2ca2 JF |
1340 | - (pkgProblemResolver *) resolver { |
1341 | return resolver_; | |
ec97ef06 JF |
1342 | } |
1343 | ||
36bb2ca2 JF |
1344 | - (pkgAcquire &) fetcher { |
1345 | return *fetcher_; | |
ec97ef06 JF |
1346 | } |
1347 | ||
36bb2ca2 JF |
1348 | - (NSArray *) packages { |
1349 | return packages_; | |
ec97ef06 JF |
1350 | } |
1351 | ||
36bb2ca2 JF |
1352 | - (void) reloadData { |
1353 | _error->Discard(); | |
1354 | delete list_; | |
1355 | manager_ = NULL; | |
1356 | delete lock_; | |
1357 | delete fetcher_; | |
1358 | delete resolver_; | |
1359 | delete records_; | |
1360 | cache_.Close(); | |
1361 | ||
1362 | if (!cache_.Open(progress_, true)) { | |
1363 | fprintf(stderr, "repairing corrupted database...\n"); | |
1364 | _error->Discard(); | |
1365 | [self updateWithStatus:status_]; | |
1366 | _assert(cache_.Open(progress_, true)); | |
1367 | } | |
1368 | ||
1369 | now_ = [[NSDate date] retain]; | |
1370 | ||
1371 | records_ = new pkgRecords(cache_); | |
1372 | resolver_ = new pkgProblemResolver(cache_); | |
1373 | fetcher_ = new pkgAcquire(&status_); | |
1374 | lock_ = NULL; | |
1375 | ||
1376 | list_ = new pkgSourceList(); | |
1377 | _assert(list_->ReadMainList()); | |
1378 | ||
1379 | [sources_ removeAllObjects]; | |
1380 | for (pkgSourceList::const_iterator source = list_->begin(); source != list_->end(); ++source) { | |
1381 | std::vector<pkgIndexFile *> *indices = (*source)->GetIndexFiles(); | |
1382 | for (std::vector<pkgIndexFile *>::const_iterator index = indices->begin(); index != indices->end(); ++index) | |
1383 | [sources_ | |
1384 | setObject:[[[Source alloc] initWithMetaIndex:*source] autorelease] | |
1385 | forKey:[NSNumber numberWithLong:reinterpret_cast<uintptr_t>(*index)] | |
1386 | ]; | |
1387 | } | |
1388 | ||
1389 | [packages_ removeAllObjects]; | |
1390 | for (pkgCache::PkgIterator iterator = cache_->PkgBegin(); !iterator.end(); ++iterator) | |
1391 | if (Package *package = [Package packageWithIterator:iterator database:self]) | |
1392 | if ([package source] != nil || [package installed] != nil) | |
1393 | [packages_ addObject:package]; | |
ec97ef06 JF |
1394 | } |
1395 | ||
36bb2ca2 JF |
1396 | - (void) prepare { |
1397 | pkgRecords records(cache_); | |
1398 | ||
1399 | lock_ = new FileFd(); | |
1400 | lock_->Fd(GetLock(_config->FindDir("Dir::Cache::Archives") + "lock")); | |
1401 | _assert(!_error->PendingError()); | |
1402 | ||
1403 | pkgSourceList list; | |
1404 | // XXX: explain this with an error message | |
1405 | _assert(list.ReadMainList()); | |
1406 | ||
1407 | manager_ = (_system->CreatePM(cache_)); | |
1408 | _assert(manager_->GetArchives(fetcher_, &list, &records)); | |
1409 | _assert(!_error->PendingError()); | |
ec97ef06 JF |
1410 | } |
1411 | ||
36bb2ca2 | 1412 | - (void) perform { |
a72074b2 JF |
1413 | NSMutableArray *before = [NSMutableArray arrayWithCapacity:16]; { |
1414 | pkgSourceList list; | |
1415 | _assert(list.ReadMainList()); | |
1416 | for (pkgSourceList::const_iterator source = list.begin(); source != list.end(); ++source) | |
1417 | [before addObject:[NSString stringWithUTF8String:(*source)->GetURI().c_str()]]; | |
1418 | } | |
a0be02eb | 1419 | |
36bb2ca2 JF |
1420 | if (fetcher_->Run(PulseInterval_) != pkgAcquire::Continue) |
1421 | return; | |
1422 | ||
1423 | _system->UnLock(); | |
1424 | pkgPackageManager::OrderResult result = manager_->DoInstall(statusfd_); | |
1425 | ||
1426 | if (result == pkgPackageManager::Failed) | |
1427 | return; | |
1428 | if (_error->PendingError()) | |
1429 | return; | |
1430 | if (result != pkgPackageManager::Completed) | |
1431 | return; | |
a0be02eb | 1432 | |
a72074b2 JF |
1433 | NSMutableArray *after = [NSMutableArray arrayWithCapacity:16]; { |
1434 | pkgSourceList list; | |
1435 | _assert(list.ReadMainList()); | |
1436 | for (pkgSourceList::const_iterator source = list.begin(); source != list.end(); ++source) | |
1437 | [after addObject:[NSString stringWithUTF8String:(*source)->GetURI().c_str()]]; | |
1438 | } | |
1439 | ||
1440 | if (![before isEqualToArray:after]) | |
1441 | [self update]; | |
ec97ef06 JF |
1442 | } |
1443 | ||
36bb2ca2 JF |
1444 | - (void) upgrade { |
1445 | _assert(cache_->DelCount() == 0 && cache_->InstCount() == 0); | |
1446 | _assert(pkgApplyStatus(cache_)); | |
1447 | ||
1448 | if (cache_->BrokenCount() != 0) { | |
1449 | _assert(pkgFixBroken(cache_)); | |
1450 | _assert(cache_->BrokenCount() == 0); | |
1451 | _assert(pkgMinimizeUpgrade(cache_)); | |
1452 | } | |
1453 | ||
1454 | _assert(pkgDistUpgrade(cache_)); | |
c7c6384e JF |
1455 | } |
1456 | ||
36bb2ca2 JF |
1457 | - (void) update { |
1458 | [self updateWithStatus:status_]; | |
1459 | } | |
b4d89997 | 1460 | |
36bb2ca2 JF |
1461 | - (void) updateWithStatus:(Status &)status { |
1462 | pkgSourceList list; | |
1463 | _assert(list.ReadMainList()); | |
b4d89997 | 1464 | |
36bb2ca2 JF |
1465 | FileFd lock; |
1466 | lock.Fd(GetLock(_config->FindDir("Dir::State::Lists") + "lock")); | |
1467 | _assert(!_error->PendingError()); | |
1468 | ||
1469 | pkgAcquire fetcher(&status); | |
1470 | _assert(list.GetIndexes(&fetcher)); | |
1471 | ||
1472 | if (fetcher.Run(PulseInterval_) != pkgAcquire::Failed) { | |
1473 | bool failed = false; | |
1474 | for (pkgAcquire::ItemIterator item = fetcher.ItemsBegin(); item != fetcher.ItemsEnd(); item++) | |
1475 | if ((*item)->Status != pkgAcquire::Item::StatDone) { | |
1476 | (*item)->Finished(); | |
1477 | failed = true; | |
1478 | } | |
1479 | ||
1480 | if (!failed && _config->FindB("APT::Get::List-Cleanup", true) == true) { | |
1481 | _assert(fetcher.Clean(_config->FindDir("Dir::State::lists"))); | |
1482 | _assert(fetcher.Clean(_config->FindDir("Dir::State::lists") + "partial/")); | |
b4d89997 | 1483 | } |
36bb2ca2 JF |
1484 | |
1485 | [Metadata_ setObject:[NSDate date] forKey:@"LastUpdate"]; | |
b4d89997 JF |
1486 | } |
1487 | } | |
1488 | ||
36bb2ca2 JF |
1489 | - (void) setDelegate:(id)delegate { |
1490 | delegate_ = delegate; | |
1491 | status_.setDelegate(delegate); | |
1492 | progress_.setDelegate(delegate); | |
1493 | } | |
b4d89997 | 1494 | |
36bb2ca2 JF |
1495 | - (Source *) getSource:(const pkgCache::PkgFileIterator &)file { |
1496 | pkgIndexFile *index(NULL); | |
1497 | list_->FindIndex(file, index); | |
1498 | return [sources_ objectForKey:[NSNumber numberWithLong:reinterpret_cast<uintptr_t>(index)]]; | |
b19871dd JF |
1499 | } |
1500 | ||
36bb2ca2 JF |
1501 | @end |
1502 | /* }}} */ | |
b4d89997 | 1503 | |
36bb2ca2 JF |
1504 | /* RVPage Interface {{{ */ |
1505 | @class RVBook; | |
b19871dd | 1506 | |
36bb2ca2 JF |
1507 | @interface RVPage : UIView { |
1508 | _transient RVBook *book_; | |
1509 | _transient id delegate_; | |
1510 | } | |
b4d89997 | 1511 | |
36bb2ca2 JF |
1512 | - (NSString *) title; |
1513 | - (NSString *) backButtonTitle; | |
1514 | - (NSString *) rightButtonTitle; | |
1515 | - (NSString *) leftButtonTitle; | |
1516 | - (UIView *) accessoryView; | |
b4d89997 | 1517 | |
36bb2ca2 JF |
1518 | - (void) _rightButtonClicked; |
1519 | - (void) _leftButtonClicked; | |
b4d89997 | 1520 | |
36bb2ca2 JF |
1521 | - (void) setPageActive:(BOOL)active; |
1522 | - (void) resetViewAnimated:(BOOL)animated; | |
b4d89997 | 1523 | |
36bb2ca2 JF |
1524 | - (void) setTitle:(NSString *)title; |
1525 | - (void) setBackButtonTitle:(NSString *)title; | |
ec97ef06 | 1526 | |
36bb2ca2 JF |
1527 | - (void) reloadButtons; |
1528 | - (void) reloadData; | |
b4d89997 | 1529 | |
36bb2ca2 | 1530 | - (id) initWithBook:(RVBook *)book; |
b19871dd | 1531 | |
36bb2ca2 | 1532 | - (void) setDelegate:(id)delegate; |
b19871dd | 1533 | |
36bb2ca2 JF |
1534 | @end |
1535 | /* }}} */ | |
1536 | /* Reset View {{{ */ | |
1537 | @protocol RVDelegate | |
1538 | - (void) setPageActive:(BOOL)active with:(id)object; | |
1539 | - (void) resetViewAnimated:(BOOL)animated with:(id)object; | |
1540 | - (void) reloadDataWith:(id)object; | |
1541 | @end | |
b19871dd | 1542 | |
36bb2ca2 JF |
1543 | @interface RVBook : UIView { |
1544 | NSMutableArray *pages_; | |
1545 | UINavigationBar *navbar_; | |
1546 | UITransitionView *transition_; | |
1547 | BOOL resetting_; | |
1548 | _transient id delegate_; | |
1549 | } | |
b4d89997 | 1550 | |
36bb2ca2 JF |
1551 | - (id) initWithFrame:(CGRect)frame; |
1552 | - (void) setDelegate:(id)delegate; | |
ec97ef06 | 1553 | |
36bb2ca2 | 1554 | - (void) setPage:(RVPage *)page; |
ec97ef06 | 1555 | |
36bb2ca2 JF |
1556 | - (void) pushPage:(RVPage *)page; |
1557 | - (void) popPages:(unsigned)pages; | |
b4d89997 | 1558 | |
36bb2ca2 | 1559 | - (void) setPrompt:(NSString *)prompt; |
b19871dd | 1560 | |
36bb2ca2 JF |
1561 | - (void) resetViewAnimated:(BOOL)animated; |
1562 | - (void) resetViewAnimated:(BOOL)animated toPage:(RVPage *)page; | |
b4d89997 | 1563 | |
36bb2ca2 JF |
1564 | - (void) setTitle:(NSString *)title forPage:(RVPage *)page; |
1565 | - (void) setBackButtonTitle:(NSString *)title forPage:(RVPage *)page; | |
1566 | - (void) reloadButtonsForPage:(RVPage *)page; | |
b4d89997 | 1567 | |
36bb2ca2 | 1568 | - (void) reloadData; |
b4d89997 | 1569 | |
36bb2ca2 | 1570 | - (CGRect) pageBounds; |
b4d89997 | 1571 | |
36bb2ca2 | 1572 | @end |
b4d89997 | 1573 | |
36bb2ca2 | 1574 | @implementation RVBook |
ec97ef06 | 1575 | |
36bb2ca2 JF |
1576 | - (void) dealloc { |
1577 | [navbar_ setDelegate:nil]; | |
b4d89997 | 1578 | |
36bb2ca2 JF |
1579 | [pages_ release]; |
1580 | [navbar_ release]; | |
1581 | [transition_ release]; | |
1582 | [super dealloc]; | |
b19871dd JF |
1583 | } |
1584 | ||
36bb2ca2 JF |
1585 | - (void) navigationBar:(UINavigationBar *)navbar buttonClicked:(int)button { |
1586 | _assert([pages_ count] != 0); | |
1587 | RVPage *page = [pages_ lastObject]; | |
1588 | switch (button) { | |
1589 | case 0: [page _rightButtonClicked]; break; | |
1590 | case 1: [page _leftButtonClicked]; break; | |
1591 | } | |
b19871dd JF |
1592 | } |
1593 | ||
36bb2ca2 JF |
1594 | - (void) navigationBar:(UINavigationBar *)navbar poppedItem:(UINavigationItem *)item { |
1595 | _assert([pages_ count] != 0); | |
1596 | if (!resetting_) | |
1597 | [[pages_ lastObject] setPageActive:NO]; | |
1598 | [pages_ removeLastObject]; | |
1599 | if (!resetting_) | |
1600 | [self resetViewAnimated:YES toPage:[pages_ lastObject]]; | |
b19871dd JF |
1601 | } |
1602 | ||
36bb2ca2 JF |
1603 | - (id) initWithFrame:(CGRect)frame { |
1604 | if ((self = [super initWithFrame:frame]) != nil) { | |
1605 | pages_ = [[NSMutableArray arrayWithCapacity:4] retain]; | |
b4d89997 | 1606 | |
36bb2ca2 JF |
1607 | struct CGRect bounds = [self bounds]; |
1608 | CGSize navsize = [UINavigationBar defaultSizeWithPrompt]; | |
1609 | CGRect navrect = {{0, 0}, navsize}; | |
b4d89997 | 1610 | |
36bb2ca2 JF |
1611 | navbar_ = [[UINavigationBar alloc] initWithFrame:navrect]; |
1612 | [self addSubview:navbar_]; | |
b4d89997 | 1613 | |
36bb2ca2 JF |
1614 | [navbar_ setBarStyle:1]; |
1615 | [navbar_ setDelegate:self]; | |
b4d89997 | 1616 | |
36bb2ca2 | 1617 | [navbar_ setPrompt:@""]; |
b4d89997 | 1618 | |
36bb2ca2 JF |
1619 | transition_ = [[UITransitionView alloc] initWithFrame:CGRectMake( |
1620 | bounds.origin.x, bounds.origin.y + navsize.height, bounds.size.width, bounds.size.height - navsize.height | |
1621 | )]; | |
b4d89997 | 1622 | |
36bb2ca2 JF |
1623 | [self addSubview:transition_]; |
1624 | } return self; | |
b4d89997 JF |
1625 | } |
1626 | ||
36bb2ca2 JF |
1627 | - (void) setDelegate:(id)delegate { |
1628 | delegate_ = delegate; | |
b19871dd JF |
1629 | } |
1630 | ||
36bb2ca2 JF |
1631 | - (void) setPage:(RVPage *)page { |
1632 | if ([pages_ count] != 0) | |
1633 | [[pages_ lastObject] setPageActive:NO]; | |
b19871dd | 1634 | |
36bb2ca2 JF |
1635 | [navbar_ disableAnimation]; |
1636 | resetting_ = true; | |
1637 | for (unsigned i(0), pages([pages_ count]); i != pages; ++i) | |
1638 | [navbar_ popNavigationItem]; | |
1639 | resetting_ = false; | |
b19871dd | 1640 | |
36bb2ca2 JF |
1641 | [self pushPage:page]; |
1642 | [navbar_ enableAnimation]; | |
49048579 JF |
1643 | } |
1644 | ||
36bb2ca2 JF |
1645 | - (void) pushPage:(RVPage *)page { |
1646 | if ([pages_ count] != 0) | |
1647 | [[pages_ lastObject] setPageActive:NO]; | |
49048579 | 1648 | |
4cf4165e | 1649 | NSString *title = Simplify([page title]); |
b4d89997 | 1650 | |
36bb2ca2 JF |
1651 | NSString *backButtonTitle = [page backButtonTitle]; |
1652 | if (backButtonTitle == nil) | |
1653 | backButtonTitle = title; | |
b19871dd | 1654 | |
36bb2ca2 JF |
1655 | UINavigationItem *navitem = [[[UINavigationItem alloc] initWithTitle:title] autorelease]; |
1656 | [navitem setBackButtonTitle:backButtonTitle]; | |
1657 | [navbar_ pushNavigationItem:navitem]; | |
b19871dd | 1658 | |
36bb2ca2 JF |
1659 | BOOL animated = [pages_ count] == 0 ? NO : YES; |
1660 | [transition_ transition:(animated ? 1 : 0) toView:page]; | |
1661 | [page setPageActive:YES]; | |
b4d89997 | 1662 | |
36bb2ca2 JF |
1663 | [pages_ addObject:page]; |
1664 | [self reloadButtonsForPage:page]; | |
23672b39 | 1665 | |
36bb2ca2 | 1666 | [navbar_ setAccessoryView:[page accessoryView] animate:animated goingBack:NO]; |
ec97ef06 JF |
1667 | } |
1668 | ||
36bb2ca2 JF |
1669 | - (void) popPages:(unsigned)pages { |
1670 | if (pages == 0) | |
1671 | return; | |
b4d89997 | 1672 | |
36bb2ca2 | 1673 | [[pages_ lastObject] setPageActive:NO]; |
2a8d9add | 1674 | |
36bb2ca2 JF |
1675 | resetting_ = true; |
1676 | for (unsigned i(0); i != pages; ++i) | |
1677 | [navbar_ popNavigationItem]; | |
1678 | resetting_ = false; | |
b4d89997 | 1679 | |
36bb2ca2 JF |
1680 | [self resetViewAnimated:YES toPage:[pages_ lastObject]]; |
1681 | } | |
b4d89997 | 1682 | |
36bb2ca2 JF |
1683 | - (void) setPrompt:(NSString *)prompt { |
1684 | [navbar_ setPrompt:prompt]; | |
b4d89997 JF |
1685 | } |
1686 | ||
36bb2ca2 JF |
1687 | - (void) resetViewAnimated:(BOOL)animated { |
1688 | resetting_ = true; | |
1689 | ||
1690 | if ([pages_ count] > 1) { | |
1691 | [navbar_ disableAnimation]; | |
1692 | while ([pages_ count] != (animated ? 2 : 1)) | |
1693 | [navbar_ popNavigationItem]; | |
1694 | [navbar_ enableAnimation]; | |
1695 | if (animated) | |
1696 | [navbar_ popNavigationItem]; | |
1697 | } | |
1698 | ||
1699 | resetting_ = false; | |
1700 | ||
1701 | [self resetViewAnimated:animated toPage:[pages_ lastObject]]; | |
1702 | } | |
2a8d9add | 1703 | |
36bb2ca2 JF |
1704 | - (void) resetViewAnimated:(BOOL)animated toPage:(RVPage *)page { |
1705 | [page resetViewAnimated:animated]; | |
1706 | [transition_ transition:(animated ? 2 : 0) toView:page]; | |
1707 | [page setPageActive:YES]; | |
1708 | [self reloadButtonsForPage:page]; | |
1709 | [navbar_ setAccessoryView:[page accessoryView] animate:animated goingBack:YES]; | |
1710 | } | |
2a8d9add | 1711 | |
36bb2ca2 JF |
1712 | - (void) setTitle:(NSString *)title forPage:(RVPage *)page { |
1713 | if ([pages_ count] == 0 || page != [pages_ lastObject]) | |
1714 | return; | |
1715 | UINavigationItem *navitem = [navbar_ topItem]; | |
1716 | [navitem setTitle:title]; | |
1717 | } | |
2a8d9add | 1718 | |
36bb2ca2 JF |
1719 | - (void) setBackButtonTitle:(NSString *)title forPage:(RVPage *)page { |
1720 | if ([pages_ count] == 0 || page != [pages_ lastObject]) | |
1721 | return; | |
1722 | UINavigationItem *navitem = [navbar_ topItem]; | |
1723 | [navitem setBackButtonTitle:title]; | |
b19871dd JF |
1724 | } |
1725 | ||
36bb2ca2 JF |
1726 | - (void) reloadButtonsForPage:(RVPage *)page { |
1727 | if ([pages_ count] == 0 || page != [pages_ lastObject]) | |
1728 | return; | |
1729 | NSString *leftButtonTitle([pages_ count] == 1 ? [page leftButtonTitle] : nil); | |
1730 | [navbar_ showButtonsWithLeftTitle:leftButtonTitle rightTitle:[page rightButtonTitle]]; | |
1731 | } | |
9b70dd6d | 1732 | |
36bb2ca2 JF |
1733 | - (void) reloadData { |
1734 | for (int i(0), e([pages_ count]); i != e; ++i) { | |
1735 | RVPage *page([pages_ objectAtIndex:(e - i - 1)]); | |
1736 | [page reloadData]; | |
9b70dd6d | 1737 | } |
36bb2ca2 | 1738 | } |
9b70dd6d | 1739 | |
36bb2ca2 JF |
1740 | - (CGRect) pageBounds { |
1741 | return [transition_ bounds]; | |
b4d89997 JF |
1742 | } |
1743 | ||
36bb2ca2 JF |
1744 | @end |
1745 | /* }}} */ | |
1746 | /* RVPage Implementation {{{ */ | |
1747 | @implementation RVPage | |
b4d89997 | 1748 | |
36bb2ca2 JF |
1749 | - (NSString *) title { |
1750 | [self doesNotRecognizeSelector:_cmd]; | |
1751 | return nil; | |
1752 | } | |
b4d89997 | 1753 | |
36bb2ca2 JF |
1754 | - (NSString *) backButtonTitle { |
1755 | return nil; | |
b19871dd JF |
1756 | } |
1757 | ||
36bb2ca2 JF |
1758 | - (NSString *) leftButtonTitle { |
1759 | return nil; | |
b19871dd JF |
1760 | } |
1761 | ||
36bb2ca2 JF |
1762 | - (NSString *) rightButtonTitle { |
1763 | return nil; | |
b19871dd JF |
1764 | } |
1765 | ||
36bb2ca2 JF |
1766 | - (void) _rightButtonClicked { |
1767 | [self doesNotRecognizeSelector:_cmd]; | |
b19871dd JF |
1768 | } |
1769 | ||
36bb2ca2 JF |
1770 | - (void) _leftButtonClicked { |
1771 | [self doesNotRecognizeSelector:_cmd]; | |
1772 | } | |
b19871dd | 1773 | |
36bb2ca2 JF |
1774 | - (UIView *) accessoryView { |
1775 | return nil; | |
1776 | } | |
b19871dd | 1777 | |
36bb2ca2 JF |
1778 | - (void) setPageActive:(BOOL)active { |
1779 | } | |
b19871dd | 1780 | |
36bb2ca2 JF |
1781 | - (void) resetViewAnimated:(BOOL)animated { |
1782 | [self doesNotRecognizeSelector:_cmd]; | |
b19871dd | 1783 | } |
3178d79b | 1784 | |
36bb2ca2 JF |
1785 | - (void) setTitle:(NSString *)title { |
1786 | [book_ setTitle:title forPage:self]; | |
b19871dd | 1787 | } |
3178d79b | 1788 | |
36bb2ca2 JF |
1789 | - (void) setBackButtonTitle:(NSString *)title { |
1790 | [book_ setBackButtonTitle:title forPage:self]; | |
b19871dd | 1791 | } |
3178d79b | 1792 | |
36bb2ca2 JF |
1793 | - (void) reloadButtons { |
1794 | [book_ reloadButtonsForPage:self]; | |
b19871dd | 1795 | } |
3178d79b | 1796 | |
36bb2ca2 | 1797 | - (void) reloadData { |
b4d89997 JF |
1798 | } |
1799 | ||
36bb2ca2 JF |
1800 | - (id) initWithBook:(RVBook *)book { |
1801 | if ((self = [super initWithFrame:[book pageBounds]]) != nil) { | |
1802 | book_ = book; | |
1803 | } return self; | |
b4d89997 JF |
1804 | } |
1805 | ||
36bb2ca2 JF |
1806 | - (void) setDelegate:(id)delegate { |
1807 | delegate_ = delegate; | |
3178d79b JF |
1808 | } |
1809 | ||
dc5812ec JF |
1810 | @end |
1811 | /* }}} */ | |
b19871dd | 1812 | |
36bb2ca2 JF |
1813 | /* Confirmation View {{{ */ |
1814 | void AddTextView(NSMutableDictionary *fields, NSMutableArray *packages, NSString *key) { | |
1815 | if ([packages count] == 0) | |
1816 | return; | |
b4d89997 | 1817 | |
36bb2ca2 JF |
1818 | UITextView *text = GetTextView([packages count] == 0 ? @"n/a" : [packages componentsJoinedByString:@", "], 120, false); |
1819 | [fields setObject:text forKey:key]; | |
1820 | ||
1821 | CGColor blue(space_, 0, 0, 0.4, 1); | |
1822 | [text setTextColor:blue]; | |
dc5812ec JF |
1823 | } |
1824 | ||
36bb2ca2 JF |
1825 | @protocol ConfirmationViewDelegate |
1826 | - (void) cancel; | |
1827 | - (void) confirm; | |
1828 | @end | |
2367a917 | 1829 | |
36bb2ca2 JF |
1830 | @interface ConfirmationView : UIView { |
1831 | Database *database_; | |
1832 | id delegate_; | |
1833 | UITransitionView *transition_; | |
1834 | UIView *overlay_; | |
1835 | UINavigationBar *navbar_; | |
1836 | UIPreferencesTable *table_; | |
1837 | NSMutableDictionary *fields_; | |
1838 | UIAlertSheet *essential_; | |
1839 | } | |
dc5812ec | 1840 | |
36bb2ca2 | 1841 | - (void) cancel; |
8da60fb7 | 1842 | |
36bb2ca2 | 1843 | - (id) initWithView:(UIView *)view database:(Database *)database delegate:(id)delegate; |
b4d89997 | 1844 | |
dc5812ec JF |
1845 | @end |
1846 | ||
36bb2ca2 | 1847 | @implementation ConfirmationView |
dc5812ec | 1848 | |
2367a917 | 1849 | - (void) dealloc { |
36bb2ca2 JF |
1850 | [navbar_ setDelegate:nil]; |
1851 | [transition_ setDelegate:nil]; | |
1852 | [table_ setDataSource:nil]; | |
1853 | ||
1854 | [transition_ release]; | |
1855 | [overlay_ release]; | |
1856 | [navbar_ release]; | |
8da60fb7 | 1857 | [table_ release]; |
36bb2ca2 JF |
1858 | [fields_ release]; |
1859 | if (essential_ != nil) | |
1860 | [essential_ release]; | |
2367a917 JF |
1861 | [super dealloc]; |
1862 | } | |
1863 | ||
36bb2ca2 JF |
1864 | - (void) cancel { |
1865 | [transition_ transition:7 toView:nil]; | |
1866 | [delegate_ cancel]; | |
1867 | } | |
1868 | ||
1869 | - (void) transitionViewDidComplete:(UITransitionView*)view fromView:(UIView*)from toView:(UIView*)to { | |
1870 | if (from != nil && to == nil) | |
1871 | [self removeFromSuperview]; | |
1872 | } | |
1873 | ||
1874 | - (void) navigationBar:(UINavigationBar *)navbar buttonClicked:(int)button { | |
1875 | switch (button) { | |
1876 | case 0: | |
1877 | if (essential_ != nil) | |
1878 | [essential_ popupAlertAnimated:YES]; | |
1879 | else | |
1880 | [delegate_ confirm]; | |
1881 | break; | |
1882 | ||
1883 | case 1: | |
1884 | [self cancel]; | |
1885 | break; | |
1886 | } | |
1887 | } | |
1888 | ||
1889 | - (void) alertSheet:(UIAlertSheet *)sheet buttonClicked:(int)button { | |
1890 | [essential_ dismiss]; | |
1891 | [self cancel]; | |
1892 | } | |
1893 | ||
dc5812ec | 1894 | - (int) numberOfGroupsInPreferencesTable:(UIPreferencesTable *)table { |
36bb2ca2 | 1895 | return 2; |
dc5812ec JF |
1896 | } |
1897 | ||
1898 | - (NSString *) preferencesTable:(UIPreferencesTable *)table titleForGroup:(int)group { | |
1899 | switch (group) { | |
36bb2ca2 JF |
1900 | case 0: return @"Statistics"; |
1901 | case 1: return @"Modifications"; | |
dc5812ec JF |
1902 | |
1903 | default: _assert(false); | |
1904 | } | |
1905 | } | |
1906 | ||
1907 | - (int) preferencesTable:(UIPreferencesTable *)table numberOfRowsInGroup:(int)group { | |
1908 | switch (group) { | |
36bb2ca2 JF |
1909 | case 0: return 3; |
1910 | case 1: return [fields_ count]; | |
dc5812ec JF |
1911 | |
1912 | default: _assert(false); | |
1913 | } | |
1914 | } | |
1915 | ||
36bb2ca2 JF |
1916 | - (float) preferencesTable:(UIPreferencesTable *)table heightForRow:(int)row inGroup:(int)group withProposedHeight:(float)proposed { |
1917 | if (group != 1 || row == -1) | |
1918 | return proposed; | |
1919 | else { | |
1920 | _assert(size_t(row) < [fields_ count]); | |
1921 | return [[[fields_ allValues] objectAtIndex:row] visibleTextRect].size.height + TextViewOffset_; | |
1922 | } | |
1923 | } | |
1924 | ||
dc5812ec | 1925 | - (UIPreferencesTableCell *) preferencesTable:(UIPreferencesTable *)table cellForRow:(int)row inGroup:(int)group { |
b4d89997 JF |
1926 | UIPreferencesTableCell *cell = [[[UIPreferencesTableCell alloc] init] autorelease]; |
1927 | [cell setShowSelection:NO]; | |
dc5812ec JF |
1928 | |
1929 | switch (group) { | |
1930 | case 0: switch (row) { | |
36bb2ca2 JF |
1931 | case 0: { |
1932 | [cell setTitle:@"Downloading"]; | |
1933 | [cell setValue:SizeString([database_ fetcher].FetchNeeded())]; | |
1934 | } break; | |
1935 | ||
1936 | case 1: { | |
1937 | [cell setTitle:@"Resuming At"]; | |
1938 | [cell setValue:SizeString([database_ fetcher].PartialPresent())]; | |
1939 | } break; | |
1940 | ||
1941 | case 2: { | |
1942 | double size([database_ cache]->UsrSize()); | |
1943 | ||
1944 | if (size < 0) { | |
1945 | [cell setTitle:@"Disk Freeing"]; | |
1946 | [cell setValue:SizeString(-size)]; | |
1947 | } else { | |
1948 | [cell setTitle:@"Disk Using"]; | |
1949 | [cell setValue:SizeString(size)]; | |
1950 | } | |
1951 | } break; | |
1952 | ||
1953 | default: _assert(false); | |
1954 | } break; | |
1955 | ||
1956 | case 1: | |
1957 | _assert(size_t(row) < [fields_ count]); | |
1958 | [cell setTitle:[[fields_ allKeys] objectAtIndex:row]]; | |
1959 | [cell addSubview:[[fields_ allValues] objectAtIndex:row]]; | |
1960 | break; | |
1961 | ||
1962 | default: _assert(false); | |
1963 | } | |
1964 | ||
1965 | return cell; | |
1966 | } | |
1967 | ||
1968 | - (id) initWithView:(UIView *)view database:(Database *)database delegate:(id)delegate { | |
1969 | if ((self = [super initWithFrame:[view bounds]]) != nil) { | |
1970 | database_ = database; | |
1971 | delegate_ = delegate; | |
b4d89997 | 1972 | |
36bb2ca2 JF |
1973 | transition_ = [[UITransitionView alloc] initWithFrame:[self bounds]]; |
1974 | [self addSubview:transition_]; | |
b4d89997 | 1975 | |
36bb2ca2 | 1976 | overlay_ = [[UIView alloc] initWithFrame:[transition_ bounds]]; |
06aa974d | 1977 | |
36bb2ca2 JF |
1978 | CGSize navsize = [UINavigationBar defaultSize]; |
1979 | CGRect navrect = {{0, 0}, navsize}; | |
1980 | CGRect bounds = [overlay_ bounds]; | |
b4d89997 | 1981 | |
36bb2ca2 JF |
1982 | navbar_ = [[UINavigationBar alloc] initWithFrame:navrect]; |
1983 | [navbar_ setBarStyle:1]; | |
1984 | [navbar_ setDelegate:self]; | |
dc5812ec | 1985 | |
36bb2ca2 JF |
1986 | UINavigationItem *navitem = [[[UINavigationItem alloc] initWithTitle:@"Confirm"] autorelease]; |
1987 | [navbar_ pushNavigationItem:navitem]; | |
1988 | [navbar_ showButtonsWithLeftTitle:@"Cancel" rightTitle:@"Confirm"]; | |
dc5812ec | 1989 | |
36bb2ca2 | 1990 | fields_ = [[NSMutableDictionary dictionaryWithCapacity:16] retain]; |
dc5812ec | 1991 | |
36bb2ca2 JF |
1992 | NSMutableArray *installing = [NSMutableArray arrayWithCapacity:16]; |
1993 | NSMutableArray *reinstalling = [NSMutableArray arrayWithCapacity:16]; | |
1994 | NSMutableArray *upgrading = [NSMutableArray arrayWithCapacity:16]; | |
1995 | NSMutableArray *downgrading = [NSMutableArray arrayWithCapacity:16]; | |
1996 | NSMutableArray *removing = [NSMutableArray arrayWithCapacity:16]; | |
dc5812ec | 1997 | |
36bb2ca2 | 1998 | bool remove(false); |
dc5812ec | 1999 | |
36bb2ca2 JF |
2000 | pkgCacheFile &cache([database_ cache]); |
2001 | for (pkgCache::PkgIterator iterator = cache->PkgBegin(); !iterator.end(); ++iterator) { | |
2002 | Package *package([Package packageWithIterator:iterator database:database_]); | |
2003 | NSString *name([package name]); | |
2004 | bool essential((iterator->Flags & pkgCache::Flag::Essential) != 0); | |
2005 | pkgDepCache::StateCache &state(cache[iterator]); | |
dc5812ec | 2006 | |
36bb2ca2 JF |
2007 | if (state.NewInstall()) |
2008 | [installing addObject:name]; | |
2009 | else if (!state.Delete() && (state.iFlags & pkgDepCache::ReInstall) == pkgDepCache::ReInstall) | |
2010 | [reinstalling addObject:name]; | |
2011 | else if (state.Upgrade()) | |
2012 | [upgrading addObject:name]; | |
2013 | else if (state.Downgrade()) | |
2014 | [downgrading addObject:name]; | |
2015 | else if (state.Delete()) { | |
2016 | if (essential) | |
2017 | remove = true; | |
2018 | [removing addObject:name]; | |
2019 | } | |
2020 | } | |
ec97ef06 | 2021 | |
36bb2ca2 JF |
2022 | if (!remove) |
2023 | essential_ = nil; | |
2024 | else { | |
2025 | essential_ = [[UIAlertSheet alloc] | |
2026 | initWithTitle:@"Unable to Comply" | |
2027 | buttons:[NSArray arrayWithObjects:@"Okay", nil] | |
2028 | defaultButtonIndex:0 | |
2029 | delegate:self | |
2030 | context:self | |
2031 | ]; | |
ec97ef06 | 2032 | |
36bb2ca2 JF |
2033 | [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."]; |
2034 | } | |
ec97ef06 | 2035 | |
36bb2ca2 JF |
2036 | AddTextView(fields_, installing, @"Installing"); |
2037 | AddTextView(fields_, reinstalling, @"Reinstalling"); | |
2038 | AddTextView(fields_, upgrading, @"Upgrading"); | |
2039 | AddTextView(fields_, downgrading, @"Downgrading"); | |
2040 | AddTextView(fields_, removing, @"Removing"); | |
dc5812ec | 2041 | |
36bb2ca2 JF |
2042 | table_ = [[UIPreferencesTable alloc] initWithFrame:CGRectMake( |
2043 | 0, navsize.height, bounds.size.width, bounds.size.height - navsize.height | |
2044 | )]; | |
dc5812ec | 2045 | |
36bb2ca2 JF |
2046 | [table_ setReusesTableCells:YES]; |
2047 | [table_ setDataSource:self]; | |
2048 | [table_ reloadData]; | |
dc5812ec | 2049 | |
36bb2ca2 JF |
2050 | [overlay_ addSubview:navbar_]; |
2051 | [overlay_ addSubview:table_]; | |
8da60fb7 | 2052 | |
36bb2ca2 | 2053 | [view addSubview:self]; |
99364ec4 | 2054 | |
36bb2ca2 | 2055 | [transition_ setDelegate:self]; |
8da60fb7 | 2056 | |
36bb2ca2 JF |
2057 | UIView *blank = [[[UIView alloc] initWithFrame:[transition_ bounds]] autorelease]; |
2058 | [transition_ transition:0 toView:blank]; | |
2059 | [transition_ transition:3 toView:overlay_]; | |
2060 | } return self; | |
b4d89997 | 2061 | } |
8da60fb7 | 2062 | |
36bb2ca2 JF |
2063 | @end |
2064 | /* }}} */ | |
8da60fb7 | 2065 | |
36bb2ca2 JF |
2066 | /* Progress Data {{{ */ |
2067 | @interface ProgressData : NSObject { | |
2068 | SEL selector_; | |
2069 | id target_; | |
2070 | id object_; | |
dc5812ec JF |
2071 | } |
2072 | ||
36bb2ca2 | 2073 | - (ProgressData *) initWithSelector:(SEL)selector target:(id)target object:(id)object; |
b4d89997 | 2074 | |
36bb2ca2 JF |
2075 | - (SEL) selector; |
2076 | - (id) target; | |
2077 | - (id) object; | |
2078 | @end | |
b4d89997 | 2079 | |
36bb2ca2 | 2080 | @implementation ProgressData |
b4d89997 | 2081 | |
36bb2ca2 JF |
2082 | - (ProgressData *) initWithSelector:(SEL)selector target:(id)target object:(id)object { |
2083 | if ((self = [super init]) != nil) { | |
2084 | selector_ = selector; | |
2085 | target_ = target; | |
2086 | object_ = object; | |
2087 | } return self; | |
2088 | } | |
b4d89997 | 2089 | |
36bb2ca2 JF |
2090 | - (SEL) selector { |
2091 | return selector_; | |
2092 | } | |
b4d89997 | 2093 | |
36bb2ca2 JF |
2094 | - (id) target { |
2095 | return target_; | |
8da60fb7 JF |
2096 | } |
2097 | ||
36bb2ca2 JF |
2098 | - (id) object { |
2099 | return object_; | |
dc5812ec JF |
2100 | } |
2101 | ||
2367a917 JF |
2102 | @end |
2103 | /* }}} */ | |
36bb2ca2 JF |
2104 | /* Progress View {{{ */ |
2105 | @interface ProgressView : UIView < | |
2106 | ProgressDelegate | |
2107 | > { | |
2108 | UIView *view_; | |
2109 | UIView *background_; | |
2110 | UITransitionView *transition_; | |
2111 | UIView *overlay_; | |
2112 | UINavigationBar *navbar_; | |
2113 | UIProgressBar *progress_; | |
2114 | UITextView *output_; | |
2115 | UITextLabel *status_; | |
2116 | id delegate_; | |
2367a917 JF |
2117 | } |
2118 | ||
36bb2ca2 | 2119 | - (void) transitionViewDidComplete:(UITransitionView*)view fromView:(UIView*)from toView:(UIView*)to; |
2367a917 | 2120 | |
36bb2ca2 JF |
2121 | - (ProgressView *) initWithFrame:(struct CGRect)frame delegate:(id)delegate; |
2122 | - (void) setContentView:(UIView *)view; | |
2123 | - (void) resetView; | |
2367a917 | 2124 | |
36bb2ca2 JF |
2125 | - (void) _retachThread; |
2126 | - (void) _detachNewThreadData:(ProgressData *)data; | |
2127 | - (void) detachNewThreadSelector:(SEL)selector toTarget:(id)target withObject:(id)object title:(NSString *)title; | |
2367a917 JF |
2128 | |
2129 | @end | |
2130 | ||
36bb2ca2 JF |
2131 | @protocol ProgressViewDelegate |
2132 | - (void) progressViewIsComplete:(ProgressView *)sender; | |
2133 | @end | |
2134 | ||
2135 | @implementation ProgressView | |
2367a917 JF |
2136 | |
2137 | - (void) dealloc { | |
36bb2ca2 JF |
2138 | [transition_ setDelegate:nil]; |
2139 | [navbar_ setDelegate:nil]; | |
2140 | ||
2141 | [view_ release]; | |
2142 | if (background_ != nil) | |
2143 | [background_ release]; | |
2144 | [transition_ release]; | |
2145 | [overlay_ release]; | |
2146 | [navbar_ release]; | |
2147 | [progress_ release]; | |
2148 | [output_ release]; | |
2149 | [status_ release]; | |
2367a917 JF |
2150 | [super dealloc]; |
2151 | } | |
2152 | ||
36bb2ca2 JF |
2153 | - (void) transitionViewDidComplete:(UITransitionView*)view fromView:(UIView*)from toView:(UIView*)to { |
2154 | if (bootstrap_ && from == overlay_ && to == view_) | |
2155 | exit(0); | |
2156 | } | |
2367a917 | 2157 | |
36bb2ca2 JF |
2158 | - (ProgressView *) initWithFrame:(struct CGRect)frame delegate:(id)delegate { |
2159 | if ((self = [super initWithFrame:frame]) != nil) { | |
2160 | delegate_ = delegate; | |
ec97ef06 | 2161 | |
36bb2ca2 JF |
2162 | transition_ = [[UITransitionView alloc] initWithFrame:[self bounds]]; |
2163 | [transition_ setDelegate:self]; | |
2367a917 | 2164 | |
36bb2ca2 | 2165 | overlay_ = [[UIView alloc] initWithFrame:[transition_ bounds]]; |
ec97ef06 | 2166 | |
36bb2ca2 JF |
2167 | if (bootstrap_) |
2168 | [overlay_ setBackgroundColor:Black_]; | |
2169 | else { | |
2170 | background_ = [[UIView alloc] initWithFrame:[self bounds]]; | |
2171 | [background_ setBackgroundColor:Black_]; | |
2172 | [self addSubview:background_]; | |
2173 | } | |
ec97ef06 | 2174 | |
36bb2ca2 | 2175 | [self addSubview:transition_]; |
2367a917 | 2176 | |
36bb2ca2 JF |
2177 | CGSize navsize = [UINavigationBar defaultSize]; |
2178 | CGRect navrect = {{0, 0}, navsize}; | |
2367a917 | 2179 | |
36bb2ca2 JF |
2180 | navbar_ = [[UINavigationBar alloc] initWithFrame:navrect]; |
2181 | [overlay_ addSubview:navbar_]; | |
b4d89997 | 2182 | |
36bb2ca2 JF |
2183 | [navbar_ setBarStyle:1]; |
2184 | [navbar_ setDelegate:self]; | |
2367a917 | 2185 | |
36bb2ca2 JF |
2186 | UINavigationItem *navitem = [[[UINavigationItem alloc] initWithTitle:nil] autorelease]; |
2187 | [navbar_ pushNavigationItem:navitem]; | |
c7c6384e | 2188 | |
36bb2ca2 JF |
2189 | CGRect bounds = [overlay_ bounds]; |
2190 | CGSize prgsize = [UIProgressBar defaultSize]; | |
ec97ef06 | 2191 | |
36bb2ca2 JF |
2192 | CGRect prgrect = {{ |
2193 | (bounds.size.width - prgsize.width) / 2, | |
2194 | bounds.size.height - prgsize.height - 20 | |
2195 | }, prgsize}; | |
ec97ef06 | 2196 | |
36bb2ca2 JF |
2197 | progress_ = [[UIProgressBar alloc] initWithFrame:prgrect]; |
2198 | [overlay_ addSubview:progress_]; | |
ec97ef06 | 2199 | |
36bb2ca2 JF |
2200 | status_ = [[UITextLabel alloc] initWithFrame:CGRectMake( |
2201 | 10, | |
2202 | bounds.size.height - prgsize.height - 50, | |
2203 | bounds.size.width - 20, | |
2204 | 24 | |
2205 | )]; | |
ec97ef06 | 2206 | |
36bb2ca2 JF |
2207 | [status_ setColor:White_]; |
2208 | [status_ setBackgroundColor:Clear_]; | |
ec97ef06 | 2209 | |
36bb2ca2 JF |
2210 | [status_ setCentersHorizontally:YES]; |
2211 | //[status_ setFont:font]; | |
ec97ef06 | 2212 | |
36bb2ca2 JF |
2213 | output_ = [[UITextView alloc] initWithFrame:CGRectMake( |
2214 | 10, | |
2215 | navrect.size.height + 20, | |
2216 | bounds.size.width - 20, | |
2217 | bounds.size.height - navsize.height - 62 - navrect.size.height | |
2218 | )]; | |
1d80f6b9 | 2219 | |
36bb2ca2 JF |
2220 | //[output_ setTextFont:@"Courier New"]; |
2221 | [output_ setTextSize:12]; | |
2367a917 | 2222 | |
36bb2ca2 JF |
2223 | [output_ setTextColor:White_]; |
2224 | [output_ setBackgroundColor:Clear_]; | |
2367a917 | 2225 | |
36bb2ca2 JF |
2226 | [output_ setMarginTop:0]; |
2227 | [output_ setAllowsRubberBanding:YES]; | |
b4d89997 | 2228 | |
36bb2ca2 JF |
2229 | [overlay_ addSubview:output_]; |
2230 | [overlay_ addSubview:status_]; | |
2367a917 | 2231 | |
36bb2ca2 JF |
2232 | [progress_ setStyle:0]; |
2233 | } return self; | |
2367a917 JF |
2234 | } |
2235 | ||
36bb2ca2 JF |
2236 | - (void) setContentView:(UIView *)view { |
2237 | view_ = [view retain]; | |
2367a917 JF |
2238 | } |
2239 | ||
36bb2ca2 JF |
2240 | - (void) resetView { |
2241 | [transition_ transition:6 toView:view_]; | |
2367a917 JF |
2242 | } |
2243 | ||
36bb2ca2 JF |
2244 | - (void) alertSheet:(UIAlertSheet *)sheet buttonClicked:(int)button { |
2245 | [sheet dismiss]; | |
2367a917 JF |
2246 | } |
2247 | ||
36bb2ca2 JF |
2248 | - (void) _retachThread { |
2249 | [delegate_ progressViewIsComplete:self]; | |
2250 | [self resetView]; | |
b19871dd JF |
2251 | } |
2252 | ||
36bb2ca2 | 2253 | - (void) _detachNewThreadData:(ProgressData *)data { |
b4d89997 JF |
2254 | NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; |
2255 | ||
36bb2ca2 JF |
2256 | [[data target] performSelector:[data selector] withObject:[data object]]; |
2257 | [data release]; | |
b19871dd | 2258 | |
36bb2ca2 | 2259 | [self performSelectorOnMainThread:@selector(_retachThread) withObject:nil waitUntilDone:YES]; |
b19871dd | 2260 | |
b4d89997 | 2261 | [pool release]; |
b19871dd JF |
2262 | } |
2263 | ||
36bb2ca2 JF |
2264 | - (void) detachNewThreadSelector:(SEL)selector toTarget:(id)target withObject:(id)object title:(NSString *)title { |
2265 | [navbar_ popNavigationItem]; | |
2266 | UINavigationItem *navitem = [[[UINavigationItem alloc] initWithTitle:title] autorelease]; | |
2267 | [navbar_ pushNavigationItem:navitem]; | |
b4d89997 | 2268 | |
36bb2ca2 JF |
2269 | [status_ setText:nil]; |
2270 | [output_ setText:@""]; | |
2271 | [progress_ setProgress:0]; | |
b19871dd | 2272 | |
36bb2ca2 | 2273 | [transition_ transition:6 toView:overlay_]; |
b19871dd | 2274 | |
36bb2ca2 JF |
2275 | [NSThread |
2276 | detachNewThreadSelector:@selector(_detachNewThreadData:) | |
2277 | toTarget:self | |
2278 | withObject:[[ProgressData alloc] | |
2279 | initWithSelector:selector | |
2280 | target:target | |
2281 | object:object | |
2282 | ] | |
2283 | ]; | |
b19871dd JF |
2284 | } |
2285 | ||
36bb2ca2 JF |
2286 | - (void) setProgressError:(NSString *)error { |
2287 | [self | |
2288 | performSelectorOnMainThread:@selector(_setProgressError:) | |
2289 | withObject:error | |
2290 | waitUntilDone:YES | |
2291 | ]; | |
b19871dd JF |
2292 | } |
2293 | ||
36bb2ca2 JF |
2294 | - (void) setProgressTitle:(NSString *)title { |
2295 | [self | |
2296 | performSelectorOnMainThread:@selector(_setProgressTitle:) | |
2297 | withObject:title | |
2298 | waitUntilDone:YES | |
2299 | ]; | |
b19871dd JF |
2300 | } |
2301 | ||
36bb2ca2 JF |
2302 | - (void) setProgressPercent:(float)percent { |
2303 | [self | |
2304 | performSelectorOnMainThread:@selector(_setProgressPercent:) | |
2305 | withObject:[NSNumber numberWithFloat:percent] | |
2306 | waitUntilDone:YES | |
2307 | ]; | |
b19871dd JF |
2308 | } |
2309 | ||
36bb2ca2 JF |
2310 | - (void) addProgressOutput:(NSString *)output { |
2311 | [self | |
2312 | performSelectorOnMainThread:@selector(_addProgressOutput:) | |
2313 | withObject:output | |
2314 | waitUntilDone:YES | |
2315 | ]; | |
b19871dd JF |
2316 | } |
2317 | ||
36bb2ca2 JF |
2318 | - (void) _setProgressError:(NSString *)error { |
2319 | UIAlertSheet *sheet = [[[UIAlertSheet alloc] | |
2320 | initWithTitle:@"Package Error" | |
2321 | buttons:[NSArray arrayWithObjects:@"Okay", nil] | |
2322 | defaultButtonIndex:0 | |
2323 | delegate:self | |
2324 | context:self | |
2325 | ] autorelease]; | |
2326 | ||
2327 | [sheet setBodyText:error]; | |
2328 | [sheet popupAlertAnimated:YES]; | |
b19871dd JF |
2329 | } |
2330 | ||
36bb2ca2 JF |
2331 | - (void) _setProgressTitle:(NSString *)title { |
2332 | [status_ setText:[title stringByAppendingString:@"..."]]; | |
b4d89997 | 2333 | } |
b19871dd | 2334 | |
36bb2ca2 JF |
2335 | - (void) _setProgressPercent:(NSNumber *)percent { |
2336 | [progress_ setProgress:[percent floatValue]]; | |
49048579 JF |
2337 | } |
2338 | ||
36bb2ca2 JF |
2339 | - (void) _addProgressOutput:(NSString *)output { |
2340 | [output_ setText:[NSString stringWithFormat:@"%@\n%@", [output_ text], output]]; | |
2341 | CGSize size = [output_ contentSize]; | |
2342 | CGRect rect = {{0, size.height}, {size.width, 0}}; | |
2343 | [output_ scrollRectToVisible:rect animated:YES]; | |
2344 | } | |
dc088e63 | 2345 | |
36bb2ca2 JF |
2346 | @end |
2347 | /* }}} */ | |
dc088e63 | 2348 | |
36bb2ca2 JF |
2349 | /* Package Cell {{{ */ |
2350 | @interface PackageCell : UITableCell { | |
2351 | UIImageView *icon_; | |
2352 | UITextLabel *name_; | |
2353 | UITextLabel *description_; | |
2354 | UITextLabel *source_; | |
2355 | UIImageView *trusted_; | |
2356 | } | |
723a0072 | 2357 | |
36bb2ca2 JF |
2358 | - (PackageCell *) init; |
2359 | - (void) setPackage:(Package *)package; | |
ec97ef06 | 2360 | |
36bb2ca2 JF |
2361 | - (void) _setSelected:(float)fraction; |
2362 | - (void) setSelected:(BOOL)selected; | |
2363 | - (void) setSelected:(BOOL)selected withFade:(BOOL)fade; | |
2364 | - (void) _setSelectionFadeFraction:(float)fraction; | |
ec97ef06 | 2365 | |
36bb2ca2 | 2366 | @end |
49048579 | 2367 | |
36bb2ca2 JF |
2368 | @implementation PackageCell |
2369 | ||
2370 | - (void) dealloc { | |
2371 | [icon_ release]; | |
2372 | [name_ release]; | |
2373 | [description_ release]; | |
2374 | [source_ release]; | |
2375 | [trusted_ release]; | |
2376 | [super dealloc]; | |
b4d89997 | 2377 | } |
b19871dd | 2378 | |
36bb2ca2 JF |
2379 | - (PackageCell *) init { |
2380 | if ((self = [super init]) != nil) { | |
2381 | GSFontRef bold = GSFontCreateWithName("Helvetica", kGSFontTraitBold, 20); | |
2382 | GSFontRef large = GSFontCreateWithName("Helvetica", kGSFontTraitNone, 12); | |
2383 | GSFontRef small = GSFontCreateWithName("Helvetica", kGSFontTraitNone, 14); | |
b19871dd | 2384 | |
36bb2ca2 | 2385 | icon_ = [[UIImageView alloc] initWithFrame:CGRectMake(10, 10, 30, 30)]; |
b19871dd | 2386 | |
36bb2ca2 JF |
2387 | name_ = [[UITextLabel alloc] initWithFrame:CGRectMake(48, 8, 240, 25)]; |
2388 | [name_ setBackgroundColor:Clear_]; | |
2389 | [name_ setFont:bold]; | |
b19871dd | 2390 | |
36bb2ca2 JF |
2391 | source_ = [[UITextLabel alloc] initWithFrame:CGRectMake(58, 28, 225, 20)]; |
2392 | [source_ setBackgroundColor:Clear_]; | |
2393 | [source_ setFont:large]; | |
b19871dd | 2394 | |
36bb2ca2 JF |
2395 | description_ = [[UITextLabel alloc] initWithFrame:CGRectMake(12, 46, 280, 20)]; |
2396 | [description_ setBackgroundColor:Clear_]; | |
2397 | [description_ setFont:small]; | |
b19871dd | 2398 | |
36bb2ca2 JF |
2399 | trusted_ = [[UIImageView alloc] initWithFrame:CGRectMake(30, 30, 16, 16)]; |
2400 | [trusted_ setImage:[UIImage applicationImageNamed:@"trusted.png"]]; | |
b19871dd | 2401 | |
36bb2ca2 JF |
2402 | [self addSubview:icon_]; |
2403 | [self addSubview:name_]; | |
2404 | [self addSubview:description_]; | |
2405 | [self addSubview:source_]; | |
2406 | ||
2407 | CFRelease(small); | |
2408 | CFRelease(large); | |
2409 | CFRelease(bold); | |
2410 | } return self; | |
b4d89997 | 2411 | } |
b19871dd | 2412 | |
36bb2ca2 JF |
2413 | - (void) setPackage:(Package *)package { |
2414 | Source *source = [package source]; | |
b19871dd | 2415 | |
36bb2ca2 JF |
2416 | UIImage *image = nil; |
2417 | if (NSString *icon = [package icon]) | |
2418 | image = [UIImage imageAtPath:[icon substringFromIndex:6]]; | |
2419 | if (image == nil) if (NSString *icon = [source defaultIcon]) | |
2420 | image = [UIImage imageAtPath:[icon substringFromIndex:6]]; | |
2421 | if (image == nil) | |
2422 | image = [UIImage applicationImageNamed:@"unknown.png"]; | |
36bb2ca2 | 2423 | [icon_ setImage:image]; |
a0be02eb JF |
2424 | |
2425 | if (image != nil) { | |
2426 | CGSize size = [image size]; | |
2427 | float scale = 30 / std::max(size.width, size.height); | |
2428 | [icon_ zoomToScale:scale]; | |
2429 | } | |
2430 | ||
36bb2ca2 | 2431 | [icon_ setFrame:CGRectMake(10, 10, 30, 30)]; |
b19871dd | 2432 | |
36bb2ca2 JF |
2433 | [name_ setText:[package name]]; |
2434 | [description_ setText:[package tagline]]; | |
2435 | ||
2436 | NSString *label; | |
2437 | bool trusted; | |
b19871dd | 2438 | |
36bb2ca2 JF |
2439 | if (source != nil) { |
2440 | label = [source label]; | |
2441 | trusted = [source trusted]; | |
2442 | } else if ([[package id] isEqualToString:@"firmware"]) { | |
2443 | label = @"Apple"; | |
2444 | trusted = false; | |
2445 | } else { | |
2446 | label = @"Unknown/Local"; | |
2447 | trusted = false; | |
b4d89997 | 2448 | } |
b19871dd | 2449 | |
4cf4165e | 2450 | [source_ setText:[NSString stringWithFormat:@"from %@ (%@)", label, Simplify([package section])]]; |
36bb2ca2 JF |
2451 | |
2452 | if (trusted) | |
2453 | [self addSubview:trusted_]; | |
2454 | else | |
2455 | [trusted_ removeFromSuperview]; | |
b19871dd JF |
2456 | } |
2457 | ||
36bb2ca2 JF |
2458 | - (void) _setSelected:(float)fraction { |
2459 | CGColor black(space_, | |
2460 | Interpolate(0.0, 1.0, fraction), | |
2461 | Interpolate(0.0, 1.0, fraction), | |
2462 | Interpolate(0.0, 1.0, fraction), | |
2463 | 1.0); | |
b19871dd | 2464 | |
36bb2ca2 JF |
2465 | CGColor gray(space_, |
2466 | Interpolate(0.4, 1.0, fraction), | |
2467 | Interpolate(0.4, 1.0, fraction), | |
2468 | Interpolate(0.4, 1.0, fraction), | |
2469 | 1.0); | |
b19871dd | 2470 | |
36bb2ca2 JF |
2471 | [name_ setColor:black]; |
2472 | [description_ setColor:gray]; | |
2473 | [source_ setColor:black]; | |
b19871dd JF |
2474 | } |
2475 | ||
36bb2ca2 JF |
2476 | - (void) setSelected:(BOOL)selected { |
2477 | [self _setSelected:(selected ? 1.0 : 0.0)]; | |
2478 | [super setSelected:selected]; | |
b19871dd JF |
2479 | } |
2480 | ||
36bb2ca2 JF |
2481 | - (void) setSelected:(BOOL)selected withFade:(BOOL)fade { |
2482 | if (!fade) | |
2483 | [self _setSelected:(selected ? 1.0 : 0.0)]; | |
2484 | [super setSelected:selected withFade:fade]; | |
2485 | } | |
2486 | ||
2487 | - (void) _setSelectionFadeFraction:(float)fraction { | |
2488 | [self _setSelected:fraction]; | |
2489 | [super _setSelectionFadeFraction:fraction]; | |
ec97ef06 JF |
2490 | } |
2491 | ||
8da60fb7 JF |
2492 | @end |
2493 | /* }}} */ | |
36bb2ca2 JF |
2494 | /* Section Cell {{{ */ |
2495 | @interface SectionCell : UITableCell { | |
2496 | UITextLabel *name_; | |
2497 | UITextLabel *count_; | |
b4d89997 | 2498 | } |
b19871dd | 2499 | |
36bb2ca2 JF |
2500 | - (id) init; |
2501 | - (void) setSection:(Section *)section; | |
2502 | ||
2503 | - (void) _setSelected:(float)fraction; | |
2504 | - (void) setSelected:(BOOL)selected; | |
2505 | - (void) setSelected:(BOOL)selected withFade:(BOOL)fade; | |
2506 | - (void) _setSelectionFadeFraction:(float)fraction; | |
b19871dd | 2507 | |
8da60fb7 JF |
2508 | @end |
2509 | ||
36bb2ca2 | 2510 | @implementation SectionCell |
8da60fb7 | 2511 | |
36bb2ca2 JF |
2512 | - (void) dealloc { |
2513 | [name_ release]; | |
2514 | [count_ release]; | |
2515 | [super dealloc]; | |
2516 | } | |
2517 | ||
2518 | - (id) init { | |
b4d89997 | 2519 | if ((self = [super init]) != nil) { |
36bb2ca2 JF |
2520 | GSFontRef bold = GSFontCreateWithName("Helvetica", kGSFontTraitBold, 22); |
2521 | GSFontRef small = GSFontCreateWithName("Helvetica", kGSFontTraitBold, 12); | |
2522 | ||
2523 | name_ = [[UITextLabel alloc] initWithFrame:CGRectMake(48, 9, 250, 25)]; | |
2524 | [name_ setBackgroundColor:Clear_]; | |
2525 | [name_ setFont:bold]; | |
2526 | ||
2527 | count_ = [[UITextLabel alloc] initWithFrame:CGRectMake(11, 7, 29, 32)]; | |
2528 | [count_ setCentersHorizontally:YES]; | |
2529 | [count_ setBackgroundColor:Clear_]; | |
2530 | [count_ setFont:small]; | |
2531 | [count_ setColor:White_]; | |
2532 | ||
2533 | UIImageView *folder = [[[UIImageView alloc] initWithFrame:CGRectMake(8, 7, 32, 32)] autorelease]; | |
2534 | [folder setImage:[UIImage applicationImageNamed:@"folder.png"]]; | |
2535 | ||
2536 | [self addSubview:folder]; | |
2537 | [self addSubview:name_]; | |
2538 | [self addSubview:count_]; | |
2539 | ||
2540 | [self _setSelected:0]; | |
2541 | ||
2542 | CFRelease(small); | |
2543 | CFRelease(bold); | |
b4d89997 | 2544 | } return self; |
b19871dd JF |
2545 | } |
2546 | ||
36bb2ca2 JF |
2547 | - (void) setSection:(Section *)section { |
2548 | if (section == nil) { | |
2549 | [name_ setText:@"All Packages"]; | |
2550 | [count_ setText:nil]; | |
2551 | } else { | |
2552 | NSString *name = [section name]; | |
2553 | [name_ setText:(name == nil ? @"(No Section)" : name)]; | |
2554 | [count_ setText:[NSString stringWithFormat:@"%d", [section count]]]; | |
2555 | } | |
b19871dd JF |
2556 | } |
2557 | ||
36bb2ca2 JF |
2558 | - (void) _setSelected:(float)fraction { |
2559 | CGColor black(space_, | |
2560 | Interpolate(0.0, 1.0, fraction), | |
2561 | Interpolate(0.0, 1.0, fraction), | |
2562 | Interpolate(0.0, 1.0, fraction), | |
2563 | 1.0); | |
b19871dd | 2564 | |
36bb2ca2 | 2565 | [name_ setColor:black]; |
b19871dd JF |
2566 | } |
2567 | ||
36bb2ca2 JF |
2568 | - (void) setSelected:(BOOL)selected { |
2569 | [self _setSelected:(selected ? 1.0 : 0.0)]; | |
2570 | [super setSelected:selected]; | |
b19871dd JF |
2571 | } |
2572 | ||
36bb2ca2 JF |
2573 | - (void) setSelected:(BOOL)selected withFade:(BOOL)fade { |
2574 | if (!fade) | |
2575 | [self _setSelected:(selected ? 1.0 : 0.0)]; | |
2576 | [super setSelected:selected withFade:fade]; | |
2577 | } | |
b19871dd | 2578 | |
36bb2ca2 JF |
2579 | - (void) _setSelectionFadeFraction:(float)fraction { |
2580 | [self _setSelected:fraction]; | |
2581 | [super _setSelectionFadeFraction:fraction]; | |
2582 | } | |
b31b87cc | 2583 | |
36bb2ca2 JF |
2584 | @end |
2585 | /* }}} */ | |
b19871dd | 2586 | |
36bb2ca2 JF |
2587 | /* Browser Interface {{{ */ |
2588 | @interface BrowserView : RVPage { | |
2589 | _transient Database *database_; | |
2590 | UIScroller *scroller_; | |
2591 | UIWebView *webview_; | |
2592 | NSMutableArray *urls_; | |
2593 | UIProgressIndicator *indicator_; | |
b19871dd | 2594 | |
36bb2ca2 JF |
2595 | NSString *title_; |
2596 | bool loading_; | |
2597 | } | |
b19871dd | 2598 | |
36bb2ca2 JF |
2599 | - (void) loadURL:(NSURL *)url cachePolicy:(NSURLRequestCachePolicy)policy; |
2600 | - (void) loadURL:(NSURL *)url; | |
b19871dd | 2601 | |
36bb2ca2 JF |
2602 | - (void) loadRequest:(NSURLRequest *)request; |
2603 | - (void) reloadURL; | |
b19871dd | 2604 | |
36bb2ca2 | 2605 | - (WebView *) webView; |
8da60fb7 | 2606 | |
36bb2ca2 | 2607 | - (id) initWithBook:(RVBook *)book database:(Database *)database; |
b4d89997 | 2608 | |
b4d89997 | 2609 | @end |
36bb2ca2 | 2610 | /* }}} */ |
b4d89997 | 2611 | |
36bb2ca2 JF |
2612 | /* Package View {{{ */ |
2613 | @protocol PackageViewDelegate | |
2614 | - (void) performPackage:(Package *)package; | |
2615 | @end | |
8da60fb7 | 2616 | |
36bb2ca2 JF |
2617 | @interface PackageView : RVPage { |
2618 | _transient Database *database_; | |
2619 | UIPreferencesTable *table_; | |
2620 | Package *package_; | |
2621 | NSString *name_; | |
2622 | UITextView *description_; | |
b31b87cc JF |
2623 | } |
2624 | ||
36bb2ca2 JF |
2625 | - (id) initWithBook:(RVBook *)book database:(Database *)database; |
2626 | - (void) setPackage:(Package *)package; | |
b4d89997 | 2627 | |
36bb2ca2 | 2628 | @end |
b4d89997 | 2629 | |
36bb2ca2 | 2630 | @implementation PackageView |
b4d89997 | 2631 | |
36bb2ca2 JF |
2632 | - (void) dealloc { |
2633 | [table_ setDataSource:nil]; | |
2634 | [table_ setDelegate:nil]; | |
b4d89997 | 2635 | |
36bb2ca2 JF |
2636 | if (package_ != nil) |
2637 | [package_ release]; | |
2638 | if (name_ != nil) | |
2639 | [name_ release]; | |
2640 | if (description_ != nil) | |
2641 | [description_ release]; | |
2642 | [table_ release]; | |
2643 | [super dealloc]; | |
2644 | } | |
8da60fb7 | 2645 | |
36bb2ca2 JF |
2646 | - (int) numberOfGroupsInPreferencesTable:(UIPreferencesTable *)table { |
2647 | return [package_ source] == nil ? 2 : 3; | |
2648 | } | |
b31b87cc | 2649 | |
36bb2ca2 JF |
2650 | - (NSString *) preferencesTable:(UIPreferencesTable *)table titleForGroup:(int)group { |
2651 | switch (group) { | |
2652 | case 0: return nil; | |
2653 | case 1: return @"Package Details"; | |
2654 | case 2: return @"Source Information"; | |
b31b87cc | 2655 | |
36bb2ca2 JF |
2656 | default: _assert(false); |
2657 | } | |
2658 | } | |
8da60fb7 | 2659 | |
36bb2ca2 JF |
2660 | - (float) preferencesTable:(UIPreferencesTable *)table heightForRow:(int)row inGroup:(int)group withProposedHeight:(float)proposed { |
2661 | if (group != 0 || row != 1) | |
2662 | return proposed; | |
2663 | else | |
2664 | return [description_ visibleTextRect].size.height + TextViewOffset_; | |
2665 | } | |
8da60fb7 | 2666 | |
36bb2ca2 JF |
2667 | - (int) preferencesTable:(UIPreferencesTable *)table numberOfRowsInGroup:(int)group { |
2668 | switch (group) { | |
2669 | case 0: return [package_ website] == nil ? 2 : 3; | |
2670 | case 1: return 5; | |
2671 | case 2: return 3; | |
8da60fb7 | 2672 | |
36bb2ca2 JF |
2673 | default: _assert(false); |
2674 | } | |
2675 | } | |
8da60fb7 | 2676 | |
36bb2ca2 JF |
2677 | - (UIPreferencesTableCell *) preferencesTable:(UIPreferencesTable *)table cellForRow:(int)row inGroup:(int)group { |
2678 | UIPreferencesTableCell *cell = [[[UIPreferencesTableCell alloc] init] autorelease]; | |
2679 | [cell setShowSelection:NO]; | |
b4d89997 | 2680 | |
36bb2ca2 JF |
2681 | switch (group) { |
2682 | case 0: switch (row) { | |
2683 | case 0: | |
2684 | [cell setTitle:[package_ name]]; | |
2685 | [cell setValue:[package_ latest]]; | |
2686 | break; | |
b4d89997 | 2687 | |
36bb2ca2 JF |
2688 | case 1: |
2689 | [cell addSubview:description_]; | |
2690 | break; | |
b4d89997 | 2691 | |
36bb2ca2 JF |
2692 | case 2: |
2693 | [cell setTitle:@"More Information"]; | |
2694 | [cell setShowDisclosure:YES]; | |
2695 | [cell setShowSelection:YES]; | |
2696 | break; | |
8da60fb7 | 2697 | |
36bb2ca2 JF |
2698 | default: _assert(false); |
2699 | } break; | |
b19871dd | 2700 | |
36bb2ca2 JF |
2701 | case 1: switch (row) { |
2702 | case 0: | |
2703 | [cell setTitle:@"Identifier"]; | |
2704 | [cell setValue:[package_ id]]; | |
2705 | break; | |
b19871dd | 2706 | |
36bb2ca2 JF |
2707 | case 1: { |
2708 | [cell setTitle:@"Installed Version"]; | |
2709 | NSString *installed([package_ installed]); | |
2710 | [cell setValue:(installed == nil ? @"n/a" : installed)]; | |
2711 | } break; | |
b19871dd | 2712 | |
36bb2ca2 JF |
2713 | case 2: { |
2714 | [cell setTitle:@"Section"]; | |
2715 | NSString *section([package_ section]); | |
2716 | [cell setValue:(section == nil ? @"n/a" : section)]; | |
2717 | } break; | |
8da60fb7 | 2718 | |
36bb2ca2 JF |
2719 | case 3: |
2720 | [cell setTitle:@"Expanded Size"]; | |
2721 | [cell setValue:SizeString([package_ size])]; | |
2722 | break; | |
8da60fb7 | 2723 | |
36bb2ca2 JF |
2724 | case 4: |
2725 | [cell setTitle:@"Maintainer"]; | |
2726 | [cell setValue:[[package_ maintainer] name]]; | |
2727 | [cell setShowDisclosure:YES]; | |
2728 | [cell setShowSelection:YES]; | |
2729 | break; | |
8da60fb7 | 2730 | |
36bb2ca2 JF |
2731 | default: _assert(false); |
2732 | } break; | |
3178d79b | 2733 | |
36bb2ca2 JF |
2734 | case 2: switch (row) { |
2735 | case 0: | |
2736 | [cell setTitle:[[package_ source] label]]; | |
2737 | [cell setValue:[[package_ source] version]]; | |
2738 | break; | |
3178d79b | 2739 | |
36bb2ca2 JF |
2740 | case 1: |
2741 | [cell setValue:[[package_ source] description]]; | |
2742 | break; | |
3178d79b | 2743 | |
36bb2ca2 JF |
2744 | case 2: |
2745 | [cell setTitle:@"Origin"]; | |
2746 | [cell setValue:[[package_ source] origin]]; | |
2747 | break; | |
3178d79b | 2748 | |
36bb2ca2 JF |
2749 | default: _assert(false); |
2750 | } break; | |
8da60fb7 | 2751 | |
36bb2ca2 JF |
2752 | default: _assert(false); |
2753 | } | |
dc5812ec | 2754 | |
36bb2ca2 | 2755 | return cell; |
b4d89997 | 2756 | } |
dc5812ec | 2757 | |
36bb2ca2 JF |
2758 | - (BOOL) canSelectRow:(int)row { |
2759 | return YES; | |
2367a917 JF |
2760 | } |
2761 | ||
36bb2ca2 JF |
2762 | - (void) tableRowSelected:(NSNotification *)notification { |
2763 | int row = [table_ selectedRow]; | |
2764 | NSString *website = [package_ website]; | |
2367a917 | 2765 | |
36bb2ca2 JF |
2766 | if (row == (website == nil ? 8 : 9)) |
2767 | [delegate_ openURL:[NSURL URLWithString:[NSString stringWithFormat:@"mailto:%@?subject=%@", | |
2768 | [[package_ maintainer] email], | |
2769 | [[NSString stringWithFormat:@"regarding apt package \"%@\"", [package_ name]] stringByAddingPercentEscapes] | |
2770 | ]]]; | |
2771 | else if (website != nil && row == 3) { | |
2772 | NSURL *url = [NSURL URLWithString:website]; | |
2773 | BrowserView *browser = [[[BrowserView alloc] initWithBook:book_ database:database_] autorelease]; | |
2774 | [browser setDelegate:delegate_]; | |
2775 | [book_ pushPage:browser]; | |
2776 | [browser loadURL:url]; | |
2777 | } | |
3178d79b JF |
2778 | } |
2779 | ||
36bb2ca2 JF |
2780 | - (void) alertSheet:(UIAlertSheet *)sheet buttonClicked:(int)button { |
2781 | switch (button) { | |
2782 | case 1: [delegate_ installPackage:package_]; break; | |
2783 | case 2: [delegate_ removePackage:package_]; break; | |
2784 | } | |
2785 | ||
2786 | [sheet dismiss]; | |
b4d89997 | 2787 | } |
2367a917 | 2788 | |
36bb2ca2 JF |
2789 | - (void) _rightButtonClicked { |
2790 | if ([package_ installed] == nil) | |
2791 | [delegate_ installPackage:package_]; | |
2792 | else { | |
2793 | NSMutableArray *buttons = [NSMutableArray arrayWithCapacity:6]; | |
2367a917 | 2794 | |
36bb2ca2 JF |
2795 | if ([package_ upgradable]) |
2796 | [buttons addObject:@"Upgrade"]; | |
2797 | else | |
2798 | [buttons addObject:@"Reinstall"]; | |
2799 | ||
2800 | [buttons addObject:@"Remove"]; | |
2801 | [buttons addObject:@"Cancel"]; | |
2802 | ||
2803 | [delegate_ slideUp:[[[UIAlertSheet alloc] | |
2804 | initWithTitle:@"Manage Package" | |
2805 | buttons:buttons | |
2806 | defaultButtonIndex:2 | |
2807 | delegate:self | |
2808 | context:self | |
2809 | ] autorelease]]; | |
2810 | } | |
b4d89997 | 2811 | } |
2367a917 | 2812 | |
36bb2ca2 JF |
2813 | - (NSString *) rightButtonTitle { |
2814 | _assert(package_ != nil); | |
559dec34 | 2815 | return [package_ installed] == nil ? @"Install" : @"Modify"; |
b4d89997 | 2816 | } |
2367a917 | 2817 | |
36bb2ca2 JF |
2818 | - (NSString *) title { |
2819 | return @"Details"; | |
dc5812ec JF |
2820 | } |
2821 | ||
36bb2ca2 JF |
2822 | - (id) initWithBook:(RVBook *)book database:(Database *)database { |
2823 | if ((self = [super initWithBook:book]) != nil) { | |
2824 | database_ = database; | |
2825 | ||
2826 | table_ = [[UIPreferencesTable alloc] initWithFrame:[self bounds]]; | |
2827 | [self addSubview:table_]; | |
2828 | ||
2829 | [table_ setDataSource:self]; | |
2830 | [table_ setDelegate:self]; | |
2831 | } return self; | |
dc5812ec JF |
2832 | } |
2833 | ||
36bb2ca2 JF |
2834 | - (void) setPackage:(Package *)package { |
2835 | if (package_ != nil) { | |
2836 | [package_ autorelease]; | |
2837 | package_ = nil; | |
2838 | } | |
2839 | ||
2840 | if (name_ != nil) { | |
2841 | [name_ release]; | |
2842 | name_ = nil; | |
2843 | } | |
2844 | ||
2845 | if (description_ != nil) { | |
2846 | [description_ release]; | |
2847 | description_ = nil; | |
2848 | } | |
2849 | ||
2850 | if (package != nil) { | |
2851 | package_ = [package retain]; | |
2852 | name_ = [[package id] retain]; | |
2853 | ||
2854 | NSString *description([package description]); | |
2855 | if (description == nil) | |
2856 | description = [package tagline]; | |
2857 | description_ = [GetTextView(description, 12, true) retain]; | |
2858 | ||
2859 | [description_ setTextColor:Black_]; | |
2860 | ||
2861 | [table_ reloadData]; | |
2862 | } | |
dc5812ec JF |
2863 | } |
2864 | ||
36bb2ca2 JF |
2865 | - (void) resetViewAnimated:(BOOL)animated { |
2866 | [table_ resetViewAnimated:animated]; | |
dc5812ec JF |
2867 | } |
2868 | ||
36bb2ca2 JF |
2869 | - (void) reloadData { |
2870 | [self setPackage:[database_ packageWithName:name_]]; | |
2871 | [self reloadButtons]; | |
8fe19fc1 JF |
2872 | } |
2873 | ||
b4d89997 JF |
2874 | @end |
2875 | /* }}} */ | |
b4d89997 | 2876 | /* Package Table {{{ */ |
36bb2ca2 JF |
2877 | @interface PackageTable : RVPage { |
2878 | _transient Database *database_; | |
2879 | NSString *title_; | |
2880 | SEL filter_; | |
2881 | id object_; | |
2882 | NSMutableArray *packages_; | |
b4d89997 | 2883 | NSMutableArray *sections_; |
36bb2ca2 | 2884 | UISectionList *list_; |
dc5812ec JF |
2885 | } |
2886 | ||
36bb2ca2 | 2887 | - (id) initWithBook:(RVBook *)book database:(Database *)database title:(NSString *)title filter:(SEL)filter with:(id)object; |
b4d89997 JF |
2888 | |
2889 | - (void) setDelegate:(id)delegate; | |
a0be02eb JF |
2890 | - (void) setObject:(id)object; |
2891 | ||
36bb2ca2 | 2892 | - (void) reloadData; |
a0be02eb | 2893 | - (void) resetCursor; |
b4d89997 | 2894 | |
b4d89997 JF |
2895 | @end |
2896 | ||
2897 | @implementation PackageTable | |
2898 | ||
2899 | - (void) dealloc { | |
36bb2ca2 JF |
2900 | [list_ setDataSource:nil]; |
2901 | ||
2902 | [title_ release]; | |
2903 | if (object_ != nil) | |
2904 | [object_ release]; | |
2905 | [packages_ release]; | |
b4d89997 | 2906 | [sections_ release]; |
36bb2ca2 | 2907 | [list_ release]; |
b4d89997 | 2908 | [super dealloc]; |
8fe19fc1 JF |
2909 | } |
2910 | ||
b4d89997 JF |
2911 | - (int) numberOfSectionsInSectionList:(UISectionList *)list { |
2912 | return [sections_ count]; | |
2913 | } | |
2367a917 | 2914 | |
b4d89997 JF |
2915 | - (NSString *) sectionList:(UISectionList *)list titleForSection:(int)section { |
2916 | return [[sections_ objectAtIndex:section] name]; | |
2917 | } | |
dc5812ec | 2918 | |
b4d89997 JF |
2919 | - (int) sectionList:(UISectionList *)list rowForSection:(int)section { |
2920 | return [[sections_ objectAtIndex:section] row]; | |
2367a917 JF |
2921 | } |
2922 | ||
b4d89997 JF |
2923 | - (int) numberOfRowsInTable:(UITable *)table { |
2924 | return [packages_ count]; | |
2925 | } | |
dc5812ec | 2926 | |
b4d89997 | 2927 | - (float) table:(UITable *)table heightForRow:(int)row { |
36bb2ca2 | 2928 | return 73; |
b4d89997 | 2929 | } |
dc5812ec | 2930 | |
b4d89997 JF |
2931 | - (UITableCell *) table:(UITable *)table cellForRow:(int)row column:(UITableColumn *)col reusing:(UITableCell *)reusing { |
2932 | if (reusing == nil) | |
36bb2ca2 | 2933 | reusing = [[[PackageCell alloc] init] autorelease]; |
b4d89997 JF |
2934 | [(PackageCell *)reusing setPackage:[packages_ objectAtIndex:row]]; |
2935 | return reusing; | |
2936 | } | |
dc5812ec | 2937 | |
b4d89997 JF |
2938 | - (BOOL) table:(UITable *)table showDisclosureForRow:(int)row { |
2939 | return NO; | |
2940 | } | |
dc5812ec | 2941 | |
b4d89997 JF |
2942 | - (void) tableRowSelected:(NSNotification *)notification { |
2943 | int row = [[notification object] selectedRow]; | |
36bb2ca2 JF |
2944 | if (row == INT_MAX) |
2945 | return; | |
2946 | ||
2947 | Package *package = [packages_ objectAtIndex:row]; | |
2948 | PackageView *view = [[[PackageView alloc] initWithBook:book_ database:database_] autorelease]; | |
2949 | [view setDelegate:delegate_]; | |
2950 | [view setPackage:package]; | |
2951 | [book_ pushPage:view]; | |
dc5812ec JF |
2952 | } |
2953 | ||
36bb2ca2 JF |
2954 | - (id) initWithBook:(RVBook *)book database:(Database *)database title:(NSString *)title filter:(SEL)filter with:(id)object { |
2955 | if ((self = [super initWithBook:book]) != nil) { | |
2956 | database_ = database; | |
2957 | title_ = [title retain]; | |
2958 | filter_ = filter; | |
2959 | object_ = object == nil ? nil : [object retain]; | |
2960 | ||
2961 | packages_ = [[NSMutableArray arrayWithCapacity:16] retain]; | |
b4d89997 | 2962 | sections_ = [[NSMutableArray arrayWithCapacity:16] retain]; |
dc5812ec | 2963 | |
b4d89997 JF |
2964 | list_ = [[UISectionList alloc] initWithFrame:[self bounds] showSectionIndex:YES]; |
2965 | [list_ setDataSource:self]; | |
dc5812ec | 2966 | |
b4d89997 JF |
2967 | UITableColumn *column = [[[UITableColumn alloc] |
2968 | initWithTitle:@"Name" | |
2969 | identifier:@"name" | |
36bb2ca2 | 2970 | width:[self frame].size.width |
b4d89997 JF |
2971 | ] autorelease]; |
2972 | ||
2973 | UITable *table = [list_ table]; | |
2974 | [table setSeparatorStyle:1]; | |
2975 | [table addTableColumn:column]; | |
2976 | [table setDelegate:self]; | |
2977 | [table setReusesTableCells:YES]; | |
2978 | ||
2979 | [self addSubview:list_]; | |
36bb2ca2 | 2980 | [self reloadData]; |
b4d89997 | 2981 | } return self; |
dc5812ec JF |
2982 | } |
2983 | ||
2984 | - (void) setDelegate:(id)delegate { | |
2367a917 | 2985 | delegate_ = delegate; |
b4d89997 JF |
2986 | } |
2987 | ||
a0be02eb JF |
2988 | - (void) setObject:(id)object { |
2989 | if (object_ != nil) | |
2990 | [object_ release]; | |
2991 | if (object == nil) | |
2992 | object_ = nil; | |
2993 | else | |
2994 | object_ = [object retain]; | |
2995 | } | |
2996 | ||
36bb2ca2 JF |
2997 | - (void) reloadData { |
2998 | NSArray *packages = [database_ packages]; | |
b4d89997 | 2999 | |
36bb2ca2 | 3000 | [packages_ removeAllObjects]; |
b4d89997 JF |
3001 | [sections_ removeAllObjects]; |
3002 | ||
36bb2ca2 JF |
3003 | for (size_t i(0); i != [packages count]; ++i) { |
3004 | Package *package([packages objectAtIndex:i]); | |
3005 | if ([[package performSelector:filter_ withObject:object_] boolValue]) | |
3006 | [packages_ addObject:package]; | |
3007 | } | |
3008 | ||
3009 | [packages_ sortUsingSelector:@selector(compareByName:)]; | |
3010 | ||
b4d89997 JF |
3011 | Section *section = nil; |
3012 | ||
3013 | for (size_t offset(0); offset != [packages_ count]; ++offset) { | |
3014 | Package *package = [packages_ objectAtIndex:offset]; | |
3015 | NSString *name = [package index]; | |
3016 | ||
36bb2ca2 | 3017 | if (section == nil || ![[section name] isEqualToString:name]) { |
b4d89997 JF |
3018 | section = [[[Section alloc] initWithName:name row:offset] autorelease]; |
3019 | [sections_ addObject:section]; | |
3020 | } | |
3021 | ||
36bb2ca2 | 3022 | [section addToCount]; |
b4d89997 JF |
3023 | } |
3024 | ||
3025 | [list_ reloadData]; | |
3026 | } | |
3027 | ||
36bb2ca2 JF |
3028 | - (NSString *) title { |
3029 | return title_; | |
b4d89997 JF |
3030 | } |
3031 | ||
36bb2ca2 JF |
3032 | - (void) resetViewAnimated:(BOOL)animated { |
3033 | [list_ resetViewAnimated:animated]; | |
dc5812ec JF |
3034 | } |
3035 | ||
a0be02eb JF |
3036 | - (void) resetCursor { |
3037 | [[list_ table] scrollPointVisibleAtTopLeft:CGPointMake(0, 0) animated:NO]; | |
3038 | } | |
3039 | ||
dc5812ec | 3040 | @end |
b4d89997 | 3041 | /* }}} */ |
dc5812ec | 3042 | |
36bb2ca2 JF |
3043 | /* Browser Implementation {{{ */ |
3044 | @implementation BrowserView | |
3045 | ||
3046 | - (void) dealloc { | |
3047 | WebView *webview = [webview_ webView]; | |
3048 | [webview setFrameLoadDelegate:nil]; | |
3049 | [webview setResourceLoadDelegate:nil]; | |
3050 | [webview setUIDelegate:nil]; | |
3051 | ||
3052 | [scroller_ setDelegate:nil]; | |
3053 | [webview_ setDelegate:nil]; | |
3054 | ||
3055 | [scroller_ release]; | |
3056 | [webview_ release]; | |
3057 | [urls_ release]; | |
3058 | [indicator_ release]; | |
3059 | if (title_ != nil) | |
3060 | [title_ release]; | |
3061 | [super dealloc]; | |
dc5812ec JF |
3062 | } |
3063 | ||
36bb2ca2 JF |
3064 | - (void) loadURL:(NSURL *)url cachePolicy:(NSURLRequestCachePolicy)policy { |
3065 | NSMutableURLRequest *request = [NSMutableURLRequest | |
3066 | requestWithURL:url | |
3067 | cachePolicy:policy | |
3068 | timeoutInterval:30.0 | |
3069 | ]; | |
b4d89997 | 3070 | |
36bb2ca2 JF |
3071 | [request addValue:[NSString stringWithCString:Firmware_] forHTTPHeaderField:@"X-Firmware"]; |
3072 | [request addValue:[NSString stringWithCString:Machine_] forHTTPHeaderField:@"X-Machine"]; | |
3073 | [request addValue:[NSString stringWithCString:SerialNumber_] forHTTPHeaderField:@"X-Serial-Number"]; | |
b4d89997 | 3074 | |
36bb2ca2 JF |
3075 | [self loadRequest:request]; |
3076 | } | |
dc5812ec | 3077 | |
dc5812ec | 3078 | |
36bb2ca2 JF |
3079 | - (void) loadURL:(NSURL *)url { |
3080 | [self loadURL:url cachePolicy:NSURLRequestUseProtocolCachePolicy]; | |
3081 | } | |
dc5812ec | 3082 | |
36bb2ca2 JF |
3083 | // XXX: this needs to add the headers |
3084 | - (NSURLRequest *) _addHeadersToRequest:(NSURLRequest *)request { | |
3085 | return request; | |
b4d89997 JF |
3086 | } |
3087 | ||
36bb2ca2 JF |
3088 | - (void) loadRequest:(NSURLRequest *)request { |
3089 | [webview_ loadRequest:request]; | |
3090 | } | |
b4d89997 | 3091 | |
36bb2ca2 JF |
3092 | - (void) reloadURL { |
3093 | NSURL *url = [[[urls_ lastObject] retain] autorelease]; | |
3094 | [urls_ removeLastObject]; | |
3095 | [self loadURL:url cachePolicy:NSURLRequestReloadIgnoringCacheData]; | |
3096 | } | |
b4d89997 | 3097 | |
36bb2ca2 JF |
3098 | - (WebView *) webView { |
3099 | return [webview_ webView]; | |
3100 | } | |
b4d89997 | 3101 | |
36bb2ca2 JF |
3102 | - (void) view:(UIView *)sender didSetFrame:(CGRect)frame { |
3103 | [scroller_ setContentSize:frame.size]; | |
3104 | } | |
b4d89997 | 3105 | |
36bb2ca2 JF |
3106 | - (void) view:(UIView *)sender didSetFrame:(CGRect)frame oldFrame:(CGRect)old { |
3107 | [self view:sender didSetFrame:frame]; | |
3108 | } | |
b4d89997 | 3109 | |
36bb2ca2 JF |
3110 | - (NSURLRequest *) webView:(WebView *)sender resource:(id)identifier willSendRequest:(NSURLRequest *)request redirectResponse:(NSURLResponse *)redirectResponse fromDataSource:(WebDataSource *)dataSource { |
3111 | return [self _addHeadersToRequest:request]; | |
3112 | } | |
b4d89997 | 3113 | |
36bb2ca2 JF |
3114 | - (WebView *) webView:(WebView *)sender createWebViewWithRequest:(NSURLRequest *)request { |
3115 | [self setBackButtonTitle:title_]; | |
3116 | BrowserView *browser = [[[BrowserView alloc] initWithBook:book_ database:database_] autorelease]; | |
3117 | [browser setDelegate:delegate_]; | |
3118 | [book_ pushPage:browser]; | |
3119 | [browser loadRequest:[self _addHeadersToRequest:request]]; | |
3120 | return [browser webView]; | |
3121 | } | |
3122 | ||
3123 | - (void) webView:(WebView *)sender willClickElement:(id)element { | |
3124 | if (![element respondsToSelector:@selector(href)]) | |
3125 | return; | |
3126 | NSString *href = [element href]; | |
3127 | if (href == nil) | |
3128 | return; | |
3129 | if ([href hasPrefix:@"apptapp://package/"]) { | |
3130 | NSString *name = [href substringFromIndex:18]; | |
3131 | Package *package = [database_ packageWithName:name]; | |
3132 | if (package == nil) { | |
3133 | UIAlertSheet *sheet = [[[UIAlertSheet alloc] | |
3134 | initWithTitle:@"Cannot Locate Package" | |
3135 | buttons:[NSArray arrayWithObjects:@"Close", nil] | |
3136 | defaultButtonIndex:0 | |
3137 | delegate:self | |
3138 | context:self | |
3139 | ] autorelease]; | |
b4d89997 | 3140 | |
36bb2ca2 JF |
3141 | [sheet setBodyText:[NSString stringWithFormat: |
3142 | @"The package %@ cannot be found in your current sources. I might recommend intalling more sources." | |
3143 | , name]]; | |
b4d89997 | 3144 | |
36bb2ca2 JF |
3145 | [sheet popupAlertAnimated:YES]; |
3146 | } else { | |
3147 | [self setBackButtonTitle:title_]; | |
3148 | PackageView *view = [[[PackageView alloc] initWithBook:book_ database:database_] autorelease]; | |
3149 | [view setDelegate:delegate_]; | |
3150 | [view setPackage:package]; | |
3151 | [book_ pushPage:view]; | |
3152 | } | |
3153 | } | |
dc5812ec JF |
3154 | } |
3155 | ||
36bb2ca2 JF |
3156 | - (void) webView:(WebView *)sender didReceiveTitle:(NSString *)title forFrame:(WebFrame *)frame { |
3157 | title_ = [title retain]; | |
3158 | [self setTitle:title]; | |
3159 | } | |
3160 | ||
3161 | - (void) webView:(WebView *)sender didStartProvisionalLoadForFrame:(WebFrame *)frame { | |
3162 | if ([frame parentFrame] != nil) | |
3163 | return; | |
3164 | ||
3165 | loading_ = true; | |
3166 | [indicator_ startAnimation]; | |
3167 | [self reloadButtons]; | |
3168 | ||
3169 | if (title_ != nil) { | |
3170 | [title_ release]; | |
3171 | title_ = nil; | |
b4d89997 | 3172 | } |
36bb2ca2 JF |
3173 | |
3174 | [self setTitle:@"Loading..."]; | |
3175 | ||
3176 | WebView *webview = [webview_ webView]; | |
3177 | NSString *href = [webview mainFrameURL]; | |
3178 | [urls_ addObject:[NSURL URLWithString:href]]; | |
3179 | ||
3180 | CGRect webrect = [scroller_ frame]; | |
3181 | webrect.size.height = 0; | |
3182 | [webview_ setFrame:webrect]; | |
dc5812ec JF |
3183 | } |
3184 | ||
36bb2ca2 JF |
3185 | - (void) _finishLoading { |
3186 | loading_ = false; | |
3187 | [indicator_ stopAnimation]; | |
3188 | [self reloadButtons]; | |
3189 | } | |
b4d89997 | 3190 | |
36bb2ca2 JF |
3191 | - (void) webView:(WebView *)sender didFinishLoadForFrame:(WebFrame *)frame { |
3192 | if ([frame parentFrame] != nil) | |
3193 | return; | |
3194 | [self _finishLoading]; | |
3195 | } | |
b4d89997 | 3196 | |
36bb2ca2 JF |
3197 | - (void) webView:(WebView *)sender didFailProvisionalLoadWithError:(NSError *)error forFrame:(WebFrame *)frame { |
3198 | if ([frame parentFrame] != nil) | |
3199 | return; | |
3200 | [self setTitle:[error localizedDescription]]; | |
3201 | [self _finishLoading]; | |
3202 | } | |
3203 | ||
3204 | - (id) initWithBook:(RVBook *)book database:(Database *)database { | |
3205 | if ((self = [super initWithBook:book]) != nil) { | |
3206 | database_ = database; | |
3207 | loading_ = false; | |
3208 | ||
3209 | struct CGRect bounds = [self bounds]; | |
3210 | ||
3211 | UIImageView *pinstripe = [[[UIImageView alloc] initWithFrame:bounds] autorelease]; | |
3212 | [pinstripe setImage:[UIImage applicationImageNamed:@"pinstripe.png"]]; | |
3213 | [self addSubview:pinstripe]; | |
3214 | ||
3215 | scroller_ = [[UIScroller alloc] initWithFrame:bounds]; | |
3216 | [self addSubview:scroller_]; | |
3217 | ||
3218 | [scroller_ setScrollingEnabled:YES]; | |
3219 | [scroller_ setAdjustForContentSizeChange:YES]; | |
3220 | [scroller_ setClipsSubviews:YES]; | |
3221 | [scroller_ setAllowsRubberBanding:YES]; | |
3222 | [scroller_ setScrollDecelerationFactor:0.99]; | |
3223 | [scroller_ setDelegate:self]; | |
3224 | ||
3225 | CGRect webrect = [scroller_ bounds]; | |
3226 | webrect.size.height = 0; | |
3227 | ||
3228 | webview_ = [[UIWebView alloc] initWithFrame:webrect]; | |
3229 | [scroller_ addSubview:webview_]; | |
3230 | ||
3231 | [webview_ setTilingEnabled:YES]; | |
3232 | [webview_ setTileSize:CGSizeMake(webrect.size.width, 500)]; | |
3233 | [webview_ setAutoresizes:YES]; | |
3234 | [webview_ setDelegate:self]; | |
3235 | //[webview_ setEnabledGestures:2]; | |
b4d89997 | 3236 | |
36bb2ca2 JF |
3237 | CGSize indsize = [UIProgressIndicator defaultSizeForStyle:0]; |
3238 | indicator_ = [[UIProgressIndicator alloc] initWithFrame:CGRectMake(281, 43, indsize.width, indsize.height)]; | |
3239 | [indicator_ setStyle:0]; | |
3240 | ||
3241 | Package *package([database_ packageWithName:@"cydia"]); | |
3242 | NSString *application = package == nil ? @"Cydia" : [NSString | |
3243 | stringWithFormat:@"Cydia/%@", | |
3244 | [package installed] | |
3245 | ]; | |
3246 | ||
3247 | WebView *webview = [webview_ webView]; | |
3248 | [webview setApplicationNameForUserAgent:application]; | |
3249 | [webview setFrameLoadDelegate:self]; | |
3250 | [webview setResourceLoadDelegate:self]; | |
3251 | [webview setUIDelegate:self]; | |
3252 | ||
3253 | urls_ = [[NSMutableArray alloc] initWithCapacity:16]; | |
3254 | } return self; | |
dc5812ec JF |
3255 | } |
3256 | ||
36bb2ca2 JF |
3257 | - (void) alertSheet:(UIAlertSheet *)sheet buttonClicked:(int)button { |
3258 | [sheet dismiss]; | |
3259 | } | |
3260 | ||
3261 | - (void) _leftButtonClicked { | |
3262 | UIAlertSheet *sheet = [[[UIAlertSheet alloc] | |
3263 | initWithTitle:@"About Cydia Packager" | |
3264 | buttons:[NSArray arrayWithObjects:@"Close", nil] | |
3265 | defaultButtonIndex:0 | |
3266 | delegate:self | |
3267 | context:self | |
3268 | ] autorelease]; | |
3269 | ||
3270 | [sheet setBodyText: | |
3271 | @"Copyright (C) 2008\n" | |
3272 | "Jay Freeman (saurik)\n" | |
3273 | "saurik@saurik.com\n" | |
3274 | "http://www.saurik.com/\n" | |
3275 | "\n" | |
3276 | "The Okori Group\n" | |
3277 | "http://www.theokorigroup.com/\n" | |
3278 | "\n" | |
3279 | "College of Creative Studies,\n" | |
3280 | "University of California,\n" | |
3281 | "Santa Barbara\n" | |
3282 | "http://www.ccs.ucsb.edu/" | |
3283 | ]; | |
3284 | ||
3285 | [sheet popupAlertAnimated:YES]; | |
3286 | } | |
3287 | ||
3288 | - (void) _rightButtonClicked { | |
3289 | [self reloadURL]; | |
3290 | } | |
3291 | ||
3292 | - (NSString *) leftButtonTitle { | |
3293 | return @"About"; | |
3294 | } | |
3295 | ||
3296 | - (NSString *) rightButtonTitle { | |
3297 | return loading_ ? @"" : @"Reload"; | |
3298 | } | |
3299 | ||
3300 | - (NSString *) title { | |
3301 | return nil; | |
3302 | } | |
3303 | ||
3304 | - (NSString *) backButtonTitle { | |
3305 | return @"Browser"; | |
dc5812ec JF |
3306 | } |
3307 | ||
36bb2ca2 JF |
3308 | - (void) setPageActive:(BOOL)active { |
3309 | if (active) | |
3310 | [book_ addSubview:indicator_]; | |
3311 | else | |
3312 | [indicator_ removeFromSuperview]; | |
dc5812ec JF |
3313 | } |
3314 | ||
36bb2ca2 | 3315 | - (void) resetViewAnimated:(BOOL)animated { |
b4d89997 | 3316 | } |
2367a917 | 3317 | |
b4d89997 JF |
3318 | @end |
3319 | /* }}} */ | |
36bb2ca2 | 3320 | |
9a7b04c5 JF |
3321 | @interface CYBook : RVBook < |
3322 | ProgressDelegate | |
3323 | > { | |
3324 | _transient Database *database_; | |
3325 | UIView *overlay_; | |
3326 | UIProgressIndicator *indicator_; | |
3327 | UITextLabel *prompt_; | |
3328 | UIProgressBar *progress_; | |
3329 | bool updating_; | |
3330 | } | |
3331 | ||
3332 | - (id) initWithFrame:(CGRect)frame database:(Database *)database; | |
3333 | - (void) update; | |
3334 | - (BOOL) updating; | |
3335 | ||
3336 | @end | |
3337 | ||
b4d89997 | 3338 | /* Install View {{{ */ |
36bb2ca2 JF |
3339 | @interface InstallView : RVPage { |
3340 | _transient Database *database_; | |
b4d89997 | 3341 | NSMutableArray *packages_; |
36bb2ca2 JF |
3342 | NSMutableArray *sections_; |
3343 | UITable *list_; | |
b4d89997 | 3344 | } |
dc5812ec | 3345 | |
36bb2ca2 JF |
3346 | - (id) initWithBook:(RVBook *)book database:(Database *)database; |
3347 | - (void) reloadData; | |
dc5812ec | 3348 | |
2367a917 JF |
3349 | @end |
3350 | ||
b4d89997 | 3351 | @implementation InstallView |
dc5812ec | 3352 | |
2367a917 | 3353 | - (void) dealloc { |
36bb2ca2 JF |
3354 | [list_ setDataSource:nil]; |
3355 | [list_ setDelegate:nil]; | |
3356 | ||
b4d89997 | 3357 | [packages_ release]; |
36bb2ca2 JF |
3358 | [sections_ release]; |
3359 | [list_ release]; | |
2367a917 JF |
3360 | [super dealloc]; |
3361 | } | |
3362 | ||
b4d89997 JF |
3363 | - (int) numberOfRowsInTable:(UITable *)table { |
3364 | return [sections_ count] + 1; | |
3365 | } | |
8da60fb7 | 3366 | |
b4d89997 JF |
3367 | - (float) table:(UITable *)table heightForRow:(int)row { |
3368 | return 45; | |
3369 | } | |
8da60fb7 | 3370 | |
b4d89997 JF |
3371 | - (UITableCell *) table:(UITable *)table cellForRow:(int)row column:(UITableColumn *)col reusing:(UITableCell *)reusing { |
3372 | if (reusing == nil) | |
3373 | reusing = [[[SectionCell alloc] init] autorelease]; | |
36bb2ca2 | 3374 | [(SectionCell *)reusing setSection:(row == 0 ? nil : [sections_ objectAtIndex:(row - 1)])]; |
b4d89997 JF |
3375 | return reusing; |
3376 | } | |
dc5812ec | 3377 | |
b4d89997 JF |
3378 | - (BOOL) table:(UITable *)table showDisclosureForRow:(int)row { |
3379 | return YES; | |
3380 | } | |
dc5812ec | 3381 | |
b4d89997 JF |
3382 | - (void) tableRowSelected:(NSNotification *)notification { |
3383 | int row = [[notification object] selectedRow]; | |
36bb2ca2 JF |
3384 | if (row == INT_MAX) |
3385 | return; | |
dc5812ec | 3386 | |
36bb2ca2 JF |
3387 | Section *section; |
3388 | NSString *title; | |
dc5812ec | 3389 | |
36bb2ca2 JF |
3390 | if (row == 0) { |
3391 | section = nil; | |
3392 | title = @"All Packages"; | |
b4d89997 | 3393 | } else { |
36bb2ca2 JF |
3394 | section = [sections_ objectAtIndex:(row - 1)]; |
3395 | title = [section name]; | |
b4d89997 | 3396 | } |
2367a917 | 3397 | |
36bb2ca2 JF |
3398 | PackageTable *table = [[[PackageTable alloc] |
3399 | initWithBook:book_ | |
3400 | database:database_ | |
3401 | title:title | |
3402 | filter:@selector(isUninstalledInSection:) | |
3403 | with:(section == nil ? nil : [section name]) | |
3404 | ] autorelease]; | |
2367a917 | 3405 | |
36bb2ca2 | 3406 | [table setDelegate:delegate_]; |
2367a917 | 3407 | |
36bb2ca2 | 3408 | [book_ pushPage:table]; |
b4d89997 | 3409 | } |
2367a917 | 3410 | |
36bb2ca2 JF |
3411 | - (id) initWithBook:(RVBook *)book database:(Database *)database { |
3412 | if ((self = [super initWithBook:book]) != nil) { | |
3413 | database_ = database; | |
3414 | ||
b4d89997 | 3415 | packages_ = [[NSMutableArray arrayWithCapacity:16] retain]; |
36bb2ca2 | 3416 | sections_ = [[NSMutableArray arrayWithCapacity:16] retain]; |
2367a917 | 3417 | |
36bb2ca2 JF |
3418 | list_ = [[UITable alloc] initWithFrame:[self bounds]]; |
3419 | [self addSubview:list_]; | |
dc5812ec | 3420 | |
b4d89997 JF |
3421 | UITableColumn *column = [[[UITableColumn alloc] |
3422 | initWithTitle:@"Name" | |
3423 | identifier:@"name" | |
36bb2ca2 | 3424 | width:[self frame].size.width |
b4d89997 | 3425 | ] autorelease]; |
dc5812ec | 3426 | |
b4d89997 JF |
3427 | [list_ setDataSource:self]; |
3428 | [list_ setSeparatorStyle:1]; | |
3429 | [list_ addTableColumn:column]; | |
3430 | [list_ setDelegate:self]; | |
3431 | [list_ setReusesTableCells:YES]; | |
2367a917 | 3432 | |
36bb2ca2 | 3433 | [self reloadData]; |
b4d89997 | 3434 | } return self; |
2367a917 JF |
3435 | } |
3436 | ||
36bb2ca2 JF |
3437 | - (void) reloadData { |
3438 | NSArray *packages = [database_ packages]; | |
3439 | ||
b4d89997 | 3440 | [packages_ removeAllObjects]; |
36bb2ca2 | 3441 | [sections_ removeAllObjects]; |
dc5812ec | 3442 | |
b4d89997 JF |
3443 | for (size_t i(0); i != [packages count]; ++i) { |
3444 | Package *package([packages objectAtIndex:i]); | |
3445 | if ([package installed] == nil) | |
3446 | [packages_ addObject:package]; | |
3447 | } | |
dc5812ec | 3448 | |
36bb2ca2 | 3449 | [packages_ sortUsingSelector:@selector(compareBySection:)]; |
dc5812ec | 3450 | |
b4d89997 JF |
3451 | Section *section = nil; |
3452 | for (size_t offset = 0, count = [packages_ count]; offset != count; ++offset) { | |
3453 | Package *package = [packages_ objectAtIndex:offset]; | |
3454 | NSString *name = [package section]; | |
2367a917 | 3455 | |
36bb2ca2 | 3456 | if (section == nil || name != nil && ![[section name] isEqualToString:name]) { |
b4d89997 | 3457 | section = [[[Section alloc] initWithName:name row:offset] autorelease]; |
36bb2ca2 | 3458 | [sections_ addObject:section]; |
b4d89997 | 3459 | } |
dc5812ec | 3460 | |
36bb2ca2 | 3461 | [section addToCount]; |
b4d89997 | 3462 | } |
2367a917 | 3463 | |
b4d89997 | 3464 | [list_ reloadData]; |
36bb2ca2 | 3465 | } |
2367a917 | 3466 | |
36bb2ca2 JF |
3467 | - (void) resetViewAnimated:(BOOL)animated { |
3468 | [list_ resetViewAnimated:animated]; | |
3469 | } | |
2367a917 | 3470 | |
36bb2ca2 JF |
3471 | - (NSString *) title { |
3472 | return @"Install"; | |
2367a917 JF |
3473 | } |
3474 | ||
36bb2ca2 JF |
3475 | - (NSString *) backButtonTitle { |
3476 | return @"Sections"; | |
dc5812ec JF |
3477 | } |
3478 | ||
3479 | @end | |
2367a917 | 3480 | /* }}} */ |
b4d89997 | 3481 | /* Changes View {{{ */ |
36bb2ca2 JF |
3482 | @interface ChangesView : RVPage { |
3483 | _transient Database *database_; | |
dc5812ec JF |
3484 | NSMutableArray *packages_; |
3485 | NSMutableArray *sections_; | |
36bb2ca2 JF |
3486 | UISectionList *list_; |
3487 | unsigned upgrades_; | |
dc5812ec JF |
3488 | } |
3489 | ||
36bb2ca2 JF |
3490 | - (id) initWithBook:(RVBook *)book database:(Database *)database; |
3491 | - (void) reloadData; | |
dc5812ec | 3492 | |
dc5812ec JF |
3493 | @end |
3494 | ||
b4d89997 JF |
3495 | @implementation ChangesView |
3496 | ||
3497 | - (void) dealloc { | |
36bb2ca2 JF |
3498 | [[list_ table] setDelegate:nil]; |
3499 | [list_ setDataSource:nil]; | |
3500 | ||
b4d89997 JF |
3501 | [packages_ release]; |
3502 | [sections_ release]; | |
36bb2ca2 | 3503 | [list_ release]; |
b4d89997 JF |
3504 | [super dealloc]; |
3505 | } | |
dc5812ec JF |
3506 | |
3507 | - (int) numberOfSectionsInSectionList:(UISectionList *)list { | |
3508 | return [sections_ count]; | |
3509 | } | |
3510 | ||
3511 | - (NSString *) sectionList:(UISectionList *)list titleForSection:(int)section { | |
3512 | return [[sections_ objectAtIndex:section] name]; | |
3513 | } | |
3514 | ||
3515 | - (int) sectionList:(UISectionList *)list rowForSection:(int)section { | |
3516 | return [[sections_ objectAtIndex:section] row]; | |
3517 | } | |
3518 | ||
3519 | - (int) numberOfRowsInTable:(UITable *)table { | |
3520 | return [packages_ count]; | |
3521 | } | |
3522 | ||
3523 | - (float) table:(UITable *)table heightForRow:(int)row { | |
36bb2ca2 | 3524 | return 73; |
dc5812ec JF |
3525 | } |
3526 | ||
1d80f6b9 JF |
3527 | - (UITableCell *) table:(UITable *)table cellForRow:(int)row column:(UITableColumn *)col reusing:(UITableCell *)reusing { |
3528 | if (reusing == nil) | |
36bb2ca2 | 3529 | reusing = [[[PackageCell alloc] init] autorelease]; |
1d80f6b9 JF |
3530 | [(PackageCell *)reusing setPackage:[packages_ objectAtIndex:row]]; |
3531 | return reusing; | |
dc5812ec JF |
3532 | } |
3533 | ||
3534 | - (BOOL) table:(UITable *)table showDisclosureForRow:(int)row { | |
b4d89997 | 3535 | return NO; |
dc5812ec JF |
3536 | } |
3537 | ||
b4d89997 JF |
3538 | - (void) tableRowSelected:(NSNotification *)notification { |
3539 | int row = [[notification object] selectedRow]; | |
36bb2ca2 JF |
3540 | if (row == INT_MAX) |
3541 | return; | |
3542 | Package *package = [packages_ objectAtIndex:row]; | |
3543 | PackageView *view = [[[PackageView alloc] initWithBook:book_ database:database_] autorelease]; | |
3544 | [view setDelegate:delegate_]; | |
3545 | [view setPackage:package]; | |
3546 | [book_ pushPage:view]; | |
dc5812ec JF |
3547 | } |
3548 | ||
9a7b04c5 JF |
3549 | - (void) _leftButtonClicked { |
3550 | [(CYBook *)book_ update]; | |
3551 | [self reloadButtons]; | |
3552 | } | |
3553 | ||
36bb2ca2 JF |
3554 | - (void) _rightButtonClicked { |
3555 | [delegate_ distUpgrade]; | |
dc5812ec JF |
3556 | } |
3557 | ||
36bb2ca2 JF |
3558 | - (id) initWithBook:(RVBook *)book database:(Database *)database { |
3559 | if ((self = [super initWithBook:book]) != nil) { | |
3560 | database_ = database; | |
dc5812ec | 3561 | |
b4d89997 JF |
3562 | packages_ = [[NSMutableArray arrayWithCapacity:16] retain]; |
3563 | sections_ = [[NSMutableArray arrayWithCapacity:16] retain]; | |
dc5812ec | 3564 | |
36bb2ca2 JF |
3565 | list_ = [[UISectionList alloc] initWithFrame:[self bounds] showSectionIndex:NO]; |
3566 | [self addSubview:list_]; | |
3567 | ||
3178d79b | 3568 | [list_ setShouldHideHeaderInShortLists:NO]; |
b4d89997 JF |
3569 | [list_ setDataSource:self]; |
3570 | //[list_ setSectionListStyle:1]; | |
dc5812ec | 3571 | |
b4d89997 | 3572 | UITableColumn *column = [[[UITableColumn alloc] |
dc5812ec JF |
3573 | initWithTitle:@"Name" |
3574 | identifier:@"name" | |
36bb2ca2 | 3575 | width:[self frame].size.width |
b4d89997 | 3576 | ] autorelease]; |
dc5812ec JF |
3577 | |
3578 | UITable *table = [list_ table]; | |
3579 | [table setSeparatorStyle:1]; | |
3580 | [table addTableColumn:column]; | |
3581 | [table setDelegate:self]; | |
1d80f6b9 | 3582 | [table setReusesTableCells:YES]; |
dc5812ec | 3583 | |
36bb2ca2 | 3584 | [self reloadData]; |
dc5812ec JF |
3585 | } return self; |
3586 | } | |
3587 | ||
36bb2ca2 JF |
3588 | - (void) reloadData { |
3589 | NSArray *packages = [database_ packages]; | |
3590 | ||
b4d89997 | 3591 | [packages_ removeAllObjects]; |
36bb2ca2 JF |
3592 | [sections_ removeAllObjects]; |
3593 | ||
b4d89997 JF |
3594 | for (size_t i(0); i != [packages count]; ++i) { |
3595 | Package *package([packages objectAtIndex:i]); | |
3596 | if ([package installed] == nil || [package upgradable]) | |
3597 | [packages_ addObject:package]; | |
3598 | } | |
2367a917 | 3599 | |
b4d89997 | 3600 | [packages_ sortUsingSelector:@selector(compareForChanges:)]; |
dc5812ec | 3601 | |
b4d89997 | 3602 | Section *upgradable = [[[Section alloc] initWithName:@"Available Upgrades" row:0] autorelease]; |
dc5812ec | 3603 | Section *section = nil; |
b4d89997 | 3604 | |
36bb2ca2 JF |
3605 | upgrades_ = 0; |
3606 | bool unseens = false; | |
3607 | ||
3608 | CFLocaleRef locale = CFLocaleCopyCurrent(); | |
3609 | CFDateFormatterRef formatter = CFDateFormatterCreate(NULL, locale, kCFDateFormatterMediumStyle, kCFDateFormatterMediumStyle); | |
3610 | ||
dc5812ec JF |
3611 | for (size_t offset = 0, count = [packages_ count]; offset != count; ++offset) { |
3612 | Package *package = [packages_ objectAtIndex:offset]; | |
dc5812ec | 3613 | |
36bb2ca2 JF |
3614 | if ([package upgradable]) { |
3615 | ++upgrades_; | |
3616 | [upgradable addToCount]; | |
3617 | } else { | |
3618 | unseens = true; | |
b4d89997 | 3619 | NSDate *seen = [package seen]; |
dc5812ec | 3620 | |
723a0072 | 3621 | NSString *name; |
723a0072 JF |
3622 | |
3623 | if (seen == nil) | |
36bb2ca2 | 3624 | name = [@"n/a ?" retain]; |
723a0072 | 3625 | else { |
36bb2ca2 | 3626 | name = (NSString *) CFDateFormatterCreateStringWithDate(NULL, formatter, (CFDateRef) seen); |
723a0072 | 3627 | } |
b4d89997 | 3628 | |
36bb2ca2 | 3629 | if (section == nil || ![[section name] isEqualToString:name]) { |
b4d89997 JF |
3630 | section = [[[Section alloc] initWithName:name row:offset] autorelease]; |
3631 | [sections_ addObject:section]; | |
3632 | } | |
3633 | ||
36bb2ca2 JF |
3634 | [name release]; |
3635 | [section addToCount]; | |
b4d89997 | 3636 | } |
dc5812ec JF |
3637 | } |
3638 | ||
36bb2ca2 JF |
3639 | CFRelease(formatter); |
3640 | CFRelease(locale); | |
b4d89997 | 3641 | |
36bb2ca2 JF |
3642 | if (unseens) { |
3643 | Section *last = [sections_ lastObject]; | |
3644 | size_t count = [last count]; | |
3645 | [packages_ removeObjectsInRange:NSMakeRange([packages_ count] - count, count)]; | |
3646 | [sections_ removeLastObject]; | |
3647 | } | |
dc5812ec | 3648 | |
36bb2ca2 JF |
3649 | if (upgrades_ != 0) |
3650 | [sections_ insertObject:upgradable atIndex:0]; | |
c25a610d | 3651 | |
36bb2ca2 JF |
3652 | [list_ reloadData]; |
3653 | [self reloadButtons]; | |
3178d79b JF |
3654 | } |
3655 | ||
36bb2ca2 JF |
3656 | - (void) resetViewAnimated:(BOOL)animated { |
3657 | [list_ resetViewAnimated:animated]; | |
3178d79b JF |
3658 | } |
3659 | ||
9a7b04c5 JF |
3660 | - (NSString *) leftButtonTitle { |
3661 | return [(CYBook *)book_ updating] ? nil : @"Refresh"; | |
3662 | } | |
3663 | ||
36bb2ca2 JF |
3664 | - (NSString *) rightButtonTitle { |
3665 | return upgrades_ == 0 ? nil : [NSString stringWithFormat:@"Upgrade All (%u)", upgrades_]; | |
3178d79b JF |
3666 | } |
3667 | ||
36bb2ca2 JF |
3668 | - (NSString *) title { |
3669 | return @"Changes"; | |
8fe19fc1 JF |
3670 | } |
3671 | ||
559dec34 JF |
3672 | @end |
3673 | /* }}} */ | |
3674 | /* Manage View {{{ */ | |
3675 | @interface ManageView : PackageTable { | |
3676 | } | |
3677 | ||
3678 | - (id) initWithBook:(RVBook *)book database:(Database *)database; | |
3679 | ||
3680 | @end | |
3681 | ||
3682 | @implementation ManageView | |
3683 | ||
3684 | - (id) initWithBook:(RVBook *)book database:(Database *)database { | |
3685 | if ((self = [super | |
3686 | initWithBook:book | |
3687 | database:database | |
3688 | title:nil | |
3689 | filter:@selector(isInstalledInSection:) | |
3690 | with:nil | |
3691 | ]) != nil) { | |
3692 | } return self; | |
3693 | } | |
3694 | ||
3695 | - (NSString *) title { | |
3696 | return @"Installed Packages"; | |
3697 | } | |
3698 | ||
3699 | - (NSString *) backButtonTitle { | |
3700 | return @"All Packages"; | |
3701 | } | |
3702 | ||
3178d79b JF |
3703 | @end |
3704 | /* }}} */ | |
36bb2ca2 JF |
3705 | /* Search View {{{ */ |
3706 | @protocol SearchViewDelegate | |
3707 | - (void) showKeyboard:(BOOL)show; | |
3708 | @end | |
b4d89997 | 3709 | |
a0be02eb | 3710 | @interface SearchView : RVPage { |
36bb2ca2 JF |
3711 | UIView *accessory_; |
3712 | UISearchField *field_; | |
a0be02eb JF |
3713 | UITransitionView *transition_; |
3714 | PackageTable *table_; | |
3715 | UIPreferencesTable *advanced_; | |
3716 | UIView *dimmed_; | |
3717 | bool flipped_; | |
36bb2ca2 | 3718 | } |
b4d89997 | 3719 | |
36bb2ca2 JF |
3720 | - (id) initWithBook:(RVBook *)book database:(Database *)database; |
3721 | - (void) reloadData; | |
b4d89997 | 3722 | |
3178d79b JF |
3723 | @end |
3724 | ||
36bb2ca2 | 3725 | @implementation SearchView |
3178d79b | 3726 | |
b4d89997 | 3727 | - (void) dealloc { |
36bb2ca2 JF |
3728 | #ifndef __OBJC2__ |
3729 | [[field_ textTraits] setEditingDelegate:nil]; | |
3730 | #endif | |
3731 | [field_ setDelegate:nil]; | |
3178d79b | 3732 | |
36bb2ca2 JF |
3733 | [accessory_ release]; |
3734 | [field_ release]; | |
a0be02eb JF |
3735 | [transition_ release]; |
3736 | [table_ release]; | |
3737 | [advanced_ release]; | |
3738 | [dimmed_ release]; | |
36bb2ca2 | 3739 | [super dealloc]; |
b4d89997 JF |
3740 | } |
3741 | ||
36bb2ca2 JF |
3742 | - (void) textFieldDidBecomeFirstResponder:(UITextField *)field { |
3743 | [delegate_ showKeyboard:YES]; | |
a0be02eb JF |
3744 | [table_ setEnabled:NO]; |
3745 | [self addSubview:dimmed_]; | |
36bb2ca2 | 3746 | } |
b4d89997 | 3747 | |
36bb2ca2 | 3748 | - (void) textFieldDidResignFirstResponder:(UITextField *)field { |
a0be02eb JF |
3749 | [dimmed_ removeFromSuperview]; |
3750 | [table_ setEnabled:YES]; | |
36bb2ca2 JF |
3751 | [delegate_ showKeyboard:NO]; |
3752 | } | |
b4d89997 | 3753 | |
36bb2ca2 JF |
3754 | - (void) keyboardInputChanged:(UIFieldEditor *)editor { |
3755 | NSString *text([field_ text]); | |
3756 | [field_ setClearButtonStyle:(text == nil || [text length] == 0 ? 0 : 2)]; | |
3757 | } | |
b4d89997 | 3758 | |
36bb2ca2 JF |
3759 | - (BOOL) keyboardInput:(id)input shouldInsertText:(NSString *)text isMarkedText:(int)marked { |
3760 | if ([text length] != 1 || [text characterAtIndex:0] != '\n') | |
3761 | return YES; | |
b4d89997 | 3762 | |
36bb2ca2 JF |
3763 | [self reloadData]; |
3764 | [field_ resignFirstResponder]; | |
3765 | return NO; | |
b4d89997 JF |
3766 | } |
3767 | ||
36bb2ca2 | 3768 | - (id) initWithBook:(RVBook *)book database:(Database *)database { |
a0be02eb JF |
3769 | if ((self = [super initWithBook:book]) != nil) { |
3770 | CGRect pageBounds = [book_ pageBounds]; | |
3771 | ||
7fea16f2 | 3772 | /*UIImageView *pinstripe = [[[UIImageView alloc] initWithFrame:pageBounds] autorelease]; |
a0be02eb | 3773 | [pinstripe setImage:[UIImage applicationImageNamed:@"pinstripe.png"]]; |
7fea16f2 | 3774 | [self addSubview:pinstripe];*/ |
a0be02eb JF |
3775 | |
3776 | dimmed_ = [[UIView alloc] initWithFrame:pageBounds]; | |
3777 | CGColor dimmed(space_, 0, 0, 0, 0.5); | |
3778 | [dimmed_ setBackgroundColor:dimmed]; | |
3779 | ||
3780 | transition_ = [[UITransitionView alloc] initWithFrame:pageBounds]; | |
3781 | [self addSubview:transition_]; | |
3782 | ||
3783 | advanced_ = [[UIPreferencesTable alloc] initWithFrame:pageBounds]; | |
3784 | ||
3785 | table_ = [[PackageTable alloc] | |
3786 | initWithBook:book | |
3787 | database:database | |
3788 | title:nil | |
3789 | filter:@selector(isSearchedForBy:) | |
3790 | with:nil | |
3791 | ]; | |
3792 | ||
3793 | [transition_ transition:0 toView:table_]; | |
3794 | ||
559dec34 | 3795 | CGRect cnfrect = {{2, 37}, {17, 18}}; |
b4d89997 | 3796 | |
36bb2ca2 | 3797 | CGRect area; |
559dec34 | 3798 | area.origin.x = cnfrect.size.width + 17; |
36bb2ca2 | 3799 | area.origin.y = 30; |
9a7b04c5 | 3800 | area.size.width = [self bounds].size.width - area.origin.x - 18; |
36bb2ca2 | 3801 | area.size.height = [UISearchField defaultHeight]; |
3178d79b | 3802 | |
36bb2ca2 | 3803 | field_ = [[UISearchField alloc] initWithFrame:area]; |
b4d89997 | 3804 | |
36bb2ca2 JF |
3805 | GSFontRef font = GSFontCreateWithName("Helvetica", kGSFontTraitNone, 16); |
3806 | [field_ setFont:font]; | |
3807 | CFRelease(font); | |
b4d89997 | 3808 | |
36bb2ca2 JF |
3809 | [field_ setPlaceholder:@"Package Names & Descriptions"]; |
3810 | [field_ setPaddingTop:5]; | |
3811 | [field_ setDelegate:self]; | |
b4d89997 | 3812 | |
36bb2ca2 JF |
3813 | #ifndef __OBJC2__ |
3814 | UITextTraits *traits = [field_ textTraits]; | |
3815 | [traits setEditingDelegate:self]; | |
3816 | [traits setReturnKeyType:6]; | |
3817 | [traits setAutoCapsType:0]; | |
3818 | [traits setAutoCorrectionType:1]; | |
3819 | #endif | |
b4d89997 | 3820 | |
36bb2ca2 JF |
3821 | UIPushButton *configure = [[[UIPushButton alloc] initWithFrame:cnfrect] autorelease]; |
3822 | [configure setShowPressFeedback:YES]; | |
559dec34 | 3823 | [configure setImage:[UIImage applicationImageNamed:@"advanced.png"]]; |
36bb2ca2 | 3824 | [configure addTarget:self action:@selector(configurePushed) forEvents:1]; |
b4d89997 | 3825 | |
36bb2ca2 JF |
3826 | accessory_ = [[UIView alloc] initWithFrame:CGRectMake(0, 6, cnfrect.size.width + area.size.width + 6 * 3, area.size.height + 30)]; |
3827 | [accessory_ addSubview:field_]; | |
3828 | [accessory_ addSubview:configure]; | |
3829 | } return self; | |
3178d79b JF |
3830 | } |
3831 | ||
a0be02eb JF |
3832 | - (void) flipPage { |
3833 | LKAnimation *animation = [LKTransition animation]; | |
3834 | [animation setType:@"oglFlip"]; | |
3835 | [animation setTimingFunction:[LKTimingFunction functionWithName:@"easeInEaseOut"]]; | |
3836 | [animation setFillMode:@"extended"]; | |
3837 | [animation setTransitionFlags:3]; | |
3838 | [animation setDuration:10]; | |
3839 | [animation setSpeed:0.35]; | |
7fea16f2 JF |
3840 | [animation setSubtype:(flipped_ ? @"fromLeft" : @"fromRight")]; |
3841 | [[transition_ _layer] addAnimation:animation forKey:0]; | |
a0be02eb JF |
3842 | [transition_ transition:0 toView:(flipped_ ? (UIView *) table_ : (UIView *) advanced_)]; |
3843 | flipped_ = !flipped_; | |
3844 | } | |
3845 | ||
36bb2ca2 | 3846 | - (void) configurePushed { |
a0be02eb JF |
3847 | [field_ resignFirstResponder]; |
3848 | [self flipPage]; | |
3849 | } | |
3850 | ||
3851 | - (void) resetViewAnimated:(BOOL)animated { | |
3852 | if (flipped_) | |
3853 | [self flipPage]; | |
3854 | [table_ resetViewAnimated:animated]; | |
8fe19fc1 JF |
3855 | } |
3856 | ||
36bb2ca2 | 3857 | - (void) reloadData { |
a0be02eb JF |
3858 | if (flipped_) |
3859 | [self flipPage]; | |
3860 | [table_ setObject:[field_ text]]; | |
3861 | [table_ reloadData]; | |
3862 | [table_ resetCursor]; | |
3178d79b JF |
3863 | } |
3864 | ||
36bb2ca2 JF |
3865 | - (UIView *) accessoryView { |
3866 | return accessory_; | |
3867 | } | |
b4d89997 | 3868 | |
a0be02eb JF |
3869 | - (NSString *) title { |
3870 | return nil; | |
3871 | } | |
3872 | ||
36bb2ca2 JF |
3873 | - (NSString *) backButtonTitle { |
3874 | return @"Search"; | |
3875 | } | |
74127566 | 3876 | |
3178d79b | 3877 | @end |
36bb2ca2 | 3878 | /* }}} */ |
3178d79b | 3879 | |
36bb2ca2 | 3880 | @implementation CYBook |
b4d89997 | 3881 | |
36bb2ca2 JF |
3882 | - (void) dealloc { |
3883 | [overlay_ release]; | |
3884 | [indicator_ release]; | |
3885 | [prompt_ release]; | |
3886 | [progress_ release]; | |
3887 | [super dealloc]; | |
3888 | } | |
b4d89997 | 3889 | |
9a7b04c5 JF |
3890 | - (BOOL) updating { |
3891 | return updating_; | |
3892 | } | |
3893 | ||
36bb2ca2 | 3894 | - (void) update { |
9a7b04c5 | 3895 | [navbar_ setPrompt:@""]; |
36bb2ca2 JF |
3896 | [navbar_ addSubview:overlay_]; |
3897 | [indicator_ startAnimation]; | |
3898 | [prompt_ setText:@"Updating Database..."]; | |
3899 | [progress_ setProgress:0]; | |
b4d89997 | 3900 | |
9a7b04c5 JF |
3901 | updating_ = true; |
3902 | ||
36bb2ca2 JF |
3903 | [NSThread |
3904 | detachNewThreadSelector:@selector(_update) | |
3905 | toTarget:self | |
3906 | withObject:nil | |
3907 | ]; | |
3178d79b JF |
3908 | } |
3909 | ||
36bb2ca2 | 3910 | - (void) _update_ { |
9a7b04c5 JF |
3911 | updating_ = false; |
3912 | ||
36bb2ca2 JF |
3913 | [overlay_ removeFromSuperview]; |
3914 | [indicator_ stopAnimation]; | |
3915 | [delegate_ reloadData]; | |
b4d89997 | 3916 | |
36bb2ca2 | 3917 | [self setPrompt:[NSString stringWithFormat:@"Last Updated: %@", GetLastUpdate()]]; |
3178d79b JF |
3918 | } |
3919 | ||
36bb2ca2 JF |
3920 | - (id) initWithFrame:(CGRect)frame database:(Database *)database { |
3921 | if ((self = [super initWithFrame:frame]) != nil) { | |
3922 | database_ = database; | |
3178d79b | 3923 | |
36bb2ca2 JF |
3924 | CGRect ovrrect = [navbar_ bounds]; |
3925 | ovrrect.size.height = [UINavigationBar defaultSizeWithPrompt].height - [UINavigationBar defaultSize].height; | |
3178d79b | 3926 | |
36bb2ca2 | 3927 | overlay_ = [[UIView alloc] initWithFrame:ovrrect]; |
b4d89997 | 3928 | |
36bb2ca2 JF |
3929 | CGSize indsize = [UIProgressIndicator defaultSizeForStyle:2]; |
3930 | unsigned indoffset = (ovrrect.size.height - indsize.height) / 2; | |
3931 | CGRect indrect = {{indoffset, indoffset}, indsize}; | |
8fe19fc1 | 3932 | |
36bb2ca2 JF |
3933 | indicator_ = [[UIProgressIndicator alloc] initWithFrame:indrect]; |
3934 | [indicator_ setStyle:2]; | |
3935 | [overlay_ addSubview:indicator_]; | |
b4d89997 | 3936 | |
36bb2ca2 | 3937 | CGSize prmsize = {200, indsize.width}; |
b4d89997 | 3938 | |
36bb2ca2 JF |
3939 | CGRect prmrect = {{ |
3940 | indoffset * 2 + indsize.width, | |
3941 | (ovrrect.size.height - prmsize.height) / 2 | |
3942 | }, prmsize}; | |
b4d89997 | 3943 | |
36bb2ca2 | 3944 | GSFontRef font = GSFontCreateWithName("Helvetica", kGSFontTraitNone, 12); |
b4d89997 | 3945 | |
36bb2ca2 | 3946 | prompt_ = [[UITextLabel alloc] initWithFrame:prmrect]; |
b4d89997 | 3947 | |
36bb2ca2 JF |
3948 | [prompt_ setColor:White_]; |
3949 | [prompt_ setBackgroundColor:Clear_]; | |
3950 | [prompt_ setFont:font]; | |
b4d89997 | 3951 | |
36bb2ca2 | 3952 | CFRelease(font); |
b4d89997 | 3953 | |
36bb2ca2 | 3954 | [overlay_ addSubview:prompt_]; |
b4d89997 | 3955 | |
36bb2ca2 | 3956 | CGSize prgsize = {75, 100}; |
b4d89997 | 3957 | |
36bb2ca2 JF |
3958 | CGRect prgrect = {{ |
3959 | ovrrect.size.width - prgsize.width - 10, | |
3960 | (ovrrect.size.height - prgsize.height) / 2 | |
3961 | } , prgsize}; | |
3962 | ||
3963 | progress_ = [[UIProgressBar alloc] initWithFrame:prgrect]; | |
3964 | [progress_ setStyle:0]; | |
3965 | [overlay_ addSubview:progress_]; | |
b4d89997 | 3966 | } return self; |
3178d79b JF |
3967 | } |
3968 | ||
36bb2ca2 JF |
3969 | - (void) _update { |
3970 | NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; | |
dc5812ec | 3971 | |
36bb2ca2 JF |
3972 | Status status; |
3973 | status.setDelegate(self); | |
b4d89997 | 3974 | |
36bb2ca2 | 3975 | [database_ updateWithStatus:status]; |
3178d79b | 3976 | |
36bb2ca2 JF |
3977 | [self |
3978 | performSelectorOnMainThread:@selector(_update_) | |
3979 | withObject:nil | |
3980 | waitUntilDone:NO | |
3981 | ]; | |
b4d89997 | 3982 | |
36bb2ca2 | 3983 | [pool release]; |
dc5812ec JF |
3984 | } |
3985 | ||
36bb2ca2 JF |
3986 | - (void) setProgressError:(NSString *)error { |
3987 | [self | |
3988 | performSelectorOnMainThread:@selector(_setProgressError:) | |
3989 | withObject:error | |
3990 | waitUntilDone:YES | |
3991 | ]; | |
dc5812ec JF |
3992 | } |
3993 | ||
36bb2ca2 JF |
3994 | - (void) setProgressTitle:(NSString *)title { |
3995 | [self | |
3996 | performSelectorOnMainThread:@selector(_setProgressTitle:) | |
3997 | withObject:title | |
3998 | waitUntilDone:YES | |
3999 | ]; | |
3178d79b JF |
4000 | } |
4001 | ||
36bb2ca2 JF |
4002 | - (void) setProgressPercent:(float)percent { |
4003 | } | |
b4d89997 | 4004 | |
36bb2ca2 JF |
4005 | - (void) addProgressOutput:(NSString *)output { |
4006 | [self | |
4007 | performSelectorOnMainThread:@selector(_addProgressOutput:) | |
4008 | withObject:output | |
4009 | waitUntilDone:YES | |
4010 | ]; | |
4011 | } | |
b4d89997 | 4012 | |
36bb2ca2 JF |
4013 | - (void) alertSheet:(UIAlertSheet *)sheet buttonClicked:(int)button { |
4014 | [sheet dismiss]; | |
4015 | } | |
4016 | ||
4017 | - (void) _setProgressError:(NSString *)error { | |
4018 | [prompt_ setText:[NSString stringWithFormat:@"Error: %@", error]]; | |
4019 | } | |
4020 | ||
4021 | - (void) _setProgressTitle:(NSString *)title { | |
4022 | [prompt_ setText:[title stringByAppendingString:@"..."]]; | |
4023 | } | |
b4d89997 | 4024 | |
36bb2ca2 | 4025 | - (void) _addProgressOutput:(NSString *)output { |
8fe19fc1 JF |
4026 | } |
4027 | ||
3178d79b | 4028 | @end |
3178d79b | 4029 | |
2367a917 | 4030 | @interface Cydia : UIApplication < |
3178d79b | 4031 | ConfirmationViewDelegate, |
b4d89997 | 4032 | ProgressViewDelegate, |
5f6bff8c JF |
4033 | SearchViewDelegate, |
4034 | CydiaDelegate | |
2367a917 | 4035 | > { |
dc5812ec | 4036 | UIWindow *window_; |
36bb2ca2 | 4037 | |
3178d79b JF |
4038 | UIView *underlay_; |
4039 | UIView *overlay_; | |
36bb2ca2 | 4040 | CYBook *book_; |
2367a917 | 4041 | UIButtonBar *buttonbar_; |
3178d79b | 4042 | |
3178d79b | 4043 | ConfirmationView *confirm_; |
dc5812ec JF |
4044 | |
4045 | Database *database_; | |
4046 | ProgressView *progress_; | |
4047 | ||
06aa974d | 4048 | unsigned tag_; |
b4d89997 JF |
4049 | |
4050 | UIKeyboard *keyboard_; | |
dc5812ec JF |
4051 | } |
4052 | ||
dc5812ec JF |
4053 | @end |
4054 | ||
4055 | @implementation Cydia | |
4056 | ||
36bb2ca2 JF |
4057 | - (void) _reloadData { |
4058 | /*UIProgressHUD *hud = [[UIProgressHUD alloc] initWithWindow:window_]; | |
4059 | [hud setText:@"Reloading Data"]; | |
4060 | [overlay_ addSubview:hud]; | |
4061 | [hud show:YES];*/ | |
dc5812ec | 4062 | |
dc5812ec | 4063 | [database_ reloadData]; |
c25a610d | 4064 | |
b4d89997 JF |
4065 | size_t count = 16; |
4066 | ||
4067 | if (Packages_ == nil) { | |
4068 | Packages_ = [[NSMutableDictionary alloc] initWithCapacity:count]; | |
4069 | [Metadata_ setObject:Packages_ forKey:@"Packages"]; | |
4070 | } | |
4071 | ||
36bb2ca2 | 4072 | size_t changes(0); |
b4d89997 | 4073 | |
36bb2ca2 JF |
4074 | NSArray *packages = [database_ packages]; |
4075 | for (int i(0), e([packages count]); i != e; ++i) { | |
4076 | Package *package = [packages objectAtIndex:i]; | |
4077 | if ([package upgradable]) | |
4078 | ++changes; | |
4079 | } | |
b4d89997 | 4080 | |
36bb2ca2 JF |
4081 | if (changes != 0) { |
4082 | NSString *badge([[NSNumber numberWithInt:changes] stringValue]); | |
c25a610d | 4083 | [buttonbar_ setBadgeValue:badge forButton:3]; |
9e98e020 JF |
4084 | if ([buttonbar_ respondsToSelector:@selector(setBadgeAnimated:forButton:)]) |
4085 | [buttonbar_ setBadgeAnimated:YES forButton:3]; | |
c25a610d JF |
4086 | [self setApplicationBadge:badge]; |
4087 | } else { | |
4088 | [buttonbar_ setBadgeValue:nil forButton:3]; | |
9e98e020 JF |
4089 | if ([buttonbar_ respondsToSelector:@selector(setBadgeAnimated:forButton:)]) |
4090 | [buttonbar_ setBadgeAnimated:NO forButton:3]; | |
c25a610d JF |
4091 | [self removeApplicationBadge]; |
4092 | } | |
b4d89997 JF |
4093 | |
4094 | _assert([Metadata_ writeToFile:@"/var/lib/cydia/metadata.plist" atomically:YES] == YES); | |
36bb2ca2 JF |
4095 | |
4096 | [book_ reloadData]; | |
4097 | /*[hud show:NO]; | |
4098 | [hud removeFromSuperview];*/ | |
b4d89997 JF |
4099 | } |
4100 | ||
36bb2ca2 JF |
4101 | - (void) reloadData { |
4102 | @synchronized (self) { | |
4103 | if (confirm_ == nil) | |
4104 | [self _reloadData]; | |
4105 | } | |
b4d89997 JF |
4106 | } |
4107 | ||
4108 | - (void) resolve { | |
4109 | pkgProblemResolver *resolver = [database_ resolver]; | |
4110 | ||
4111 | resolver->InstallProtect(); | |
4112 | if (!resolver->Resolve(true)) | |
4113 | _error->Discard(); | |
2367a917 JF |
4114 | } |
4115 | ||
4116 | - (void) perform { | |
8fe19fc1 | 4117 | [database_ prepare]; |
49048579 JF |
4118 | |
4119 | if ([database_ cache]->BrokenCount() == 0) | |
4120 | confirm_ = [[ConfirmationView alloc] initWithView:underlay_ database:database_ delegate:self]; | |
4121 | else { | |
4122 | NSMutableArray *broken = [NSMutableArray arrayWithCapacity:16]; | |
4123 | NSArray *packages = [database_ packages]; | |
4124 | ||
4125 | for (size_t i(0); i != [packages count]; ++i) { | |
4126 | Package *package = [packages objectAtIndex:i]; | |
4127 | if ([package broken]) | |
4128 | [broken addObject:[package name]]; | |
4129 | } | |
4130 | ||
4131 | UIAlertSheet *sheet = [[[UIAlertSheet alloc] | |
4132 | initWithTitle:[NSString stringWithFormat:@"%d Broken Packages", [database_ cache]->BrokenCount()] | |
4133 | buttons:[NSArray arrayWithObjects:@"Okay", nil] | |
4134 | defaultButtonIndex:0 | |
4135 | delegate:self | |
4136 | context:self | |
4137 | ] autorelease]; | |
4138 | ||
4139 | [sheet setBodyText:[NSString stringWithFormat:@"The following packages have unmet dependencies:\n\n%@", [broken componentsJoinedByString:@"\n"]]]; | |
4140 | [sheet popupAlertAnimated:YES]; | |
4141 | ||
36bb2ca2 | 4142 | [self _reloadData]; |
49048579 | 4143 | } |
3178d79b JF |
4144 | } |
4145 | ||
36bb2ca2 JF |
4146 | - (void) installPackage:(Package *)package { |
4147 | @synchronized (self) { | |
4148 | [package install]; | |
4149 | [self resolve]; | |
4150 | [self perform]; | |
4151 | } | |
4152 | } | |
4153 | ||
4154 | - (void) removePackage:(Package *)package { | |
4155 | @synchronized (self) { | |
4156 | [package remove]; | |
4157 | [self resolve]; | |
4158 | [self perform]; | |
4159 | } | |
4160 | } | |
4161 | ||
4162 | - (void) distUpgrade { | |
4163 | @synchronized (self) { | |
4164 | [database_ upgrade]; | |
4165 | [self perform]; | |
4166 | } | |
b4d89997 JF |
4167 | } |
4168 | ||
3178d79b | 4169 | - (void) cancel { |
36bb2ca2 JF |
4170 | @synchronized (self) { |
4171 | [confirm_ release]; | |
4172 | confirm_ = nil; | |
4173 | [self _reloadData]; | |
4174 | } | |
3178d79b JF |
4175 | } |
4176 | ||
4177 | - (void) confirm { | |
4178 | [overlay_ removeFromSuperview]; | |
b4d89997 | 4179 | restart_ = true; |
3178d79b | 4180 | |
2367a917 JF |
4181 | [progress_ |
4182 | detachNewThreadSelector:@selector(perform) | |
4183 | toTarget:database_ | |
4184 | withObject:nil | |
b4d89997 | 4185 | title:@"Running..." |
2367a917 JF |
4186 | ]; |
4187 | } | |
4188 | ||
b31b87cc JF |
4189 | - (void) bootstrap_ { |
4190 | [database_ update]; | |
4191 | [database_ upgrade]; | |
4192 | [database_ prepare]; | |
4193 | [database_ perform]; | |
4194 | } | |
4195 | ||
4196 | - (void) bootstrap { | |
4197 | [progress_ | |
4198 | detachNewThreadSelector:@selector(bootstrap_) | |
4199 | toTarget:self | |
4200 | withObject:nil | |
4201 | title:@"Bootstrap Install..." | |
4202 | ]; | |
4203 | } | |
4204 | ||
2367a917 | 4205 | - (void) progressViewIsComplete:(ProgressView *)progress { |
36bb2ca2 JF |
4206 | @synchronized (self) { |
4207 | [self _reloadData]; | |
4208 | ||
4209 | if (confirm_ != nil) { | |
4210 | [underlay_ addSubview:overlay_]; | |
4211 | [confirm_ removeFromSuperview]; | |
4212 | [confirm_ release]; | |
4213 | confirm_ = nil; | |
4214 | } | |
3178d79b | 4215 | } |
dc5812ec JF |
4216 | } |
4217 | ||
36bb2ca2 JF |
4218 | - (void) alertSheet:(UIAlertSheet *)sheet buttonClicked:(int)button { |
4219 | [sheet dismiss]; | |
4220 | } | |
2367a917 | 4221 | |
36bb2ca2 JF |
4222 | - (void) setPage:(RVPage *)page { |
4223 | [page setDelegate:self]; | |
4224 | [book_ setPage:page]; | |
dc5812ec JF |
4225 | } |
4226 | ||
36bb2ca2 JF |
4227 | - (RVPage *) _setNewsPage { |
4228 | BrowserView *browser = [[[BrowserView alloc] initWithBook:book_ database:database_] autorelease]; | |
4229 | [self setPage:browser]; | |
4230 | [browser loadURL:[NSURL URLWithString:@"http://cydia.saurik.com/"]]; | |
4231 | return browser; | |
2367a917 JF |
4232 | } |
4233 | ||
dc5812ec | 4234 | - (void) buttonBarItemTapped:(id)sender { |
06aa974d | 4235 | unsigned tag = [sender tag]; |
559dec34 JF |
4236 | if (tag == tag_) { |
4237 | [book_ resetViewAnimated:YES]; | |
4238 | return; | |
4239 | } | |
dc5812ec | 4240 | |
06aa974d | 4241 | switch (tag) { |
36bb2ca2 JF |
4242 | case 1: |
4243 | [self _setNewsPage]; | |
4244 | break; | |
4245 | ||
4246 | case 2: | |
4247 | [self setPage:[[[InstallView alloc] initWithBook:book_ database:database_] autorelease]]; | |
4248 | break; | |
4249 | ||
4250 | case 3: | |
4251 | [self setPage:[[[ChangesView alloc] initWithBook:book_ database:database_] autorelease]]; | |
4252 | break; | |
4253 | ||
4254 | case 4: | |
559dec34 | 4255 | [self setPage:[[[ManageView alloc] initWithBook:book_ database:database_] autorelease]]; |
36bb2ca2 JF |
4256 | break; |
4257 | ||
4258 | case 5: | |
4259 | [self setPage:[[[SearchView alloc] initWithBook:book_ database:database_] autorelease]]; | |
4260 | break; | |
dc5812ec JF |
4261 | |
4262 | default: | |
4263 | _assert(false); | |
4264 | } | |
4265 | ||
06aa974d | 4266 | tag_ = tag; |
06aa974d JF |
4267 | } |
4268 | ||
b4d89997 | 4269 | - (void) applicationWillSuspend { |
36bb2ca2 JF |
4270 | [super applicationWillSuspend]; |
4271 | ||
b4d89997 | 4272 | if (restart_) |
ec97ef06 JF |
4273 | if (FW_LEAST(1,1,3)) |
4274 | notify_post("com.apple.language.changed"); | |
4275 | else | |
4276 | system("launchctl stop com.apple.SpringBoard"); | |
b4d89997 JF |
4277 | } |
4278 | ||
dc5812ec JF |
4279 | - (void) applicationDidFinishLaunching:(id)unused { |
4280 | _assert(pkgInitConfig(*_config)); | |
4281 | _assert(pkgInitSystem(*_config, _system)); | |
4282 | ||
3178d79b | 4283 | confirm_ = nil; |
06aa974d | 4284 | tag_ = 1; |
3178d79b | 4285 | |
dc5812ec JF |
4286 | CGRect screenrect = [UIHardware fullScreenApplicationContentRect]; |
4287 | window_ = [[UIWindow alloc] initWithContentRect:screenrect]; | |
4288 | ||
4289 | [window_ orderFront: self]; | |
4290 | [window_ makeKey: self]; | |
4291 | [window_ _setHidden: NO]; | |
4292 | ||
2367a917 | 4293 | progress_ = [[ProgressView alloc] initWithFrame:[window_ bounds] delegate:self]; |
dc5812ec JF |
4294 | [window_ setContentView:progress_]; |
4295 | ||
3178d79b JF |
4296 | underlay_ = [[UIView alloc] initWithFrame:[progress_ bounds]]; |
4297 | [progress_ setContentView:underlay_]; | |
4298 | ||
4299 | overlay_ = [[UIView alloc] initWithFrame:[underlay_ bounds]]; | |
b31b87cc JF |
4300 | |
4301 | if (!bootstrap_) | |
4302 | [underlay_ addSubview:overlay_]; | |
dc5812ec | 4303 | |
36bb2ca2 JF |
4304 | database_ = [[Database alloc] init]; |
4305 | [database_ setDelegate:progress_]; | |
06aa974d | 4306 | |
36bb2ca2 JF |
4307 | book_ = [[CYBook alloc] initWithFrame:CGRectMake( |
4308 | 0, 0, screenrect.size.width, screenrect.size.height - 48 | |
4309 | ) database:database_]; | |
dc5812ec | 4310 | |
36bb2ca2 | 4311 | [book_ setDelegate:self]; |
dc5812ec | 4312 | |
36bb2ca2 | 4313 | [overlay_ addSubview:book_]; |
b19871dd | 4314 | |
dc5812ec JF |
4315 | NSArray *buttonitems = [NSArray arrayWithObjects: |
4316 | [NSDictionary dictionaryWithObjectsAndKeys: | |
4317 | @"buttonBarItemTapped:", kUIButtonBarButtonAction, | |
36bb2ca2 JF |
4318 | @"news-up.png", kUIButtonBarButtonInfo, |
4319 | @"news-dn.png", kUIButtonBarButtonSelectedInfo, | |
dc5812ec JF |
4320 | [NSNumber numberWithInt:1], kUIButtonBarButtonTag, |
4321 | self, kUIButtonBarButtonTarget, | |
36bb2ca2 | 4322 | @"News", kUIButtonBarButtonTitle, |
dc5812ec JF |
4323 | @"0", kUIButtonBarButtonType, |
4324 | nil], | |
4325 | ||
4326 | [NSDictionary dictionaryWithObjectsAndKeys: | |
4327 | @"buttonBarItemTapped:", kUIButtonBarButtonAction, | |
4328 | @"install-up.png", kUIButtonBarButtonInfo, | |
4329 | @"install-dn.png", kUIButtonBarButtonSelectedInfo, | |
4330 | [NSNumber numberWithInt:2], kUIButtonBarButtonTag, | |
4331 | self, kUIButtonBarButtonTarget, | |
4332 | @"Install", kUIButtonBarButtonTitle, | |
4333 | @"0", kUIButtonBarButtonType, | |
4334 | nil], | |
4335 | ||
4336 | [NSDictionary dictionaryWithObjectsAndKeys: | |
4337 | @"buttonBarItemTapped:", kUIButtonBarButtonAction, | |
b4d89997 JF |
4338 | @"changes-up.png", kUIButtonBarButtonInfo, |
4339 | @"changes-dn.png", kUIButtonBarButtonSelectedInfo, | |
dc5812ec JF |
4340 | [NSNumber numberWithInt:3], kUIButtonBarButtonTag, |
4341 | self, kUIButtonBarButtonTarget, | |
b4d89997 | 4342 | @"Changes", kUIButtonBarButtonTitle, |
dc5812ec JF |
4343 | @"0", kUIButtonBarButtonType, |
4344 | nil], | |
4345 | ||
4346 | [NSDictionary dictionaryWithObjectsAndKeys: | |
4347 | @"buttonBarItemTapped:", kUIButtonBarButtonAction, | |
b4d89997 JF |
4348 | @"manage-up.png", kUIButtonBarButtonInfo, |
4349 | @"manage-dn.png", kUIButtonBarButtonSelectedInfo, | |
dc5812ec JF |
4350 | [NSNumber numberWithInt:4], kUIButtonBarButtonTag, |
4351 | self, kUIButtonBarButtonTarget, | |
36bb2ca2 | 4352 | @"Manage", kUIButtonBarButtonTitle, |
dc5812ec JF |
4353 | @"0", kUIButtonBarButtonType, |
4354 | nil], | |
4355 | ||
4356 | [NSDictionary dictionaryWithObjectsAndKeys: | |
4357 | @"buttonBarItemTapped:", kUIButtonBarButtonAction, | |
b4d89997 JF |
4358 | @"search-up.png", kUIButtonBarButtonInfo, |
4359 | @"search-dn.png", kUIButtonBarButtonSelectedInfo, | |
dc5812ec JF |
4360 | [NSNumber numberWithInt:5], kUIButtonBarButtonTag, |
4361 | self, kUIButtonBarButtonTarget, | |
b4d89997 | 4362 | @"Search", kUIButtonBarButtonTitle, |
dc5812ec JF |
4363 | @"0", kUIButtonBarButtonType, |
4364 | nil], | |
4365 | nil]; | |
4366 | ||
2367a917 | 4367 | buttonbar_ = [[UIButtonBar alloc] |
3178d79b | 4368 | initInView:overlay_ |
dc5812ec JF |
4369 | withFrame:CGRectMake( |
4370 | 0, screenrect.size.height - 48, | |
4371 | screenrect.size.width, 48 | |
4372 | ) | |
4373 | withItemList:buttonitems | |
4374 | ]; | |
4375 | ||
2367a917 JF |
4376 | [buttonbar_ setDelegate:self]; |
4377 | [buttonbar_ setBarStyle:1]; | |
4378 | [buttonbar_ setButtonBarTrackingMode:2]; | |
dc5812ec JF |
4379 | |
4380 | int buttons[5] = {1, 2, 3, 4, 5}; | |
2367a917 JF |
4381 | [buttonbar_ registerButtonGroup:0 withButtons:buttons withCount:5]; |
4382 | [buttonbar_ showButtonGroup:0 withDuration:0]; | |
dc5812ec JF |
4383 | |
4384 | for (int i = 0; i != 5; ++i) | |
2367a917 | 4385 | [[buttonbar_ viewWithTag:(i + 1)] setFrame:CGRectMake( |
dc5812ec JF |
4386 | i * 64 + 2, 1, 60, 48 |
4387 | )]; | |
4388 | ||
2367a917 | 4389 | [buttonbar_ showSelectionForButton:1]; |
3178d79b | 4390 | [overlay_ addSubview:buttonbar_]; |
dc5812ec | 4391 | |
b4d89997 | 4392 | [UIKeyboard initImplementationNow]; |
b4d89997 JF |
4393 | CGSize keysize = [UIKeyboard defaultSize]; |
4394 | CGRect keyrect = {{0, [overlay_ bounds].size.height - keysize.height}, keysize}; | |
4395 | keyboard_ = [[UIKeyboard alloc] initWithFrame:keyrect]; | |
d73cede2 | 4396 | [[UIKeyboardImpl sharedInstance] setSoundsEnabled:(Sounds_Keyboard_ ? YES : NO)]; |
b4d89997 | 4397 | |
36bb2ca2 JF |
4398 | [self reloadData]; |
4399 | [book_ update]; | |
b31b87cc JF |
4400 | |
4401 | [progress_ resetView]; | |
4402 | ||
4403 | if (bootstrap_) | |
4404 | [self bootstrap]; | |
36bb2ca2 JF |
4405 | else |
4406 | [self _setNewsPage]; | |
b4d89997 JF |
4407 | } |
4408 | ||
4409 | - (void) showKeyboard:(BOOL)show { | |
4410 | if (show) | |
4411 | [overlay_ addSubview:keyboard_]; | |
4412 | else | |
4413 | [keyboard_ removeFromSuperview]; | |
dc5812ec JF |
4414 | } |
4415 | ||
36bb2ca2 JF |
4416 | - (void) slideUp:(UIAlertSheet *)alert { |
4417 | [alert presentSheetFromButtonBar:buttonbar_]; | |
4418 | } | |
4419 | ||
dc5812ec JF |
4420 | @end |
4421 | ||
b4d89997 JF |
4422 | void AddPreferences(NSString *plist) { |
4423 | NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; | |
4424 | ||
4425 | NSMutableDictionary *settings = [[[NSMutableDictionary alloc] initWithContentsOfFile:plist] autorelease]; | |
4426 | _assert(settings != NULL); | |
4427 | NSMutableArray *items = [settings objectForKey:@"items"]; | |
4428 | ||
4429 | bool cydia(false); | |
4430 | ||
4431 | for (size_t i(0); i != [items count]; ++i) { | |
4432 | NSMutableDictionary *item([items objectAtIndex:i]); | |
4433 | NSString *label = [item objectForKey:@"label"]; | |
4434 | if (label != nil && [label isEqualToString:@"Cydia"]) { | |
4435 | cydia = true; | |
4436 | break; | |
4437 | } | |
4438 | } | |
4439 | ||
4440 | if (!cydia) { | |
4441 | for (size_t i(0); i != [items count]; ++i) { | |
4442 | NSDictionary *item([items objectAtIndex:i]); | |
4443 | NSString *label = [item objectForKey:@"label"]; | |
4444 | if (label != nil && [label isEqualToString:@"General"]) { | |
4445 | [items insertObject:[NSDictionary dictionaryWithObjectsAndKeys: | |
4446 | @"CydiaSettings", @"bundle", | |
4447 | @"PSLinkCell", @"cell", | |
4448 | [NSNumber numberWithBool:YES], @"hasIcon", | |
4449 | [NSNumber numberWithBool:YES], @"isController", | |
4450 | @"Cydia", @"label", | |
4451 | nil] atIndex:(i + 1)]; | |
4452 | ||
4453 | break; | |
4454 | } | |
4455 | } | |
4456 | ||
4457 | _assert([settings writeToFile:plist atomically:YES] == YES); | |
4458 | } | |
4459 | ||
4460 | [pool release]; | |
4461 | } | |
4462 | ||
4463 | /*IMP alloc_; | |
4464 | id Alloc_(id self, SEL selector) { | |
4465 | id object = alloc_(self, selector); | |
4466 | fprintf(stderr, "[%s]A-%p\n", self->isa->name, object); | |
4467 | return object; | |
4468 | }*/ | |
4469 | ||
36bb2ca2 JF |
4470 | /*IMP dealloc_; |
4471 | id Dealloc_(id self, SEL selector) { | |
4472 | id object = dealloc_(self, selector); | |
4473 | fprintf(stderr, "[%s]D-%p\n", self->isa->name, object); | |
4474 | return object; | |
4475 | }*/ | |
b4d89997 | 4476 | |
36bb2ca2 | 4477 | int main(int argc, char *argv[]) { |
d73cede2 JF |
4478 | NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; |
4479 | ||
b31b87cc JF |
4480 | bootstrap_ = argc > 1 && strcmp(argv[1], "--bootstrap") == 0; |
4481 | ||
d73cede2 JF |
4482 | Home_ = NSHomeDirectory(); |
4483 | ||
4484 | { | |
4485 | NSString *plist = [Home_ stringByAppendingString:@"/Library/Preferences/com.apple.preferences.sounds.plist"]; | |
4486 | if (NSDictionary *sounds = [NSDictionary dictionaryWithContentsOfFile:plist]) | |
4487 | if (NSNumber *keyboard = [sounds objectForKey:@"keyboard"]) | |
4488 | Sounds_Keyboard_ = [keyboard boolValue]; | |
4489 | } | |
4490 | ||
b4d89997 JF |
4491 | setuid(0); |
4492 | setgid(0); | |
4493 | ||
4494 | /*Method alloc = class_getClassMethod([NSObject class], @selector(alloc)); | |
4495 | alloc_ = alloc->method_imp; | |
4496 | alloc->method_imp = (IMP) &Alloc_;*/ | |
4497 | ||
36bb2ca2 JF |
4498 | /*Method dealloc = class_getClassMethod([NSObject class], @selector(dealloc)); |
4499 | dealloc_ = dealloc->method_imp; | |
4500 | dealloc->method_imp = (IMP) &Dealloc_;*/ | |
4501 | ||
2a8d9add JF |
4502 | if (NSDictionary *sysver = [NSDictionary dictionaryWithContentsOfFile:@"/System/Library/CoreServices/SystemVersion.plist"]) { |
4503 | if (NSString *prover = [sysver valueForKey:@"ProductVersion"]) { | |
5f6bff8c | 4504 | Firmware_ = strdup([prover UTF8String]); |
2a8d9add JF |
4505 | NSArray *versions = [prover componentsSeparatedByString:@"."]; |
4506 | int count = [versions count]; | |
4507 | Major_ = count > 0 ? [[versions objectAtIndex:0] intValue] : 0; | |
51a1ffdf JF |
4508 | Minor_ = count > 1 ? [[versions objectAtIndex:1] intValue] : 0; |
4509 | BugFix_ = count > 2 ? [[versions objectAtIndex:2] intValue] : 0; | |
2a8d9add JF |
4510 | } |
4511 | } | |
4512 | ||
3178d79b JF |
4513 | size_t size; |
4514 | sysctlbyname("hw.machine", NULL, &size, NULL, 0); | |
4515 | char *machine = new char[size]; | |
4516 | sysctlbyname("hw.machine", machine, &size, NULL, 0); | |
4517 | Machine_ = machine; | |
4518 | ||
4519 | if (CFMutableDictionaryRef dict = IOServiceMatching("IOPlatformExpertDevice")) | |
4520 | if (io_service_t service = IOServiceGetMatchingService(kIOMasterPortDefault, dict)) { | |
4521 | if (CFTypeRef serial = IORegistryEntryCreateCFProperty(service, CFSTR(kIOPlatformSerialNumberKey), kCFAllocatorDefault, 0)) { | |
4522 | SerialNumber_ = strdup(CFStringGetCStringPtr((CFStringRef) serial, CFStringGetSystemEncoding())); | |
4523 | CFRelease(serial); | |
4524 | } | |
4525 | ||
4526 | IOObjectRelease(service); | |
4527 | } | |
4528 | ||
99364ec4 JF |
4529 | /*AddPreferences(@"/Applications/Preferences.app/Settings-iPhone.plist"); |
4530 | AddPreferences(@"/Applications/Preferences.app/Settings-iPod.plist");*/ | |
b4d89997 JF |
4531 | |
4532 | if ((Metadata_ = [[NSMutableDictionary alloc] initWithContentsOfFile:@"/var/lib/cydia/metadata.plist"]) == NULL) | |
4533 | Metadata_ = [[NSMutableDictionary alloc] initWithCapacity:2]; | |
4534 | else | |
4535 | Packages_ = [Metadata_ objectForKey:@"Packages"]; | |
4536 | ||
68a238ec | 4537 | setenv("CYDIA", "", _not(int)); |
26c2dd8c JF |
4538 | if (access("/User", F_OK) != 0) |
4539 | system("/usr/libexec/cydia/firmware.sh"); | |
9e98e020 JF |
4540 | system("dpkg --configure -a"); |
4541 | ||
36bb2ca2 JF |
4542 | space_ = CGColorSpaceCreateDeviceRGB(); |
4543 | ||
4544 | Black_.Set(space_, 0.0, 0.0, 0.0, 1.0); | |
4545 | Clear_.Set(space_, 0.0, 0.0, 0.0, 0.0); | |
4546 | Red_.Set(space_, 1.0, 0.0, 0.0, 1.0); | |
4547 | White_.Set(space_, 1.0, 1.0, 1.0, 1.0); | |
4548 | ||
4549 | int value = UIApplicationMain(argc, argv, [Cydia class]); | |
4550 | ||
4551 | CGColorSpaceRelease(space_); | |
4552 | ||
dc5812ec | 4553 | [pool release]; |
36bb2ca2 | 4554 | return value; |
dc5812ec | 4555 | } |