I have a fairly straight-forward navigation based app. It is like a "wizard" in that the user selects a series of prefs is a logically sequential way (that is, the subsequent options are determined by the previous choices).
Do this (a) -> then this (b) -> then this(c) then this (d).
Ah, but now I want to have a simple 2-stage navigationController that just functions in stage (b).
To be specific, viewController 1 is a table of 'favorites' and viewController 2 is a table of many possible choices.
So, I need to nest a navigationController for stage (b) within the bigger, overarching navigationController.
Just can't quite get my brain around this one. I'm an IB fan, but willing to do it programmatically if needed.
Ideas?
For anyone interested...
I came up with this elegant solution.
I push a 'managing' viewController(1) onto the main navigationController(1), and then in that viewController(1) I add another navigationController(2) / assign the real root viewController(2) / then set the navigationController(2) view to the managingVC(1) view. Viola!
A few delegates later and I have a very slick app with nested navigation.
Related
I'm new to the NoSQL world and I'm wondering if there are some known good patterns established for maintaining a manually sorted list.
More specifically, imagine the typical ToDo list application. At the top you have the List and under that you have each of the Items. I want the end user to be able to drag and drop the items. Therefore, I need to preserve this order for the next time I read these Items.
In a Relational DB I had a few ways to solve this, though none of those ways were that pretty. Maybe there is something better in the world of NoSQL? Not that it should matter, I'm using Firebase.
Just create an integer field for each item that indicates its position in the list. Update the values of the positions when user makes a change.
tl;dr
In a program that calls a function onEnterFrame on each frame, how do you store and mutate state? For instance if you are making a level editor or a painting program where keeping track of state and making small incremental changes are tempting / enticing / inviting. What is the most performany way to handle such a thing with minimal global state mutations?
long version:
In a interactive program that accepts input from the user, like mouse clicks and key strokes, we may need to keep track of the state of the data model. For instance:
Are some elements selected?
Is the mouse cursor hovering over an element, which one?
How long is the mouse button held down? Is this a click or a drag?
We also, sometimes need make small changes to a large model:
In a level editor, we may need to add one wall to an existing large set of prefabs. You don't want to recreate the set, no?
Read Prof Frisby's mostly-adequate-guide so far, there are many functional solutions to issues that deal with extracting a piece of data from some source of input, performing computation on that data and passing the result to some output.
Sometimes an app let's the user interact and perform a sequence of mutations on data. For instance, what if a program let's the user draw (like Paint) on a canvas and we need to store the state of the painting as well as the actions that led to that state (for undo and logging/debugging purposes)?
What state is acceptable to store and what should we absolutely avoid?
Currently my conclusions is that we should never store state that we only need temporarily, we should pass it to the function that needs it directly.
But what if there are several functions that need a specific computation? Like the case in which we check if the mouse's cursor is hovering over a specific area, why would we want to recompute that?
Are there ways to further minimize mutations of global state?
Storing state isn't the problem. It is mutating global state that is the problem. There are solutions to handling this. One that comes to mind is the State Monad. However, I am not sure this is ideal for undoing operations. But it is a place to start.
If you just want to look at the problem as an initial state and a set of operations then you can think of the operations as a List that can be traversed (with the head being the latest operation). Undoing a set of n operations could be accomplished by traversing the first n elements of the list and cons-ing the inverse of these operations to the list.
That way you don't modify global state at all.
I'm learning the Model/View paradigm of Qt because it seems very well suited to edit the data structures I have to deal with, such as this one:
Addition
|_QuadraticFunction
| |_intercept=0.2
| |_slope=0.0
| |_quadratic=1.2
|_Multiplication
|_LinearFunction
| |_intercept=0.0
| |_slope=-8.9
|_Gaussian
|_center=0.6
|_sigma=0.4
My data structure is made up of a combination of functions, each function has its own properties. However, I don't want to display the whole data structure in a single TreeView because it can get too long for complicated structures. Instead, I want to show one view including only the function names, and other view showing only the properties of the function selected in the previous view by the user with a click of the mouse, like this:
(FunctionsView, the first View)
Addition
|_QuadraticFunction
|_Multiplication
|_**LinearFunction**
|_Gaussian
(selectedFunctionView, the second View)
intercept 0.0
slope -8.9
In this example, the user clicked on LinearFunction in the first View, and the second View automatically showed its properties.
My question is: can I hold all my data structure (function names and function properties) under a single model and then have two Views that display only parts of the model like above? If not, do I have to create one model for each partial View, each model indexing different parts of the data structure? Please help, I'm inexperienced with this.
.Jose
Yes, you can absolutely keep it all in one model with two different views. You'll probably want to look into a QSortFilterProxyModel; you would have one of these for each view. The proxy applies sorting and filtering--and filtering is what you're doing here--to a more complete model. When you select something in the main view, you'll want to issue a signal that's picked up by the other proxy model (or the other view and passed to its proxy), and then refilter based on the newly selected item. It's actually very easy to use overall. The easiest mistake to make is getting confused over which model index to use because you'll have model indexes for the proxies, and model indexes for the complete model, and sometimes you have to convert between the two. The documentation is pretty clear on where that's necessary, but it helps to be extra aware of it.
Take a look at the documentation and if you have more questions, please ask.
My application is a tool library manager. It has a treeview containing a list of lists and tools. It also has a tableview showing a list of tools.
When I click on a list in the treeview, I want to show the tableview with the list of children. When I click on a single tool in the tree, I switch widgets and display the editform for the tool.
How do I limit the tableview to only the children of the selected node in the treeview?
My data model is a custom qAbstractItemModel.
I have a similar situation (not quite the same!) as yours. Before I share my experience, my assumption is that you have a database of sorts which consists of the items that make up your lists/tools.
One possible solution is to create two custom models, one for the tree view (say, MyTreeViewModel -> QAbstractItemModel, associated with QTreeView) and one for the table view (MyTableViewModel -> QAbstractItemModel, associated with QTableView).
The two custom models should be fed by the same agent working with the database. The key difference is that the tree view model works with the entire database, and the table view model with only a subset, that is, the children of the chosen item in the main list. Think of it as full mapping v. partial mapping of the database.
When the user clicks on the top list of nodes in the tree view, you can emit a signal which could be picked up by MyTableViewModel, populates with only the children, and is displayed by QTableView.
Because the same agent serves both models, you should be able to maintain data integrity, in the sense changes to the underlying data by one model should be reflected in the other model. This solution has worked out really well for my application. Hope this works for you too!
I'm not sure if this is a complete answer to my own question but I'm much closer. On the tableview I can call setRootIndex() and pass in the current item from the qTreeView. This works to show only the children of the current tree item in the table list.
For me, it still shows both tools and child lists, which I want to filter, but I think that's a different issue.
What I'm trying to do is have a 3 state tree expansion.
I have three different icons for "expand" "collapse" "semi-expanded" which I want to use to show a partially populated tree control with all nodes initialized to semi-expanded state and then on clicking the "semi-expanded" icon it gets data from server and populates the tree and open that branch with "expanded" icon.
I tried looking for it but couldn't find anything close to it except the 3-state checkbox but don't know how to use it on 3 state icon when tree would only maintain 2 states.
Thanks in advance.
I think what you are looking for is called a lazy-loading tree. There are lots of examples your can google for, but here is a great example.
As far as the visual part of your request goes (3 different icons to show that state of the branch or node) - you could easily handle that with a custom renderer, by looking at a flag on the node for it's load status.
Does that help?
A 3-State tree control is a bit uncommon and might therefore be a bit confusing; consider that even simple 3-state checkboxes are relatively rare and users may not be accustomed to them. Maybe that's why you didn't find such a tree control.
Thus, maybe you should consider using an alternate design that doesn't require 3-state controls.
For example, the node could start in collapsed node. If the user expands it, and there is no data yet, show a single sub node with the text "retrieving data..." (and a progress wheel or other progress indicator, if you can) and start data retrieval. When the data arrives, replace this sub node with the actual data.