1
votes

I'm working on a programm (notifyfs) which takes care for caching of directory entries and watching the underlying filesystem for changes. The cache is stored in shared memory, (gui) clients can make use of the cache very easily.

Communication between server (notifyfs) and clients can go using a socket or via the shared memory self, by sharing a mutex and condition variable.

When a client wants to load a directory it does the following:

a. select a "view", which is a data struct in shared memory, which consists of a shared mutex, conditionvariable and a small queue (array), to communicate add/remove/change events with the client.

b. the client populates his/her model with what it already finds in the shared memory

c. send a message to the server with a reference to the view, and an indication to the path it wants to load its contents. This maybe a path, but if possible the parent entry.

d. server receives the message (does some checks), sets a watch on the directory, and synces the directory. When the directory has not yet been in the cache this means that every entry it detects is stored in the cache. While doing so it signals the view (the data in shared memory) an entry is added, and it stores this event in the array/queue.

e. the gui client has a special thread watching this view in shared memory constantly for changes using the pthread_cond_wait call. This thread is a special io thread, which can send three signals: entry added, entry removed and entry changed. The right parameters it reads from the array queue: a reference to the entry, and what the action is. These three signals are connected to three slots in my model, which is based upon a QStandardItemModel.

This works perfectly. It's very fast. When testing it I had a lot of debugging output. After removing these to test it without this extra slow io, it looks like the QTreeView can't catch up the changes. When loading a directory it loads two third of it, and when going to load another directory, this gets less and less.

I've connected the different signals from the special thread to the model using Qt::QueuedConnection.

Adding a row at a certain row is done using the insertRow(row, list) call, where row is of course the row, and list is a QList of items.

I've been looking to this issue for some time now, and saw that all the changes are detected by the special io thread, and that the signals are received by the model. Only the signal to the QTreeView is not received somehow. I've been thinking, do I have to set the communication between the models signal and the receiving slot of the treeview also to "Qt::QueuedConnection"? Maybe something else?

1
Your question is too heavy. You can simplify it like: "Sometimes QTreeView does not update, even if new items are added to module. How to fix it?" and provide minimal code sample that reproduce your problem. In most cases such bugs appears after incorrect implementation of models. I can add a code sample that shows how to fill QTreeView with list of files during scanning of folder from separated thread.Dmitry Sazonov
What do you mean with too heavy? Too much details? My question has some details because I want to provide information when the problem occurs, and what I did already to prevent suggestions which I already tried. And your idea to ask a question like "sometimes QTreeView does not update" is way too short. Than people will then ask naturally to give more details.user1388973
@user1388973: Sometimes a bit of self-contained code is better than a thousand words.Kuba hasn't forgotten Monica
@Kuba Ober: yes I agree, but sometimes giving details about the process in words is better. I preferred that here. But Dmitry Sasonov, I'm interested in your code. How did you code the population of QTreeView using a special thread?user1388973
All QWidget-derived objects must be in the GUI thread. The IO and the model can be moved to another thread. Just pay attention to those data() calls! If your model is read-only, then you should probably have a trivial implementation of setData() returning false.Kuba hasn't forgotten Monica

1 Answers

0
votes

suggested in the reactions was to put the model in a special thread. This was tempting, but is not the right way to solve this. The model and the view should be in the same thread.

I solved this issue by doing as much as possible when it comes to providing the model with data by the special io thread. I moved some functions which populated the model to this special io, and used the standard calls to insert or remove a row. That worked.

Thanks to everyone giving suggestions,

Stef Bon