how to show a progress bar on file's icon - macos

You know there is a mini progress bar on the file's icon when we copy a file or download file with safari and chrome.
I am wondering how to let it shown in Finder window when I'm copying or download files with my own code.
Could somebody help me?
Thanks a lot.

I got the way by query file/directory attributes myself. It's quit simple.
Get attributes of the file you want to show a progress bar on it's icon
NSDictionary *fileAttr = [[NSFileManager defaultManager] attributesOfItemAtPath:filePath error:nil];
Get extend attributes
NSDictionary *extendAttr = [fileAttr objectForKey:#"NSFileExtendedAttributes"];
Create a Mutable copy of extendAttr and change some value in it
NSMutableDictionary *mutableExtendAttr = [NSMutableDictionary dictionaryWithDictionary:extendAttr];
// create data of progress value
NSData *progressData = [#"0.1" dataUsingEncoding:NSASCIIStringEncoding];
// change it
[mutableExtendAttr setObject:progressData forKey:#"com.apple.progress.fractionCompleted"];
Create a mutable copy of fileAttr
NSMutableDictionary *mutableFileAttr = [NSMutableDictionary dictionaryWithDictionary:fileAttr];
// change extend attr
[mutableFileAttr setObject:[NSDictionary dictionaryWithDictionary:mutableExtendAttr] forKey:extendAttrKey];
// change file/dir create date to the special one
// if not , progress bar will not show
[mutableFileAttr setObject:[NSDate dateWithString:#"1984-01-24 08:00:00 +0000"] forKey:NSFileCreationDate];
// set attribute to file
[[NSFileManager defaultManager] setAttributes:mutableFileAttr ofItemAtPath:filePath error:&error];
Now you'll find it the progress bar showed up.

One starting point would be to use a NSProgressIndicator, then [progressIndicator setIndeterminate:NO];. Your updates/background operation should then not block the main thread. NSProgressIndicator is a bit different for an AppKit widget -- it permits some updates from secondary threads. Of course, updates to the 'current progress' may also be enqueued upon the main thread's run loop.

Related

Menubar just shows applications name - OS X

My applications window is generated programmatically. I have a xib file with a menu in it but I really don't know how to link it correct.
The menu bar is empty, except for the bold application name. I tried a few programmatically solutions to link the existing menu or to create and add a completely new menu, but nothing happened.
Does anybody know why this happens? Could it be that there's code in my project which overrides the menu with the empty menu every time?
Is it possible to alter this kind of menu and add menuitems?
Hope you'd help me.
Cheers
Swift:
let nib = NSNib(nibName: "NameOfXIB", bundle: nil)
nib.instantiateWithOwner(self, topLevelObjects: &array)
Objective-C:
NSArray *array;
NSNib *nib = [[NSNib alloc] initWithNibNamed:#"MainMenu" bundle:nil];
[nib instantiateWithOwner:self topLevelObjects:&array];
In your "array" you have all the top level stuff from XIB.
Hold you objects strongly or they will get released.
Owner is the object where you have IBOUtlets that needs to get linked by instantiation.

Try to set an icon to a file in Cocoa

I try to get a file icon and to set it back to the same file (goal is to have overlay, but I first want to have this one work):
NSImage *img=[[NSWorkspace sharedWorkspace] iconForFile:#"MyFilePath"];
NSLog(#"x=%.f",img.size.width); // Result=32
[[NSWorkspace sharedWorkspace] setIcon:img forFile:#"MyFilePath" options:0];
-> Result is that my file gets a standard Finder icon instead of keeping its own icon. Anything I am doing wrong ?
Try using it like this:
[[NSWorkspace sharedWorkspace]
setIcon: [[NSImage alloc] initWithContentsOfFile:#"MyFilePath"]
forFile: #"MyFilePath"
options: 0];
You need to to load the icon/image into memory first.
EDIT: Answer updated to provide additional information in regards to
the comment below.
"how can I keep the image in memory to "play" with it before reassigning it?"
The NSImage that gets allocated into memory from your specified path can be manipulated in just about any possible way once it's been loaded. You'll want to thoroughly read the NSImage Class Reference to gain a real understanding of what it does and how use it's methods. For this particular scenario you'll want to be able have a named variable assigned from the icon you load.
Only one change needs to happen with the code above to make it work:
NSImage *iconImage = [[NSImage alloc] initWithContentsOfFile:#"MyFilePath"];
[[NSWorkspace sharedWorkspace]
setIcon: iconImage
forFile: #"MyFilePath"
options: 0];
NSLog(#"iconImage: %#",iconImage);
The slight change essentially assigns the variable iconImage from the NSImage icon; everything else stays the same. The NSLog will give you a very quick glimpse at properties associated with iconImage — where you take it from there is really up to your coding ability and creativity.

How to open maps from app and drop an arbitrary pin

I've read several questions about this, but no answer seems to fit. If I want to open maps from my app, with an arbitrary location defined by coordinates and an arbitrary name, to use as a title in a pin dropped in that location, how can I do it? With iOS5 I used the openURL with an url scheme built this way:
maps:q=Arbitrary+name#45.000,45.000
This doesn't work anymore (thus all the apps to be updated!), and I don't seem to find a way to achieve the same behaviour: the name I provide is always used as a search parameter, and if nothing is found the pin won't be dropped. On the other side, any found result seems to override coordinates, so several pin are dropped in another part of the globe.
I am trying even formats such:
http://maps.apple.com/?sll=45.000,45.000&q=Arbitrary+name
Any help?
This can be done by the following way:
CLLocationCoordinate2D coOrdinates = //
MKPlacemark *location = [[MKPlacemark alloc] initWithCoordinate:coOrdinates addressDictionary:nil];
MKMapItem *pinItem = [[MKMapItem alloc] initWithPlacemark:endLocation];
pinItem.name =#"Location";
NSMutableDictionary *launchOptions = [[NSMutableDictionary alloc] init];
[pinItem openInMapsWithLaunchOptions:launchOptions];
[location release];
[launchOptions release];
[pinItem release];

How do I load PersistentDocuments into the same window

I want to open NSPersistentDocuments and load them into the same window one at a time. I'm almost there but missing some steps. Hopefully someone can help me.
I have a few saved documents on the hard drive. On launch my app opens to an untitled NSPersistentDocument and creates a separate NSWindowController. When I press the button to load file 1 off the hard drive the data appears in the fields but two things are wrong that I can see:
1) changing the data doesn't make the document dirty
2) choosing save updates the persistentstore (I know this because when I open the file again I see the changes) but I get an error: +entityForName: could not locate an NSManagedObjectModel for entity name 'Book'
Here's my code which is in the WindowController that was launched initially with the untitled document. This code isn't perfect. For example, I know I should processPendingChanges and save the current doc before I load the new one. This is test code to try to get over this hurdle.
- (IBAction)newBookTwo:(id)sender {
NSDocumentController *dc = [NSDocumentController sharedDocumentController];
NSURL *url = [NSURL fileURLWithPath:[#"~/Desktop/File 2.binary" stringByExpandingTildeInPath]];
NSError *error;
MainWindowDocument *thisDoc = [dc openDocumentWithContentsOfURL:url display:NO error:&error];
[self setDocument:thisDoc];
[self setManagedObjectContext:[thisDoc managedObjectContext]];
}
Thanks!
Assuming you have an entity called "Book" or "book" then the second problem is most likely a typo swapping case. Depending on the entity graph that may be triggering your first problem as well.
Put a break point in there and see if your model is nil.

How do I set the default selection for NSTreeController at startup?

The Background
I've built a source list (similar to iTunes et al.) in my Cocoa app.
I've got an NSOutlineView, with Value
column bound to arrangedObjects.name
key path of an NSTreeController.
The NSTreeController accesses
JGSourceListNode entities in a Core
Data store.
I have three subclasses of
JGSourceListNode - JGProjectNode,
JGGroupNode and JGFolderNode.
I have selectedIndexPaths on NSTreeController bound to an NSArray called selectedIndexPaths in my App Delegate.
On startup, I search for group nodes and if they're not found in the core data store I create them:
if ([allGroupNodes count] == 0) {
JGGroupNode *rootTrainingNode = [JGGroupNode insertInManagedObjectContext:context];
[rootTrainingNode setNodeName:#"TRAIN"];
JGProjectNode *childUntrainedNode = [JGProjectNode insertInManagedObjectContext:context];
[childUntrainedNode setParent:rootTrainingNode];
[childUntrainedNode setNodeName:#"Untrained"];
JGGroupNode *rootBrowsingNode = [JGGroupNode insertInManagedObjectContext:context];
[rootBrowsingNode setNodeName:#"BROWSE"];
JGFolderNode *childFolder = [JGFolderNode insertInManagedObjectContext:context];
[childFolder setNodeName:#"Folder"];
[childFolder setParent:rootBrowsingNode];
[context save:nil];
}
What I Want
When I start the app, I want both top level groups to be expanded and "Untrained" to be highlighted as shown:
My Window http://synapticmishap.co.uk/Window.jpeg
The Problem
I put the following code in the applicationDidFinishLaunching: method of the app delegate:
[sourceListOutlineView expandItem:[sourceListOutlineView itemAtRow:0]];
[sourceListOutlineView expandItem:[sourceListOutlineView itemAtRow:2]];
NSIndexPath *rootIndexPath = [NSIndexPath indexPathWithIndex:0];
NSIndexPath *childIndexPath = [rootIndexPath indexPathByAddingIndex:0];
[self setSelectedIndexPaths:[NSArray arrayWithObject:childIndexPath]];
but the outline view seems to not have been prepared yet, so this code does nothing.
Ideally, eventually I want to save the last selection the user had made and restore this on a restart.
The Question
I'm sure it's possible using some crazy KVO to observe when the NSTreeController or NSOutlineView gets populated then expand the items and change the selection, but that feels clumsy and too much like a work around.
How would I do this elegantly?
Elegantly? This isn't elegant but it's how I'm doing it. I just do it manually. At app quit I write this value to user defaults:
lastSelectedRow = [outlineView selectedRow]
Then at app launch I run this in app did finish launching:
[self performSelector:#selector(selectLastNoteOrCreateDefaultNote) withObject:nil afterDelay:1];
Notice I just use a delay because I noticed the same as you that "the outline view seems to not have been prepared yet". Then in that selector I use this.
[outlineView selectRowIndexes:[NSIndexSet indexSetWithIndex:lastSelectedRow] byExtendingSelection:NO];
It works but better (more elegant) solutions are welcome from me too.

Resources