void Print() {
if (total_ != 0)
- std::cerr << std::setw(5) << count_ << ", " << std::setw(7) << total_ << " : " << name_ << std::endl;
+ std::cerr << std::setw(7) << count_ << ", " << std::setw(7) << total_ << " : " << name_ << std::endl;
total_ = 0;
count_ = 0;
}
#define ForRelease 1
#define TraceLogging (1 && !ForRelease)
-#define HistogramInsertionSort (!ForRelease ? 0 : 0)
+#define HistogramInsertionSort (0 && !ForRelease)
#define ProfileTimes (0 && !ForRelease)
#define ForSaurik (0 && !ForRelease)
#define LogBrowser (0 && !ForRelease)
base_.set(pool, file);
pkgAcquire acquire;
+ _profile(Source$setMetaIndex$GetIndexes)
dindex->GetIndexes(&acquire, true);
+ _end
+ _profile(Source$setMetaIndex$DescURI)
for (pkgAcquire::ItemIterator item(acquire.ItemsBegin()); item != acquire.ItemsEnd(); item++) {
std::string file((*item)->DescURI());
files_.insert(file);
files_.insert(file + ".gz");
files_.insert(file + "Index");
}
+ _end
FileFd fd;
if (!fd.Open(dindex->MetaIndexFile("Release"), FileFd::ReadOnly))
database_ = database;
index_ = index;
+ _profile(Source$initWithMetaIndex$setMetaIndex)
[self setMetaIndex:index inPool:pool];
+ _end
} return self;
}
@interface Package : NSObject {
uint32_t era_ : 25;
- uint32_t role_ : 3;
+ @public uint32_t role_ : 3;
uint32_t essential_ : 1;
uint32_t obsolete_ : 1;
uint32_t ignored_ : 1;
CYString latest_;
CYString installed_;
+ time_t updated_;
const char *section_;
_transient NSString *section$_;
- (void) install;
- (void) remove;
-- (bool) isUnfilteredAndSearchedForBy:(NSArray *)query;
-- (bool) isUnfilteredAndSelectedForBy:(NSString *)search;
-- (bool) isInstalledAndUnfiltered:(NSNumber *)number;
-- (bool) isVisibleInSection:(NSString *)section source:(Source *)source;
-- (bool) isVisibleInSource:(Source *)source;
-
@end
uint32_t PackageChangesRadix(Package *self, void *) {
_profile(Package$initWithVersion$Metadata)
const char *mixed(iterator.Name());
size_t size(strlen(mixed));
- char lower[size + 1];
+ static const size_t prefix(sizeof("/var/lib/dpkg/info/") - 1);
+ char lower[prefix + size + 5 + 1];
for (size_t i(0); i != size; ++i)
- lower[i] = mixed[i] | 0x20;
- lower[size] = '\0';
+ lower[prefix + i] = mixed[i] | 0x20;
+
+ if (!installed_.empty()) {
+ memcpy(lower, "/var/lib/dpkg/info/", prefix);
+ memcpy(lower + prefix + size, ".list", 6);
+ struct stat info;
+ if (stat(lower, &info) != -1)
+ updated_ = info.st_birthtime;
+ }
- PackageValue *metadata(PackageFind(lower, size));
+ PackageValue *metadata(PackageFind(lower + prefix, size));
metadata_ = metadata;
id_.set(NULL, metadata->name_, size);
return source_ == (Source *) [NSNull null] ? nil : source_;
}
+- (uint32_t) updated {
+ return std::numeric_limits<uint32_t>::max() - updated_;
+}
+
- (uint32_t) rank {
return rank_;
}
cache->MarkDelete(iterator_, true);
} }
-- (bool) isUnfilteredAndSearchedForBy:(NSArray *)query {
- _profile(Package$isUnfilteredAndSearchedForBy)
- bool value(true);
-
- _profile(Package$isUnfilteredAndSearchedForBy$Unfiltered)
- value &= [self unfiltered];
- _end
-
- _profile(Package$isUnfilteredAndSearchedForBy$Match)
- value &= [self matches:query];
- _end
-
- return value;
- _end
-}
-
-- (bool) isUnfilteredAndSelectedForBy:(NSString *)search {
- if ([search length] == 0)
- return false;
-
- _profile(Package$isUnfilteredAndSelectedForBy)
- bool value(true);
-
- _profile(Package$isUnfilteredAndSelectedForBy$Unfiltered)
- value &= [self unfiltered];
- _end
-
- _profile(Package$isUnfilteredAndSelectedForBy$Match)
- value &= [[self name] compare:search options:MatchCompareOptions_ range:NSMakeRange(0, [search length])] == NSOrderedSame;
- _end
-
- return value;
- _end
-}
-
-- (bool) isInstalledAndUnfiltered:(NSNumber *)number {
- return ![self uninstalled] && role_ <= ([number boolValue] ? 1 : 3);
-}
-
-- (bool) isVisibleInSection:(NSString *)name source:(Source *)source {
- NSString *section([self section]);
-
- return (
- name == nil ||
- section == nil && [name length] == 0 ||
- [name isEqualToString:section]
- ) && (
- source == nil ||
- [self source] == source
- ) && [self visible];
-}
-
-- (bool) isVisibleInSource:(Source *)source {
- return [self source] == source && [self visible];
-}
-
@end
/* }}} */
/* Section Class {{{ */
NSString *title(UCLocalize("DATABASE"));
list_ = new pkgSourceList();
+ _profile(reloadDataWithInvocation$ReadMainList)
if ([self popErrorWithTitle:title forOperation:list_->ReadMainList()])
return;
+ _end
+ _profile(reloadDataWithInvocation$Source$initWithMetaIndex)
for (pkgSourceList::const_iterator source = list_->begin(); source != list_->end(); ++source) {
Source *object([[[Source alloc] initWithMetaIndex:*source forDatabase:self inPool:pool_] autorelease]);
[sourceList_ addObject:object];
}
+ _end
_trace();
OpProgress progress;
+ bool opened;
open:
- if (!cache_.Open(progress, true)) {
+ _profile(reloadDataWithInvocation$pkgCacheFile)
+ opened = cache_.Open(progress, true);
+ _end
+ if (!opened) {
// XXX: what if there are errors, but Open() == true? this should be merged with popError:
while (!_error->empty()) {
std::string error;
return;
}
+ _profile(reloadDataWithInvocation$pkgApplyStatus)
if ([self popErrorWithTitle:title forOperation:pkgApplyStatus(cache_)])
return;
+ _end
if (cache_->BrokenCount() != 0) {
+ _profile(pkgApplyStatus$pkgFixBroken)
if ([self popErrorWithTitle:title forOperation:pkgFixBroken(cache_)])
return;
+ _end
if (cache_->BrokenCount() != 0) {
[delegate_ addProgressEventOnMainThread:[CydiaProgressEvent eventWithMessage:UCLocalize("STILL_BROKEN_EX") ofType:kCydiaProgressEventTypeError] forTask:title];
return;
}
+ _profile(pkgApplyStatus$pkgMinimizeUpgrade)
if ([self popErrorWithTitle:title forOperation:pkgMinimizeUpgrade(cache_)])
return;
+ _end
}
for (Source *object in (id) sourceList_) {
packages.reserve(std::max(10000U, [packages_ count] + 1000));
packages_ = nil;*/
- _trace();
-
+ _profile(reloadDataWithInvocation$packageWithIterator)
for (pkgCache::PkgIterator iterator = cache_->PkgBegin(); !iterator.end(); ++iterator)
if (Package *package = [Package packageWithIterator:iterator withZone:zone_ inPool:pool_ database:self])
//packages.push_back(package);
CFArrayAppendValue(packages_, CFRetain(package));
+ _end
- _trace();
/*if (packages.empty())
packages_ = [[NSArray alloc] init];
packages_ = [[NSArray alloc] initWithObjects:&packages.front() count:packages.size()];
_trace();*/
- [(NSMutableArray *) packages_ radixSortUsingFunction:reinterpret_cast<MenesRadixSortFunction>(&PackagePrefixRadix) withContext:reinterpret_cast<void *>(16)];
+ _profile(reloadDataWithInvocation$radix$8)
+ [(NSMutableArray *) packages_ radixSortUsingFunction:reinterpret_cast<MenesRadixSortFunction>(&PackagePrefixRadix) withContext:reinterpret_cast<void *>(8)];
+ _end
+
+ _profile(reloadDataWithInvocation$radix$4)
[(NSMutableArray *) packages_ radixSortUsingFunction:reinterpret_cast<MenesRadixSortFunction>(&PackagePrefixRadix) withContext:reinterpret_cast<void *>(4)];
- [(NSMutableArray *) packages_ radixSortUsingFunction:reinterpret_cast<MenesRadixSortFunction>(&PackagePrefixRadix) withContext:reinterpret_cast<void *>(0)];
+ _end
- /*_trace();
- PrintTimes();
- _trace();*/
+ _profile(reloadDataWithInvocation$radix$0)
+ [(NSMutableArray *) packages_ radixSortUsingFunction:reinterpret_cast<MenesRadixSortFunction>(&PackagePrefixRadix) withContext:reinterpret_cast<void *>(0)];
+ _end
- _trace();
+ _profile(reloadDataWithInvocation$insertion)
+ CFArrayInsertionSortValues(packages_, CFRangeMake(0, CFArrayGetCount(packages_)), reinterpret_cast<CFComparatorFunction>(&PackageNameCompare), NULL);
+ _end
- /*if (!packages.empty())
- CFQSortArray(&packages.front(), packages.size(), sizeof(packages.front()), reinterpret_cast<CFComparatorFunction>(&PackageNameCompare_), NULL);*/
- //std::sort(packages.begin(), packages.end(), PackageNameOrdering());
+ /*_profile(reloadDataWithInvocation$CFQSortArray)
+ CFQSortArray(&packages.front(), packages.size(), sizeof(packages.front()), reinterpret_cast<CFComparatorFunction>(&PackageNameCompare_), NULL);
+ _end*/
- //CFArraySortValues((CFMutableArrayRef) packages_, CFRangeMake(0, [packages_ count]), reinterpret_cast<CFComparatorFunction>(&PackageNameCompare), NULL);
+ /*_profile(reloadDataWithInvocation$stdsort)
+ std::sort(packages.begin(), packages.end(), PackageNameOrdering());
+ _end*/
- CFArrayInsertionSortValues(packages_, CFRangeMake(0, CFArrayGetCount(packages_)), reinterpret_cast<CFComparatorFunction>(&PackageNameCompare), NULL);
+ /*_profile(reloadDataWithInvocation$CFArraySortValues)
+ CFArraySortValues((CFMutableArrayRef) packages_, CFRangeMake(0, [packages_ count]), reinterpret_cast<CFComparatorFunction>(&PackageNameCompare), NULL);
+ _end*/
- //[packages_ sortUsingFunction:reinterpret_cast<NSComparisonResult (*)(id, id, void *)>(&PackageNameCompare) context:NULL];
+ /*_profile(reloadDataWithInvocation$sortUsingFunction)
+ [packages_ sortUsingFunction:reinterpret_cast<NSComparisonResult (*)(id, id, void *)>(&PackageNameCompare) context:NULL];
+ _end*/
- _trace();
size_t count(CFArrayGetCount(packages_));
MetaFile_->active_ = count;
-
for (size_t index(0); index != count; ++index)
[(Package *) CFArrayGetValueAtIndex(packages_, index) setIndex:index];
-
- _trace();
}
} }
_transient Database *database_;
unsigned era_;
_H<NSArray> packages_;
- _H<NSMutableArray> sections_;
+ _H<NSArray> sections_;
_H<UITableView, 2> list_;
_H<NSMutableArray> index_;
- _H<NSMutableDictionary> indices_;
_H<NSString> title_;
unsigned reloading_;
}
- (void) resetCursor;
- (void) clearData;
+- (NSArray *) sectionsForPackages:(NSMutableArray *)packages;
+
@end
@implementation PackageListController
packages_ = nil;
sections_ = nil;
index_ = nil;
- indices_ = nil;
[super releaseSubviews];
}
return;
}
- NSArray *packages;
+ NSMutableArray *packages;
reload:
if ([self shouldYield]) {
reloading_ = 0;
packages_ = packages;
+ sections_ = [self sectionsForPackages:packages];
- indices_ = [NSMutableDictionary dictionaryWithCapacity:32];
- sections_ = [NSMutableArray arrayWithCapacity:16];
+ [self updateHeight];
+
+ _profile(PackageTable$reloadData$List)
+ [(UITableView *) list_ setDataSource:self];
+ [list_ reloadData];
+ _end
+}
+
+ PrintTimes();
+}
+
+- (NSArray *) sectionsForPackages:(NSMutableArray *)packages {
+ NSMutableArray *sections([NSMutableArray arrayWithCapacity:16]);
Section *section = nil;
int secidx = -1;
_profile(PackageTable$reloadData$Section)
- for (size_t offset(0), end([packages_ count]); offset != end; ++offset) {
+ for (size_t offset(0), end([packages count]); offset != end; ++offset) {
Package *package;
int index;
_profile(PackageTable$reloadData$Section$Package)
- package = [packages_ objectAtIndex:offset];
+ package = [packages objectAtIndex:offset];
index = [collation sectionForObject:package collationStringSelector:@selector(name)];
_end
_end
_profile(PackageTable$reloadData$Section$Add)
- [sections_ addObject:section];
+ [sections addObject:section];
_end
}
bool sectioned([self showsSections]);
if (!sectioned) {
section = [[[Section alloc] initWithName:nil localize:false] autorelease];
- [sections_ addObject:section];
+ [sections addObject:section];
}
_profile(PackageTable$reloadData$Section)
- for (size_t offset(0), end([packages_ count]); offset != end; ++offset) {
+ for (size_t offset(0), end([packages count]); offset != end; ++offset) {
Package *package;
unichar index;
_profile(PackageTable$reloadData$Section$Package)
- package = [packages_ objectAtIndex:offset];
+ package = [packages objectAtIndex:offset];
index = [package index];
_end
_end
[index_ addObject:[section name]];
- //[indices_ setObject:[NSNumber numberForInt:[sections_ count]] forKey:index];
_profile(PackageTable$reloadData$Section$Add)
- [sections_ addObject:section];
+ [sections addObject:section];
_end
}
_end
}
- [self updateHeight];
-
- _profile(PackageTable$reloadData$List)
- [(UITableView *) list_ setDataSource:self];
- [list_ reloadData];
- _end
-} }
+ return sections;
+}
- (void) reloadData {
[super reloadData];
@end
/* }}} */
/* Filtered Package List Controller {{{ */
+typedef Function<bool, Package *> PackageFilter;
+typedef Function<void, NSMutableArray *> PackageSorter;
@interface FilteredPackageListController : PackageListController {
- SEL filter_;
- IMP imp_;
- _H<NSObject> object_;
- _H<NSObject> stuff_;
+ PackageFilter filter_;
+ PackageSorter sorter_;
}
-- (void) setObject:(id)object;
-- (void) setStuff:(id)object;
-- (void) setObject:(id)object andStuff:(id)stuff;
-
-- (void) setObject:(id)object forFilter:(SEL)filter;
-- (void) setObject:(id)object andStuff:(id)stuff forFilter:(SEL)filter;
-
-- (SEL) filter;
-- (void) setFilter:(SEL)filter;
+- (id) initWithDatabase:(Database *)database title:(NSString *)title filter:(PackageFilter)filter;
-- (id) initWithDatabase:(Database *)database title:(NSString *)title filter:(SEL)filter with:(id)object;
+- (void) setFilter:(PackageFilter)filter;
+- (void) setSorter:(PackageSorter)sorter;
@end
@implementation FilteredPackageListController
-- (SEL) filter {
- return filter_;
-}
-
-- (void) setFilter:(SEL)filter {
+- (void) setFilter:(PackageFilter)filter {
@synchronized (self) {
filter_ = filter;
-
- /* XXX: this is an unsafe optimization of doomy hell */
- Method method(class_getInstanceMethod([Package class], filter));
- _assert(method != NULL);
- imp_ = method_getImplementation(method);
- _assert(imp_ != NULL);
-} }
-
-- (void) setObject:(id)object {
-@synchronized (self) {
- object_ = object;
-} }
-
-- (void) setStuff:(id)stuff {
-@synchronized (self) {
- stuff_ = stuff;
} }
-- (void) setObject:(id)object andStuff:(id)stuff {
+- (void) setSorter:(PackageSorter)sorter {
@synchronized (self) {
- object_ = object;
- stuff_ = stuff;
-} }
-
-- (void) setObject:(id)object forFilter:(SEL)filter {
-@synchronized (self) {
- [self setFilter:filter];
- object_ = object;
-} }
-
-- (void) setObject:(id)object andStuff:(id)stuff forFilter:(SEL)filter {
-@synchronized (self) {
- [self setFilter:filter];
- object_ = object;
- stuff_ = stuff;
+ sorter_ = sorter;
} }
- (NSMutableArray *) _reloadPackages {
@synchronized (database_) {
era_ = [database_ era];
- NSArray *packages([database_ packages]);
+ NSArray *packages([database_ packages]);
NSMutableArray *filtered([NSMutableArray arrayWithCapacity:[packages count]]);
- IMP imp;
- SEL filter;
- _H<NSObject> object;
- _H<NSObject> stuff;
+ PackageFilter filter;
+ PackageSorter sorter;
@synchronized (self) {
- imp = imp_;
filter = filter_;
- object = object_;
- stuff = stuff_;
+ sorter = sorter_;
}
_profile(PackageTable$reloadData$Filter)
for (Package *package in packages)
- if ([package valid] && (*reinterpret_cast<bool (*)(id, SEL, id, id)>(imp))(package, filter, object, stuff))
+ if ([package valid] && filter(package))
[filtered addObject:package];
_end
+ if (sorter)
+ sorter(filtered);
return filtered;
} }
-- (id) initWithDatabase:(Database *)database title:(NSString *)title filter:(SEL)filter with:(id)object {
- if ((self = [super initWithDatabase:database title:title]) != nil) {
- [self setFilter:filter];
- object_ = object;
- } return self;
-}
-
-- (id) initWithDatabase:(Database *)database title:(NSString *)title filter:(SEL)filter with:(id)object with:(id)stuff {
+- (id) initWithDatabase:(Database *)database title:(NSString *)title filter:(PackageFilter)filter {
if ((self = [super initWithDatabase:database title:title]) != nil) {
[self setFilter:filter];
- object_ = object;
- stuff_ = stuff;
} return self;
}
else
title = UCLocalize("NO_SECTION");
- if ((self = [super initWithDatabase:database title:title filter:@selector(isVisibleInSection:source:) with:section with:source]) != nil) {
+ if ((self = [super initWithDatabase:database title:title]) != nil) {
key_ = [source key];
section_ = section;
} return self;
}
- (void) reloadData {
- [super setStuff:[database_ sourceWithKey:key_]];
+ Source *source([database_ sourceWithKey:key_]);
+ _H<NSString> name(section_);
+
+ [self setFilter:[=](Package *package) {
+ NSString *section([package section]);
+
+ return (
+ name == nil ||
+ section == nil && [name length] == 0 ||
+ [name isEqualToString:section]
+ ) && (
+ source == nil ||
+ [package source] == source
+ ) && [package visible];
+ }];
+
[super reloadData];
}
/* }}} */
/* Changes Controller {{{ */
-@interface ChangesController : CyteViewController <
- UITableViewDataSource,
- UITableViewDelegate
-> {
- _transient Database *database_;
- unsigned era_;
- _H<NSMutableArray> packages_;
- _H<NSMutableArray> sections_;
- _H<UITableView, 2> list_;
+@interface ChangesController : FilteredPackageListController {
unsigned upgrades_;
}
@implementation ChangesController
-- (NSURL *) navigationURL {
- return [NSURL URLWithString:@"cydia://changes"];
-}
-
-- (void) viewDidAppear:(BOOL)animated {
- [super viewDidAppear:animated];
- [list_ deselectRowAtIndexPath:[list_ indexPathForSelectedRow] animated:animated];
-}
-
-- (NSInteger) numberOfSectionsInTableView:(UITableView *)list {
- NSInteger count([sections_ count]);
- return count == 0 ? 1 : count;
-}
-
-- (NSString *) tableView:(UITableView *)list titleForHeaderInSection:(NSInteger)section {
- if ([sections_ count] == 0)
- return nil;
- return [[sections_ objectAtIndex:section] name];
+- (NSURL *) referrerURL {
+ return [NSURL URLWithString:[NSString stringWithFormat:@"%@/#!/changes/", UI_]];
}
-- (NSInteger) tableView:(UITableView *)list numberOfRowsInSection:(NSInteger)section {
- if ([sections_ count] == 0)
- return 0;
- return [[sections_ objectAtIndex:section] count];
+- (NSURL *) navigationURL {
+ return [NSURL URLWithString:@"cydia://changes"];
}
- (Package *) packageAtIndexPath:(NSIndexPath *)path {
return [[[packages_ objectAtIndex:([section row] + row)] retain] autorelease];
} }
-- (UITableViewCell *) tableView:(UITableView *)table cellForRowAtIndexPath:(NSIndexPath *)path {
- PackageCell *cell((PackageCell *) [table dequeueReusableCellWithIdentifier:@"Package"]);
- if (cell == nil)
- cell = [[[PackageCell alloc] init] autorelease];
-
- Package *package([database_ packageWithName:[[self packageAtIndexPath:path] id]]);
- [cell setPackage:package asSummary:false];
- return cell;
-}
-
-- (NSIndexPath *) tableView:(UITableView *)table willSelectRowAtIndexPath:(NSIndexPath *)path {
- Package *package([self packageAtIndexPath:path]);
- CYPackageController *view([[[CYPackageController alloc] initWithDatabase:database_ forPackage:[package id] withReferrer:[NSString stringWithFormat:@"%@/#!/changes/", UI_]] autorelease]);
- [view setDelegate:delegate_];
- [[self navigationController] pushViewController:view animated:YES];
- return path;
-}
-
- (void) alertView:(UIAlertView *)alert clickedButtonAtIndex:(NSInteger)button {
NSString *context([alert context]);
[[self navigationItem] setRightBarButtonItem:nil animated:YES];
}
-- (void) loadView {
- UIView *view([[[UIView alloc] initWithFrame:[[UIScreen mainScreen] applicationFrame]] autorelease]);
- [view setAutoresizingMask:(UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight)];
- [self setView:view];
-
- list_ = [[[UITableView alloc] initWithFrame:[view bounds] style:UITableViewStylePlain] autorelease];
- [list_ setAutoresizingMask:UIViewAutoresizingFlexibleBoth];
- [list_ setRowHeight:73];
- [(UITableView *) list_ setDataSource:self];
- [list_ setDelegate:self];
- [view addSubview:list_];
+- (bool) shouldYield {
+ return true;
}
-- (void) viewDidLoad {
- [super viewDidLoad];
-
- [[self navigationItem] setTitle:UCLocalize("CHANGES")];
+- (bool) shouldBlock {
+ return true;
}
-- (void) releaseSubviews {
- list_ = nil;
-
- packages_ = nil;
- sections_ = nil;
+- (void) useFilter {
+@synchronized (self) {
+ [self setFilter:[](Package *package) {
+ return [package upgradableAndEssential:YES] || [package visible];
+ }];
- [super releaseSubviews];
-}
+ [self setSorter:[](NSMutableArray *packages) {
+ [packages radixSortUsingFunction:reinterpret_cast<MenesRadixSortFunction>(&PackageChangesRadix) withContext:NULL];
+ }];
+} }
- (id) initWithDatabase:(Database *)database {
- if ((self = [super init]) != nil) {
- database_ = database;
+ if ((self = [super initWithDatabase:database title:UCLocalize("CHANGES")]) != nil) {
+ [self useFilter];
} return self;
}
-- (NSMutableArray *) _reloadPackages {
-@synchronized (database_) {
- era_ = [database_ era];
- NSArray *packages([database_ packages]);
-
- NSMutableArray *filtered([NSMutableArray arrayWithCapacity:[packages count]]);
-
- _trace();
- _profile(ChangesController$_reloadPackages$Filter)
- for (Package *package in packages)
- if ([package upgradableAndEssential:YES] || [package visible])
- CFArrayAppendValue((CFMutableArrayRef) filtered, package);
- _end
- _trace();
- _profile(ChangesController$_reloadPackages$radixSort)
- [filtered radixSortUsingFunction:reinterpret_cast<MenesRadixSortFunction>(&PackageChangesRadix) withContext:NULL];
- _end
- _trace();
-
- return filtered;
-} }
-
-- (void) _reloadData {
+- (void) reloadData {
[self setLeftBarButtonItem];
+ [super reloadData];
+}
- NSMutableArray *packages;
-
- reload:
- if (true) {
- UIProgressHUD *hud([delegate_ addProgressHUD]);
- [hud setText:UCLocalize("LOADING")];
- //NSLog(@"HUD:%@::%@", delegate_, hud);
- packages = [self yieldToSelector:@selector(_reloadPackages)];
- [delegate_ removeProgressHUD:hud];
- } else {
- packages = [self _reloadPackages];
- }
-
-@synchronized (database_) {
- if (era_ != [database_ era])
- goto reload;
-
- packages_ = packages;
- sections_ = [NSMutableArray arrayWithCapacity:16];
+- (NSArray *) sectionsForPackages:(NSMutableArray *)packages {
+ NSMutableArray *sections([NSMutableArray arrayWithCapacity:16]);
Section *upgradable = [[[Section alloc] initWithName:UCLocalize("AVAILABLE_UPGRADES") localize:NO] autorelease];
Section *ignored = nil;
CFDateFormatterRef formatter(CFDateFormatterCreate(NULL, Locale_, kCFDateFormatterMediumStyle, kCFDateFormatterMediumStyle));
- for (size_t offset = 0, count = [packages_ count]; offset != count; ++offset) {
- Package *package = [packages_ objectAtIndex:offset];
+ for (size_t offset = 0, count = [packages count]; offset != count; ++offset) {
+ Package *package = [packages objectAtIndex:offset];
BOOL uae = [package upgradableAndEssential:YES];
_profile(ChangesController$reloadData$Allocate)
name = [NSString stringWithFormat:UCLocalize("NEW_AT"), name];
section = [[[Section alloc] initWithName:name row:offset localize:NO] autorelease];
- [sections_ addObject:section];
+ [sections addObject:section];
_end
}
CFRelease(formatter);
if (unseens) {
- Section *last = [sections_ lastObject];
+ Section *last = [sections lastObject];
size_t count = [last count];
- [packages_ removeObjectsInRange:NSMakeRange([packages_ count] - count, count)];
- [sections_ removeLastObject];
+ [packages removeObjectsInRange:NSMakeRange([packages count] - count, count)];
+ [sections removeLastObject];
}
if ([ignored count] != 0)
- [sections_ insertObject:ignored atIndex:0];
+ [sections insertObject:ignored atIndex:0];
if (upgrades_ != 0)
- [sections_ insertObject:upgradable atIndex:0];
+ [sections insertObject:upgradable atIndex:0];
[list_ reloadData];
action:@selector(upgradeButtonClicked)
] autorelease]) animated:YES];
- PrintTimes();
-} }
-
-- (void) reloadData {
- [super reloadData];
- [self performSelector:@selector(_reloadData) withObject:nil afterDelay:0];
+ return sections;
}
@end
> {
_H<UISearchBar, 1> search_;
BOOL searchloaded_;
+ bool summary_;
}
- (id) initWithDatabase:(Database *)database query:(NSString *)query;
}
- (void) useSearch {
- [self setObject:[self termsForQuery:[search_ text]] forFilter:@selector(isUnfilteredAndSearchedForBy:)];
+ _H<NSArray> query([self termsForQuery:[search_ text]]);
+ summary_ = false;
+
+@synchronized (self) {
+ [self setFilter:[=](Package *package) {
+ if (![package unfiltered])
+ return false;
+ if (![package matches:query])
+ return false;
+ return true;
+ }];
+
+ [self setSorter:[](NSMutableArray *packages) {
+ [packages radixSortUsingSelector:@selector(rank)];
+ }];
+}
+
[self clearData];
[self reloadData];
}
+- (void) usePrefix:(NSString *)prefix {
+ _H<NSString> query(prefix);
+ summary_ = true;
+
+@synchronized (self) {
+ [self setFilter:[=](Package *package) {
+ if ([query length] == 0)
+ return false;
+ if (![package unfiltered])
+ return false;
+ if ([[package name] compare:query options:MatchCompareOptions_ range:NSMakeRange(0, [query length])] != NSOrderedSame)
+ return false;
+ return true;
+ }];
+
+ [self setSorter:nullptr];
+}
+
+ [self reloadData];
+}
+
- (void) searchBarTextDidBeginEditing:(UISearchBar *)searchBar {
- [self setObject:[search_ text] forFilter:@selector(isUnfilteredAndSelectedForBy:)];
[self clearData];
- [self reloadData];
+ [self usePrefix:[search_ text]];
}
- (void) searchBarButtonClicked:(UISearchBar *)searchBar {
}
- (void) searchBar:(UISearchBar *)searchBar textDidChange:(NSString *)text {
- [self setObject:text forFilter:@selector(isUnfilteredAndSelectedForBy:)];
- [self reloadData];
+ [self usePrefix:text];
}
- (bool) shouldYield {
}
- (bool) shouldBlock {
- return [self filter] == @selector(isUnfilteredAndSearchedForBy:);
+ return !summary_;
}
- (bool) isSummarized {
- return [self filter] == @selector(isUnfilteredAndSelectedForBy:);
+ return summary_;
}
- (bool) showsSections {
return false;
}
-- (NSMutableArray *) _reloadPackages {
- NSMutableArray *packages([super _reloadPackages]);
- if ([self filter] == @selector(isUnfilteredAndSearchedForBy:))
- [packages radixSortUsingSelector:@selector(rank)];
- return packages;
-}
-
- (id) initWithDatabase:(Database *)database query:(NSString *)query {
- if ((self = [super initWithDatabase:database title:UCLocalize("SEARCH") filter:@selector(isUnfilteredAndSearchedForBy:) with:[self termsForQuery:query]])) {
+ if ((self = [super initWithDatabase:database title:UCLocalize("SEARCH")])) {
search_ = [[[UISearchBar alloc] init] autorelease];
+ [search_ setPlaceholder:UCLocalize("SEARCH_EX")];
[search_ setDelegate:self];
+ UITextField *textField;
+ if ([search_ respondsToSelector:@selector(searchField)])
+ textField = [search_ searchField];
+ else
+ textField = MSHookIvar<UITextField *>(search_, "_searchField");
+
+ [textField setAutoresizingMask:UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleTopMargin | UIViewAutoresizingFlexibleBottomMargin];
+ [textField setEnablesReturnKeyAutomatically:NO];
+ [[self navigationItem] setTitleView:textField];
+
if (query != nil)
[search_ setText:query];
+ [self useSearch];
} return self;
}
searchloaded_ = YES;
[search_ setFrame:CGRectMake(0, 0, [[self view] bounds].size.width, 44.0f)];
[search_ layoutSubviews];
- [search_ setPlaceholder:UCLocalize("SEARCH_EX")];
-
- UITextField *textField;
- if ([search_ respondsToSelector:@selector(searchField)])
- textField = [search_ searchField];
- else
- textField = MSHookIvar<UITextField *>(search_, "_searchField");
-
- [textField setAutoresizingMask:UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleTopMargin | UIViewAutoresizingFlexibleBottomMargin];
- [textField setEnablesReturnKeyAutomatically:NO];
- [[self navigationItem] setTitleView:textField];
}
if ([self isSummarized])
}
- (void) reloadData {
- id object([search_ text]);
- if ([self filter] == @selector(isUnfilteredAndSearchedForBy:))
- object = [self termsForQuery:object];
-
- [self setObject:object];
[self resetCursor];
-
[super reloadData];
}
/* Installed Controller {{{ */
@interface InstalledController : FilteredPackageListController {
+ bool sectioned_;
}
- (id) initWithDatabase:(Database *)database;
return [NSURL URLWithString:@"cydia://installed"];
}
+- (bool) showsSections {
+ return sectioned_;
+}
+
+- (void) useUpdated {
+ sectioned_ = false;
+
+@synchronized (self) {
+ [self setFilter:[](Package *package) {
+ return ![package uninstalled] && package->role_ < 7;
+ }];
+
+ [self setSorter:[](NSMutableArray *packages) {
+ [packages radixSortUsingSelector:@selector(updated)];
+ }];
+} }
+
+- (void) useFilter:(UISegmentedControl *)segmented {
+ NSInteger selected([segmented selectedSegmentIndex]);
+ if (selected == 2)
+ return [self useUpdated];
+ bool simple(selected == 0);
+ sectioned_ = true;
+
+@synchronized (self) {
+ [self setFilter:[=](Package *package) {
+ return ![package uninstalled] && package->role_ <= (simple ? 1 : 3);
+ }];
+
+ [self setSorter:nullptr];
+} }
+
- (id) initWithDatabase:(Database *)database {
- if ((self = [super initWithDatabase:database title:UCLocalize("INSTALLED") filter:@selector(isInstalledAndUnfiltered:) with:[NSNumber numberWithBool:YES]]) != nil) {
- UISegmentedControl *segmented([[[UISegmentedControl alloc] initWithItems:[NSArray arrayWithObjects:UCLocalize("SIMPLE"), UCLocalize("EXPERT"), nil]] autorelease]);
+ if ((self = [super initWithDatabase:database title:UCLocalize("INSTALLED")]) != nil) {
+ UISegmentedControl *segmented([[[UISegmentedControl alloc] initWithItems:[NSArray arrayWithObjects:UCLocalize("USER"), UCLocalize("EXPERT"), UCLocalize("RECENT"), nil]] autorelease]);
[segmented setSelectedSegmentIndex:0];
[segmented setSegmentedControlStyle:UISegmentedControlStyleBar];
[[self navigationItem] setTitleView:segmented];
[segmented addTarget:self action:@selector(modeChanged:) forEvents:UIControlEventValueChanged];
+ [self useFilter:segmented];
[self queueStatusDidChange];
} return self;
}
- (void) modeChanged:(UISegmentedControl *)segmented {
- bool simple([segmented selectedSegmentIndex] == 0);
- [self setObject:[NSNumber numberWithBool:simple]];
+ [self useFilter:segmented];
[self reloadData];
}
}
- (void) reloadDataWithInvocation:(NSInvocation *)invocation {
+_profile(reloadDataWithInvocation)
@synchronized (self) {
UIProgressHUD *hud(loaded_ ? [self addProgressHUD] : nil);
if (hud != nil)
[essential_ removeAllObjects];
[broken_ removeAllObjects];
+ _profile(reloadDataWithInvocation$Essential)
NSArray *packages([database_ packages]);
for (Package *package in packages) {
if ([package half])
++changes;
}
}
+ _end
UITabBarItem *changesItem = [[[tabbar_ viewControllers] objectAtIndex:2] tabBarItem];
if (changes != 0) {
if (hud != nil)
[self removeProgressHUD:hud];
-} }
+}
+_end
+
+ PrintTimes();
+}
- (void) updateData {
[self _updateData];
if (emulated_ == nil)
return;
- [window_ addSubview:[tabbar_ view]];
if ([window_ respondsToSelector:@selector(setRootViewController:)])
[window_ setRootViewController:tabbar_];
- [[emulated_ view] removeFromSuperview];
+ else {
+ [window_ addSubview:[tabbar_ view]];
+ [[emulated_ view] removeFromSuperview];
+ }
+
emulated_ = nil;
[window_ setUserInteractionEnabled:YES];
}
[self setupViewControllers];
emulated_ = [[[CydiaLoadingViewController alloc] init] autorelease];
- [window_ addSubview:[emulated_ view]];
if ([window_ respondsToSelector:@selector(setRootViewController:)])
[window_ setRootViewController:emulated_];
+ else
+ [window_ addSubview:[emulated_ view]];
[self performSelector:@selector(loadData) withObject:nil afterDelay:0];
_trace();
[self reloadDataWithInvocation:nil];
[self refreshIfPossible];
- PrintTimes();
-
[self disemulate];
int savedIndex = [[Metadata_ objectForKey:@"InterfaceIndex"] intValue];