Qt/QML: Delay window rendering until data is available - c++

I am building an application using Qt/QML. The QML of my main window is very complex and depends on lots of data which must be loaded via HTTP and then be processed by a C++ backend before it is ready to be displayed.
The C++ backend provides a signal which is fired when the data is ready. Until then, I want the window to be empty except for a simple loading indicator being displayed. Of course, I could use a simple overlay which hides my actual interface until the data is available, but this would mean that the QML code of my actual user interface is already loaded and tries to access the not-yet-available data, which is causing a lot of errors, so I would need to add dozens of dummy values and NOTIFY signals for each single property which might not yet be available.
What is the best way to completely deactivate a portion of QML code and to enable it as soon as a signal is triggered?

My personal experience is to not give data to your view components, don't bind them. For example, set your text value to an empty string or don't set it, set your image component source to an empty string or don't set it at first. When your signal comes in with data ready, you assign the data to the views at that time.

Related

How to link the received variables from tcp-modbus to the respective widget that should deal with it on wxWidgets?

I am working on a GUI with wxWidgets to communicate with a PLC. I dedicate a thread especially for the communication via the ModBus protocol. The read variables are send back to the GUI as a custom event containing the adress of the variable and the value. The GUI is designed as a notebook which displays some content that depends on the read variables.
The problem
I am looking for the best and cleanest way to assign the received variable to a widget that should display it (either a led that must be switched on/off, or a textcontrol,...). My first idea was to choose the Ids of the widgets such that it is linked to the modbus adress. Thus, when I receive the event in the top handler (one page of a notebook), I would distribute it further to the respective widget as follows:
int id = convert_adress2id(evt.adress); // For example, 2*adress + wxID_LAST
wxWindow w = FindWindow(id);
w.AppendEvent(evt); // Distribute it further to the widgets that handles the adress
This solution seems nice to me but is not very robust. For example, one widget might need several variables from different widgets. The task is complex because there are a lot of variables.
So what other solution do I have? I need sort of a table to connect the adresses to the widgets. But how to design it the best way?
I thank you in advance for your help.

Qt / CPP: how to implement callbacks with signals and slots the "right way"

I'm trying to implement an application in Qt with a model-view-controller scheme. I have some model classes (databases), one application controller, and a bunch of GUI classes. All GUI classes know the app controller and can call its public slots to send data to it that should be stored in the model. The app controller takes the data and calls the appropriate database to store it. The database classes check the data and return a bool to the app controller to tell if the data was okay or not.
Now, one GUI element has prepared some user data and wants to send it to the app controller. I am trying to figure out how to let the GUI-class know that the app controller validated the incoming data with the model and it accepted the data. My app controller shouldn't care nor know which GUI elements call its public API to commit data to the model. But how does the app controller communicate a response to the GUI element to tell it, that everything was fine, so the GUI element can close itself?
My idea would have been to let the GUI element create a random number token to send it to the app controller together with the data as a kind of "callback address". As soon as my GUI element receives an okay signal with the correct token attached, it can react to that.
I was dunno. All my solutions feel weird and not how it's supposed to be in Qt.
Edit 1: a pseudo-code example for clarification:
void Appcontroller::Slot(userdata)
{
bool okay = database->save(userdata)
};
void Appcontroller::CreateMasterWindow()
{
this->masterwindow_ = new MasterWindow(this);
// I am propagating the knowledge of the app controller to the
// MasterWindow and the latter can propagate that info further
// down, that's fine (everybody can know the responsible
// controller, but I don't think the controller should care about
// all his bastard children)
};
void MasterWindow::CreateSubWindow()
{
this->subwindow_ = new SubWindow(appcontroller_);
// the masterwindow creates a random subwindow that the controller
// should't have to care about
};
void SubWindow::SendUserData(userdata)
{
QObject::connect(this, &SubWindow::SendToControllerSignal,
appcontroller_, &Appcontroller::Slot);
emit SendToControllerSignal(userdata);
// how to get a callback (targeted to me/this) from this,
// if the appcontroller does not know me? what is de way?
};
TL;DR: Connections should be made outside of the components. To compose the parts of your system, you instantiate the objects, and then connect them for desired functionality. The objects should otherwise have no knowledge of each other.
Thus, the only means of communication between the objects are signals and slots.
All GUI classes know the app controller and can call its public slots to send data to it that should be stored in the model
Nope.
The GUI classes should know nothing. When a GUI class needs something, it emits a signal. When a GUI class is supposed act on something (e.g. a change in the model), it exposes that as a slot.
I am propagating the knowledge of the app controller to the MasterWindow
Why? The MasterWindow exposes its functionality via signals and slots. Composing it into a bigger system is accomplished by signal/slot connections. No other knowledge is needed.
The app controller takes the data and calls the appropriate database to store it.
Does there even need to be a controller? All it seems to do is act like a signal-slot connection. You can directly connect the GUI classes to the database, and the controller could be what sets the connections up initially.
Otherwise, the application controller can act as a viewmodel, i.e. a QAbstractItemModel that adapts the model exposed by the database, and tweaks it for display/interaction (e.g. adds color properties, icons, etc.).
The database classes check the data and return a bool to the app controller to tell if the data was okay or not.
The database classes should expose slots that are used to modify the database state. They should also expose signals that indicate any changes. To indicate failure, the database can indicate a "change" with the same value.
how to get a callback (targeted to me/this) from this, if the appcontroller does not know me? what is de way?
The signals from the model/database are connected to the GUI classes. A GUI class can go into a "change pending" state once it emits a "change requested" signal. It will then react accordingly when its "new value" slot is called with the updated value: if the value didn't change, it indicates a failure, otherwise it indicates success. If it didn't request a change, it simply updates the displayed value - something else changed it.
This can be all done using nothing more than the Q_PROPERTY mechanism, and the change notification signals.
If the values aren't simple discretes, but rather have some structure, expose those as indices in a custom QAbstractItemModel. Each GUI item can then act on one or more model indices: requesting the changes, and reacting to value updates.
Multiple GUI elements can be hooked up to the same database variable (or no GUI elements!), and the GUI must support this and update its state to reflect the state of the model.
The "tickets" or "request identifiers" you propose are mostly spurious. The requesting GUI element has enough state to know that it requested a change, and can always act predictably on subsequent feedback from the model/database.

MFC Saving Custom Header Column Widths

So I'm just learning MFC to see if I want to start using it over normal Win32 programming. I have a SDI MFC application setup. I have a view with members that create a CTreeCtrl and CHeaderCtrl. I have a CDwordArray setup as m_ColWidths that is currently in my View class, but using MFC, should this be in the document class instead since I'll want to save and restore it to keep the users widths when program exits? I guess even though it's only part of the view it's still data and use GetDocument() to reference them?
TIA!!
Application state should not be stored in the document. The purpose of the CDocument(-derived) class is:
A document represents the unit of data that the user typically opens with the File Open command and saves with the File Save command.
CDocument supports standard operations such as creating a document, loading it, and saving it. The framework manipulates documents using the interface defined by CDocument.
The designated entity to store application state (e.g. size and visibility of UI elements) is the CWinAppEx(-derived) implementation:
CWinAppEx handles the application state, saves the state to the registry, loads the state from the registry, [...].

How to delay the sending of the data of the widget to the server side (to wait for a potential change in the input of the widget)

I have some widgets that receives a lot of user inputs in a very short period of time.
eg. a selectInput with multiple selection on which the user are clicking a lot very quickly
This causes unnecessary calls to the server side of the Shiny application.
Is there a way to set a delay before the widget sends its new data to the server? either application wise or on a per-widget basis.
I guess that would ask for some 'setTimeout' and 'clearTimeout' in the javascript.
If that's not available natively what are my options?
I have written a few custom widgets using http://www.htmlwidgets.org/ but I don't want to reinvent the wheel and I don't want to make a clone of the native widget because that would force me to track new versions of the the widget and update the clone correspondingly.
Is there a way to extend an existing widget and override only some part of it (the part sending the new input to the server side), and keep getting the updates of this existing widget?
Another option would be to let the widget send its updated input every time there is a change on the widget BUT to tell the server to wait before handling it, in case a new input comes in. That would work for me as well.
NOTE: I don't want to use observeEvent/eventReactive
If you are able to use JavaScript then I would recommend using a setInterval loops stored in variables. I find them really handy for running functions in intervals and you can run multiple loops at the same time and tweak the timing for best performance as you can also close off and start up new ones. Hope this helps.

How to know when all QAbstractItemModel::data() functions finished

I wrote a QAbstractItemModel based class and implemented data(const QModelIndex & ar_index, int a_role) const function. I refresh the model using:
beginInsertRows(QModelIndex(), 0, 0);
// fill model
endInsertRows();
Inside data function I update some information X needed after refreshing.
I checked that data functions are invoked after refreshing the model and debugging I verified that my X variable is properly setted.
After refreshing, I need to fill another widget with this X value. How do I know that all data refresh was finished and correctly show Xvalue? Which signal is emmited after completelly refreshing the model?
There is no standard signal to use here -- the Qt's MVC API is designed to support not only static models, but also the dynamic ones, and for these, there cannot ever be a signal telling "all done". For example, in Trojita, a Qt IMAP e-mail client, rowsInserted is emitted to indicate that a new e-mail has arrived, but this happens even before the library knows anything about the new arrivals -- not even their UIDs. Only after the remote server has responded to the library's commands with data, the dataChanged is emitted to indicate that the "data represented by the model" has changed and that the attached views shall update.
You said you're reimplementing your own QAIM from scratch. This means that you can set any contracts you see fit here. Are some of the data immutable, i.e. guaranteed to never change after they have been loaded? If so, you can use a custom role like RoleIsItemFetched and after each change to the model (that is, after modelReset, rowsInserted, rowsMoved and dataChanged) check whether your data(someIndex, RoleIsItemFetched).toBool() function returns true. If so, you have your data, if not, you have to keep waiting.
An alternative to that might be to introduce your own signal. Don't be afraid of that, the MVC API is great for presenting data to users, but if you think you need more control over what is returned and have full control over the model and the "views", go ahead and make the code do what you need.