Trying to use NSManagedObjectModel through NSTreeController and NSBrowser - cocoa

I'm trying to use NSManagedObjectModel through NSTreeController and NSBrowser. I found some simple tutorials on the Net but they don't solve all my problems. Right now I can: add nodes (except in the leaf); to show children's nodes selecting the parent. My model is heterogeneous, all entities are different, but have the same properties: "name"; "children" (except the leaf); "parent (except the root). My model is all generated by the XCode. I don't have entered any code and don't have changed anything, all is generated by the XCode and Interface Builder.
I have 3 questions:
(1) How can I avoid the "children key error" when I reach the leaf entity?
(2) How can I avoid the creation of a children in the column of a parent?
(3) How can I disable the add children button if no one parent is selected?
(Thanks about some help. :D )

With regard to question 1: I have all my nodes implement all methods, but the leaf entities return nil for the children getter method, for example, and the root returns nil for parent.
Unfortunately, I haven't used NSBrowser, I use this technique for NSOutlineView and NSTreeController, so I can't help with questions 2 & 3.

Related

QTableWidget and QGraphicsItem sync selection

I have a QTableWidget with a list of QTableWidgetItems and also a matching number of QGraphicsItems in a different display.
I want their selection to be synchronised where if I select a table widget item, it selects the corresponding QgraphicsItem and vice versa. I already have this data and have it implemented, however it causes some kind of cycle because when
object A (QTableWidgetItem) is selected, it selects object B (QGraphicsItem), then that triggers the object A (QTableWidgetItem) to be selected again, which triggers object B (QGraphicsItem) and so on. How do you avoid this kind of loop, while still having the functionality ?
Thanks :)

Can I add an NSManagedObject to the selected parent object just using Interface Builder and Core Data?

I'm learning Core Data and at the moment just using Interface Builder and the XCode data model (following the Aaron Hillegass Cocoa book examples).
I have an MVC application and core data set up and working within interface builder (no hand-written code yet). I've set up various arraycontrollers, views and buttons to add and remove objects and edit data and determine relationships between objects.
However my object model is strictly hierarchical parent-child (and grandchildren) and each relationship is one-to-many. So when I add a child (or grandchild) I want to automatically assign the parent object currently selected in the main tableView as the parent of the new child object.
Is this possible in interface builder or is this the point where I have to start coding my own methods?
Any pointers on the next step I should be looking to take or how to figure it out myself much appreciated. I'm just a bit stuck and can't find a relevant tutorial or reference.
Perhaps it will help if I describe my document window. It has two tableViews with add/remove buttons. The tableView on the right displays an NSSet of the child objects of the parent objected selected in the tableView on left. I want the add button on the right to add a new object and automatically make it a child of the selected parent object so it appears in the tableView on the right.
At the moment the only methods I can see on the arrayController for the the child objects are add: and remove: but of course they don't connect the new object to the currently selected parent. Do I need to add my own (IBAction) method to the parent object i.e. addChildObject:? Or is there a built in way to add the child automatically within CoreData based on the parent-child relationship?
Problem solved. I found a tutorial (albeit a bit dated) describing exactly what I am trying to do:
https://developer.apple.com/cocoa/coredatatutorial/index.html
And after studiously following every step carefully I realised I had done everything right I had just missed one binding: I had only set the Content Set of the child array controller and not its Managed Object Context (to File's Owner). That is the only reason my add button was not adding a new child object! Trivial mistake, but when you are not confident you question you're whole approach rather than looking for a simple error. Sorry for anyone who had to read this but maybe the link to the tutorial will help someone.

Is it possible to bind an NSTreeController to an NSOutlineViewDataSource?

I have some hierarchical data model that I'd like to present in an NSOutlineView. I'm binding a tree controller to the outline view to provide data and to handle selection and binding to other views.
However, I only want to show only part of the data in my model to the outline view. (Each object in my hierarchy has an array of child objects, but I'd only like some of these child objects to appear as child nodes of the node in the tree.) I wish I could just attach a filter predicate to the tree controller, but it seems that NSOutlineView doesn't support filter predicates.
I think that this design requires an NSOutlineViewDataSource to filter my data model, and an NSTreeController bound to the data source and the outline view. However, none of the binding outlets in the tree controller (Content Array, Content Object, Content Set, etc.) seems appropriate for binding a data source.
Any ideas? Thanks in advance...
You can try feeding the data to your array of child objects through an array controller.
Here's how I'd do it. Override the accessor method in your represented object and return a filtered array from your array controller.
In general, NS[Outline|Table]ViewDataSource and Cocoa Bindings is an "either/or" choice. Mixing the approaches, while perhaps not strictly impossible, will likely lead to unpredictable results.
You mention binding a filter predicate to the Outline View itself and not to specific nodes, so I surmise that one filter predicate for all nodes might be "good enough." If that's the case, then one solution to this would be to expose a second children-vending property on your model, maybe filteredChildren, and tell the NSOutlineView to use that to access children instead of the your default/complete children-vending property. If you need functionality like drag reordering, this approach might prove to be non-trivial, but it should be easy to explore this approach regardless.
If you need a different filter for each node, or if the filter changes dynamically, this task would likely have crossed over into being a case that was a good candidate for implementing NSOutlineViewDataSource (and a poor candidate for using Cocoa Bindings.)

How to NOT display certain nodes in outline view?

In Apple's Mail app, in the outline view on the left, an inbox or a folder is shown in hierarchy but the emails in the folder or email is not shown at all.
I would like to reproduce this feature.
I have an outline view connected to a tree controller. Objects (nodes) are added to the tree controller and displayed in the outline view. How can I prevent some objects from appearing? Specifically, I have folder nodes that contain instances of a custom object. Just as in Mail.app, I would like to only display the folder in the outline view and will have the custom objects displayed in another view.
Some controller code as per request; here I am adding nodes to a folderNode that is selected in the outline view:
indexPath = [treeController selectionIndexPath];
indexPath = [indexPath indexPathByAddingIndex:[[[[treeController selectedObjects] objectAtIndex:0] children] count]];//want to insert the new node at the end of the folder node's array of children
...
[treeController insertObject:customObjectNode atArrangedObjectIndexPath:indexPath];
NSLog(#"No. of items selected in tree controller/outline view is %i",[[treeController selectedNodes] count]); //if the folderNode is a leaf, this gives 0, i.e. no selection
// if the folderNode is not a leaf, the added child automatically becomes selected by NSOutlineView. In that case I keep its parent selected (the folder) so the next customObjectNode can be added
[self selectParentFromSelection];//however this method will then do nothing because at this point nothing is selected. Now this whole paragraph of code cannot be repeated because nothing is selected so the first line of code doesn't work.
Are you using any other tree controllers which need to continue on to the children?
If not, just have the folder nodes return YES to -isLeaf (and nil for the childNodes key).

NSOutlineView with Bindings driven by Core Data

I've got an NSOutlineView acting as a source list for my application, and my data model is done with Core Data. I'd like to use bindings (if possible) to glue these things together as follows:
I have three main entities in my model, for sake of example let's call them "Stores", "Cars" and "People".
My goal is to have the outline view have 3 "groups" (expandable nodes, like PLAYLISTS in iTunes), each group representing and listing one of my entities, and also I've got three buttons at the bottom of my window to "Add Store", "Add Car", etc which I'd like to have wired up to perform that action.
So far in my window's nib I've got a TreeController which is bound to my NSManagedObjectContext instance of my window controller, but I can't figure out how to properly bind and populate the outline view from the TreeController.
Is this possible with bindings? I've seen one tutorial where a second managed object model is created, with entities for the outline nodes, but some comments on the article said this was a bad idea. I'm not really sure how to proceed, any help would be wonderful!
Try the Cocoa Bindings Programming topics: Providing Controller Content section
What I did was create custom classes for my entities, and added isLeaf properties to them. For the top level (Stores, Cars, People) I return no. For leaf nodes (a car, a person, etc) I return YES.
The top level needs to have a to-many relationship to the leaf nodes, I called this children.
In Interface Builder, I set the NSTreeController's mode to Entity, name: Groups. It's bound to the managedObjectContext. In the Key Paths I set the Children attribute to children, and Leaf to isLeaf.

Resources