]> git.saurik.com Git - cydia.git/blobdiff - MobileCydia.mm
Super-charge the Reload button to actually reload.
[cydia.git] / MobileCydia.mm
index 0a47412b9735783d59f20dfb80ed655083f8d636..b14cda12640c0573612b67af4bf900305514dc77 100644 (file)
@@ -1108,7 +1108,7 @@ NSString *GetLastUpdate() {
 }
 
 bool isSectionVisible(NSString *section) {
-    NSDictionary *metadata([Sections_ objectForKey:section]);
+    NSDictionary *metadata([Sections_ objectForKey:(section ?: @"")]);
     NSNumber *hidden(metadata == nil ? nil : [metadata objectForKey:@"Hidden"]);
     return hidden == nil || ![hidden boolValue];
 }
@@ -1156,6 +1156,7 @@ bool isSectionVisible(NSString *section) {
 - (void) removeProgressHUD:(UIProgressHUD *)hud;
 - (CYViewController *) pageForPackage:(NSString *)name;
 - (void) showActionSheet:(UIActionSheet *)sheet fromItem:(UIBarButtonItem *)item;
+- (void) reloadDataWithInvocation:(NSInvocation *)invocation;
 @end
 
 static id<CydiaDelegate> CydiaApp;
@@ -1335,7 +1336,7 @@ typedef std::map< unsigned long, _H<Source> > SourceMap;
 - (NSArray *) packages;
 - (NSArray *) sources;
 - (Source *) sourceWithKey:(NSString *)key;
-- (void) reloadData;
+- (void) reloadDataWithInvocation:(NSInvocation *)invocation;
 
 - (void) configure;
 - (bool) prepare;
@@ -1808,23 +1809,20 @@ static void PackageImport(const void *key, const void *value, void *context) {
 
 @end
 /* }}} */
-/* CydiaRelation Class {{{ */
-@interface CydiaRelation : NSObject {
-    NSString *relationship_;
+/* CydiaClause Class {{{ */
+@interface CydiaClause : NSObject {
     NSString *package_;
     CydiaOperation *version_;
 }
 
-- (NSString *) relationship;
 - (NSString *) package;
 - (CydiaOperation *) version;
 
 @end
 
-@implementation CydiaRelation
+@implementation CydiaClause
 
 - (void) dealloc {
-    [relationship_ release];
     [package_ release];
     [version_ release];
     [super dealloc];
@@ -1832,7 +1830,6 @@ static void PackageImport(const void *key, const void *value, void *context) {
 
 - (id) initWithIterator:(pkgCache::DepIterator &)dep {
     if ((self = [super init]) != nil) {
-        relationship_ = [[NSString alloc] initWithUTF8String:dep.DepType()];
         package_ = [[NSString alloc] initWithUTF8String:dep.TargetPkg().Name()];
 
         if (const char *version = dep.TargetVer())
@@ -1845,7 +1842,6 @@ static void PackageImport(const void *key, const void *value, void *context) {
 + (NSArray *) _attributeKeys {
     return [NSArray arrayWithObjects:
         @"package",
-        @"relationship",
         @"version",
     nil];
 }
@@ -1858,10 +1854,6 @@ static void PackageImport(const void *key, const void *value, void *context) {
     return ![[self _attributeKeys] containsObject:[NSString stringWithUTF8String:name]] && [super isKeyExcludedFromWebScript:name];
 }
 
-- (NSString *) relationship {
-    return relationship_;
-}
-
 - (NSString *) package {
     return package_;
 }
@@ -1870,6 +1862,74 @@ static void PackageImport(const void *key, const void *value, void *context) {
     return version_;
 }
 
+@end
+/* }}} */
+/* CydiaRelation Class {{{ */
+@interface CydiaRelation : NSObject {
+    NSString *relationship_;
+    NSMutableArray *clauses_;
+}
+
+- (NSString *) relationship;
+- (NSArray *) clauses;
+
+@end
+
+@implementation CydiaRelation
+
+- (void) dealloc {
+    [relationship_ release];
+    [clauses_ release];
+    [super dealloc];
+}
+
+- (id) initWithIterator:(pkgCache::DepIterator &)dep {
+    if ((self = [super init]) != nil) {
+        relationship_ = [[NSString alloc] initWithUTF8String:dep.DepType()];
+        clauses_ = [[NSMutableArray alloc] initWithCapacity:8];
+
+        pkgCache::DepIterator start;
+        pkgCache::DepIterator end;
+        dep.GlobOr(start, end); // ++dep
+
+        _forever {
+            [clauses_ addObject:[[[CydiaClause alloc] initWithIterator:start] autorelease]];
+
+            // yes, seriously. (wtf?)
+            if (start == end)
+                break;
+            ++start;
+        }
+    } return self;
+}
+
++ (NSArray *) _attributeKeys {
+    return [NSArray arrayWithObjects:
+        @"clauses",
+        @"relationship",
+    nil];
+}
+
+- (NSArray *) attributeKeys {
+    return [[self class] _attributeKeys];
+}
+
++ (BOOL) isKeyExcludedFromWebScript:(const char *)name {
+    return ![[self _attributeKeys] containsObject:[NSString stringWithUTF8String:name]] && [super isKeyExcludedFromWebScript:name];
+}
+
+- (NSString *) relationship {
+    return relationship_;
+}
+
+- (NSArray *) clauses {
+    return clauses_;
+}
+
+- (void) addClause:(CydiaClause *)clause {
+    [clauses_ addObject:clause];
+}
+
 @end
 /* }}} */
 /* Package Class {{{ */
@@ -2205,25 +2265,8 @@ struct PackageNameOrdering :
 - (NSArray *) relations {
 @synchronized (database_) {
     NSMutableArray *relations([NSMutableArray arrayWithCapacity:16]);
-
-    for (pkgCache::DepIterator dep(version_.DependsList()); !dep.end(); ++dep) {
-        pkgCache::DepIterator start;
-        pkgCache::DepIterator end;
-        dep.GlobOr(start, end); // ++dep
-
-        NSMutableArray *ors([NSMutableArray arrayWithCapacity:2]);
-        [relations addObject:ors];
-
-        _forever {
-            [ors addObject:[[[CydiaRelation alloc] initWithIterator:start] autorelease]];
-
-            // yes, seriously. (wtf?)
-            if (start == end)
-                break;
-            ++start;
-        }
-    }
-
+    for (pkgCache::DepIterator dep(version_.DependsList()); !dep.end(); ++dep)
+        [relations addObject:[[[CydiaRelation alloc] initWithIterator:dep] autorelease]];
     return relations;
 } }
 
@@ -2618,7 +2661,7 @@ struct PackageNameOrdering :
     _end
 
     _profile(Package$visible$isSectionVisible)
-        if (section != nil && !isSectionVisible(section))
+        if (!isSectionVisible(section))
             return false;
     _end
 
@@ -3396,7 +3439,7 @@ static NSString *Warning_;
     return [self popErrorWithTitle:title] || !success;
 }
 
-- (void) reloadData { CYPoolStart() {
+- (void) reloadDataWithInvocation:(NSInvocation *)invocation { CYPoolStart() {
 @synchronized (self) {
     ++era_;
 
@@ -3432,6 +3475,9 @@ static NSString *Warning_;
     if (chk != -1)
         close(chk);
 
+    if (invocation != nil)
+        [invocation invoke];
+
     NSString *title(UCLocalize("DATABASE"));
 
     _trace();
@@ -4455,6 +4501,13 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
                     if ((cache[end] & pkgDepCache::DepGInstall) != 0)
                         continue;
 
+                    NSMutableArray *clauses([NSMutableArray arrayWithCapacity:4]);
+
+                    [reasons addObject:[NSDictionary dictionaryWithObjectsAndKeys:
+                        [NSString stringWithUTF8String:start.DepType()], @"relationship",
+                        clauses, @"clauses",
+                    nil]];
+
                     _forever {
                         NSString *reason, *installed((NSString *) [WebUndefined undefined]);
 
@@ -4479,8 +4532,7 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
                             [NSString stringWithUTF8String:start.TargetVer()], @"value",
                         nil]);
 
-                        [reasons addObject:[NSDictionary dictionaryWithObjectsAndKeys:
-                            [NSString stringWithUTF8String:start.DepType()], @"relation",
+                        [clauses addObject:[NSDictionary dictionaryWithObjectsAndKeys:
                             [NSString stringWithUTF8String:start.TargetPkg().Name()], @"package",
                             version, @"version",
                             reason, @"reason",
@@ -4514,10 +4566,14 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
                     [NSNull null], @"package",
                     [NSArray arrayWithObjects:
                         [NSDictionary dictionaryWithObjectsAndKeys:
-                            @"Conflicts", @"relation",
-                            name, @"package",
-                            [NSNull null], @"version",
-                            @"installed", @"reason",
+                            @"Conflicts", @"relationship",
+                            [NSArray arrayWithObjects:
+                                [NSDictionary dictionaryWithObjectsAndKeys:
+                                    name, @"package",
+                                    [NSNull null], @"version",
+                                    @"installed", @"reason",
+                                nil],
+                            nil], @"clauses",
                         nil],
                     nil], @"reasons",
                 nil]];
@@ -5772,12 +5828,11 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
         database_ = database;
         buttons_ = [[NSMutableArray alloc] initWithCapacity:4];
         name_ = [[NSString alloc] initWithString:name];
+        [self setURL:[NSURL URLWithString:[NSString stringWithFormat:@"%@/package/#!/%@", UI_, name_]]];
     } return self;
 }
 
 - (void) reloadData {
-    [super reloadData];
-
     if (package_ != nil)
         [package_ autorelease];
     package_ = [database_ packageWithName:name_];
@@ -5820,7 +5875,7 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
         action:@selector(customButtonClicked)
     ];
 
-    [self loadURL:[NSURL URLWithString:[NSString stringWithFormat:@"%@/package/#!/%@", UI_, name_]]];
+    [super reloadData];
 }
 
 - (bool) isLoading {
@@ -7538,22 +7593,29 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
     if (package_ == nil)
         return 0;
 
-    return 1;
+    if ([package_ installed] == nil)
+        return 1;
+    else
+        return 2;
 }
 
 - (NSInteger) tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
     if (package_ == nil)
         return 0;
 
-    return 2;
+    // both sections contain just one item right now.
+    return 1;
 }
 
 - (NSString *) tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section {
-    return UCLocalize("CHANGE_PACKAGE_SETTINGS");
+    return nil;
 }
 
 - (NSString *) tableView:(UITableView *)tableView titleForFooterInSection:(NSInteger)section {
-    return UCLocalize("SHOW_ALL_CHANGES_EX");
+    if (section == 0)
+        return UCLocalize("SHOW_ALL_CHANGES_EX");
+    else
+        return UCLocalize("IGNORE_UPGRADES_EX");
 }
 
 - (void) onSubscribed:(id)control {
@@ -7564,15 +7626,50 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
         [delegate_ updateData];
 }
 
+- (void) _updateIgnored {
+    const char *package([name_ UTF8String]);
+    bool on([ignoredSwitch_ isOn]);
+
+    pid_t pid(ExecFork());
+    if (pid == 0) {
+        FILE *dpkg(popen("dpkg --set-selections", "w"));
+        fwrite(package, strlen(package), 1, dpkg);
+
+        if (on)
+            fwrite(" hold\n", 6, 1, dpkg);
+        else
+            fwrite(" install\n", 9, 1, dpkg);
+
+        pclose(dpkg);
+
+        exit(0);
+        _assert(false);
+    }
+
+    _forever {
+        int status;
+        int result(waitpid(pid, &status, 0));
+
+        if (result != -1) {
+            _assert(result == pid);
+            break;
+        }
+    }
+}
+
 - (void) onIgnored:(id)control {
-    // TODO: set Held state - possibly call out to dpkg, etc.
+    NSInvocation *invocation([NSInvocation invocationWithMethodSignature:[self methodSignatureForSelector:@selector(_updateIgnored)]]);
+    [invocation setTarget:self];
+    [invocation setSelector:@selector(_updateIgnored)];
+
+    [delegate_ reloadDataWithInvocation:invocation];
 }
 
 - (UITableViewCell *) tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
     if (package_ == nil)
         return nil;
 
-    switch ([indexPath row]) {
+    switch ([indexPath section]) {
         case 0: return subscribedCell_;
         case 1: return ignoredCell_;
 
@@ -7598,8 +7695,6 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
     ignoredSwitch_ = [[UISwitch alloc] initWithFrame:CGRectMake(0, 0, 50, 20)];
     [ignoredSwitch_ setAutoresizingMask:UIViewAutoresizingFlexibleLeftMargin];
     [ignoredSwitch_ addTarget:self action:@selector(onIgnored:) forEvents:UIControlEventValueChanged];
-    // Disable this switch, since it only reflects (not modifies) the ignored state.
-    [ignoredSwitch_ setUserInteractionEnabled:NO];
 
     subscribedCell_ = [[UITableViewCell alloc] init];
     [subscribedCell_ setText:UCLocalize("SHOW_ALL_CHANGES")];
@@ -7610,8 +7705,6 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
     [ignoredCell_ setText:UCLocalize("IGNORE_UPGRADES")];
     [ignoredCell_ setAccessoryView:ignoredSwitch_];
     [ignoredCell_ setSelectionStyle:UITableViewCellSelectionStyleNone];
-    // FIXME: Ignored state is not saved.
-    [ignoredCell_ setUserInteractionEnabled:NO];
 }
 
 - (void) viewDidLoad {
@@ -7648,11 +7741,12 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
     if (package_ != nil)
         [package_ autorelease];
     package_ = [database_ packageWithName:name_];
+
     if (package_ != nil) {
-        [package_ retain];
+        package_ = [package_ retain];
         [subscribedSwitch_ setOn:([package_ subscribed] ? 1 : 0) animated:NO];
         [ignoredSwitch_ setOn:([package_ ignored] ? 1 : 0) animated:NO];
-    }
+    } // XXX: what now, G?
 
     [table_ reloadData];
 }
@@ -8760,11 +8854,11 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
     [NSThread detachNewThreadSelector:@selector(_refreshIfPossible) toTarget:self withObject:nil];
 }
 
-- (void) _reloadData {
+- (void) _reloadDataWithInvocation:(NSInvocation *)invocation {
     UIProgressHUD *hud(loaded_ ? [self addProgressHUD] : nil);
     [hud setText:UCLocalize("RELOADING_DATA")];
 
-    [database_ yieldToSelector:@selector(reloadData) withObject:nil];
+    [database_ yieldToSelector:@selector(reloadDataWithInvocation:) withObject:invocation];
 
     if (hud != nil)
         [self removeProgressHUD:hud];
@@ -8846,12 +8940,16 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
     ];
 }
 
-- (void) reloadData {
+- (void) reloadDataWithInvocation:(NSInvocation *)invocation {
     @synchronized (self) {
-        [self _reloadData];
+        [self _reloadDataWithInvocation:invocation];
     }
 }
 
+- (void) reloadData {
+    [self reloadDataWithInvocation:nil];
+}
+
 - (void) resolve {
     pkgProblemResolver *resolver = [database_ resolver];
 
@@ -8932,7 +9030,7 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
 
 - (void) complete {
     @synchronized (self) {
-        [self _reloadData];
+        [self _reloadDataWithInvocation:nil];
     }
 }
 
@@ -9778,10 +9876,15 @@ int main(int argc, char *argv[]) { _pooled
 
     Finishes_ = [NSArray arrayWithObjects:@"return", @"reopen", @"restart", @"reload", @"reboot", nil];
 
-    if (substrate && access("/Library/MobileSubstrate/DynamicLibraries/SimulatedKeyEvents.dylib", F_OK) == 0)
-        dlopen("/Library/MobileSubstrate/DynamicLibraries/SimulatedKeyEvents.dylib", RTLD_LAZY | RTLD_GLOBAL);
-    if (substrate && access("/Applications/WinterBoard.app/WinterBoard.dylib", F_OK) == 0)
-        dlopen("/Applications/WinterBoard.app/WinterBoard.dylib", RTLD_LAZY | RTLD_GLOBAL);
+#define MobileSubstrate_(name) \
+    if (substrate && access("/Library/MobileSubstrate/DynamicLibraries/" #name ".dylib", F_OK) == 0) \
+        dlopen("/Library/MobileSubstrate/DynamicLibraries/" #name ".dylib", RTLD_LAZY | RTLD_GLOBAL);
+
+    MobileSubstrate_(Activator)
+    MobileSubstrate_(libstatusbar)
+    MobileSubstrate_(SimulatedKeyEvents)
+    MobileSubstrate_(WinterBoard)
+
     /*if (substrate && access("/Library/MobileSubstrate/MobileSubstrate.dylib", F_OK) == 0)
         dlopen("/Library/MobileSubstrate/MobileSubstrate.dylib", RTLD_LAZY | RTLD_GLOBAL);*/