NSOutlineView expand items by default with `autosaveExpandedItems` - appkit

I have an NSOutlineView that uses autosaveExpandedItems to remember which items are in an expanded state and which are collapsed, this is working well.
The other requirement I have is that all items should be expanded by default, unless the user has collapsed it. At the moment, all new items are collapsed by default.
Is there any way to achieve this?
edit:
Let's assume 5 (could be any number) static groups, on first load I can expandAll which expands all 5. If I collapse 2 and close the window the next time I open it all will be expanded again due to the expandAll call, instead of remembering that 2 were collapsed. Taking out the expandAll call will properly save the expand/collapse states, but it then defaults all to collapsed. So on first open all will be collapsed, instead of expanded.

Related

How to control which GTK widgets visible in an expanded row of a tree?

I'm building a tree store with GTK3 in C in which there are primary rows that are always displayed, and by clicking on the little triangle icon to the left of a primary row, additional secondary (child) rows expand below the primary. As an example, consider that the primary rows could be directories, and when they're expanded, rows below that show the files in those directories. I'm doing this to allow a user to select primary items to be deleted, while the secondary rows are just informational, telling, for example, what files are in the directory, so they'll know if they really want to delete the whole thing.
To enable selection for deletion, the first column contains a GTK_CELL_RENDERER_TOGGLE, and I have a callback associated with the checkbox toggle. Everything works nicely except for one thing. When the user clicks the little triangle item to expand a row, most of the content of the primary row does not appear in the secondary rows (this is expected and desired), but... the checkbox toggle does appear in the first column. Although in a directories/files example that might be meaningful, in my case it makes no sense to think of deleting the content of the secondary rows.
When building the secondary rows, I've tried things like just:
gtk_tree_store_set(TS,&J,2,"filename",-1);
or
gtk_tree_store_set(TS,&J,0,NULL,2,"filename",-1);
hoping that NULL would cause the toggle to be suppressed, but to no avail. GTK still displays a checkbox, probably just interpreting the NULL as a zero.
Is there a way to control (and in my case, suppress) display of the toggle? Or more generally, is there a clean way to control which columns are displayed in child rows? It seems to work with TEXT, but just not with TOGGLE.
A little later: There is a potentially useful function called gtk_cell_renderer_set_visible(), but it requires a reference to the cell renderer. How to acquire that on a per-row or per-cell basis when all I have during construction is the GtkTreeStore and a GtkTreeIter?
There are (at least) 2 solutions:
Base class GtkCellRenderer has visible property. You can add extra field to your model which indicates, whether Toggle should be visible for this row.
If there are other fields in you model which indicate whether it's a primary or secondary row but not directly you can use gtk_tree_view_column_set_cell_data_func to set a function to be called before rendering. There you can call gtk_cell_renderer_set_visible or any other function to set renderer's properties manually.

QTreeView calls QAbstractItemModel::hasChildren() even for invisible items

I have a custom tree model with many items. It has more than 1000000 items at the first level below the top level. When I expand this level in a QTreeView it calls model.hasChildren() for each of these items even though the items are not visible (you would need to scroll down, down, down... to make them visible). The trouble is that my function hasChildren() takes some time especially when called million times (takes about 10 secs - in PySide/PyQt). My questions are:
1) I understand that hasChildren() is called for visible items because it must know whether the item should be expandable (if it has children) or not. But why it is called for invisible items (I mean those which are not inside the visible range and become visible only after scrolling down)? In my view it should be called only when the item is about to become visible. Am I missing somethig?
2) How to work around this issue?
You likely need to override fetchMore/canFetchMore per pyqt docs. Basically when you expand the root, fetchMore() will be called, you will only return a subset of data items; when the user scrolls, the view will ask the root if it can fetch more; if it answers yes, fetchMore() will get called and your model can return more items. This should cause hasChildren() to be called only on the tree items fetched.

Source List collapsed on Start

I have configured a Source List as a sidebar on my app. Problem is when I run it all of the groups are collapsed. How do I fix this?
Yes, an outline view will start with its rows collapsed. (You can configure it to remember the last state, but that doesn't help for the first time and may not be what you want anyway. For example, if you change your program to add more groups.)
You need to add code to expand the rows you want expanded after the outline view has been populated. One place to do this would be in a window controller's -windowDidLoad method or an override of a view controller's -loadView method. Also, almost anywhere that you call -reloadData or -reloadItem:... with the root (nil) item.
If the only expandable rows in your source list are the groups — that is, there are only groups and one level of leaf nodes within the groups — then you can do [outlineView expandItem:nil expandChildren:YES] and that will expand all groups. Otherwise, you need to identify which specific items you want expanded and invoke -expandItem:... on each.

Black line appears when updating a ListView with selected items

I have a list view that draws an additional black line when items in the list are modified and there are selected items in the list.
The code iterates over the list and updates the cells using the line of code below:
ListView_SetItem(m_hListCtrl, &lvItem);
Additional rows are added using the ListView_InsertItem macro.
If a row is added and there are other rows selected, the following happens:
The line disappears if the user selects a different row. How can this black line be prevented/removed?
The LVS_EX_GRIDLINES style has a number of bugs associated with it that Microsoft have never bothered to fix, and this is one of them. The workaround is to forcibly redraw the list items when you make the particular changes that trigger the problem. You can redraw a range of list items using the LVM_REDRAWITEMS message, or even simpler just repaint the whole control with InvalidateRect().

Scroll SlickGrid only one line, when using keyboard navigation

I have implemented a slickgrid and activated keyboard navigation.
When the users is scrolling down using the down-arrow key and reaches the last of the currently visible rows, the grid loads a whole new section of rows and places the selection at the top.
My user tests have all included a complaint about this behaviour as they all find the jump jarring.
I would like to implement behaviour, so the grid scrolls just one line at a time, when I press the down arrow while the last visible row is selected.
I was wondering if there might be some setting, I have overlooked, or if anyone has some suggestions for how to approach the task of adding this behaviour.
(the "problem" is the same, when you scroll upwards - only reversed of course)
This is controlled by the doPaging argument in scrollRowIntoView(row, doPaging) (https://github.com/mleibman/SlickGrid/blob/master/slick.grid.js#L2662). There's no setting to control that behavior, but you could easily add one.
It was initially written this way to make keyboard navigation faster since continuously navigating down doesn't have to do as much work as it would have if we were updating the grid on every 'row down'.

Resources