Still working unsuccessfully on the QSortFilterProxyModel problem, but I've now discovered that a bug in that class was fixed in QT 4.6.2, so it may be solved by an update which I'll do tomorrow.
Cleaning up dead code; preparing to re-integrate the regexp filter for the xml:id list view. I'm having trouble re-understanding some of my original code, using the QSortFilterProxyModel...
Added bool properties for namespace awareness in the HcmcImtDoc and DlgXmlIndex classes, so we don't have to decide right now which approach is best for our purposes. These are set in the constructor, but there's also a setter to change them later.
Tested two approaches to handling XML documents, one of which is namespace-aware and the other which is not. Both have advantages and disadvantages, so it's not yet clear which approach we should take for IMT. I need to make this switchable at the level of DlgXmlIndex and HcmcImtDoc, via public properties.
SA and I have decided that an effective way for Half-Baked to prepare for writing Hot Potatoes 7 would be to sponsor the development of the Image Markup Tool version 2, allowing us to develop a set of core libraries and functions, as well as gaining familiarity with the issues involved in compiling and releasing for different platforms. We also intend to use IMT 2 for creating end-user documentation in HotPot 7.
For this reason, Half-Baked will pay SA and myself to work on the development of IMT, and this work will be tracked in the "Half-Baked Contributions" post category, as well as in the "Activity Log" category.
I've started the process this morning by checking out the project and confirming I can build the DocModel subproject.
I've now created a container class which hosts a DomModel and a QStringListModel, showing two views of the same data. It should be fairly easy to hook up the filter which I had hooked up before, to allow filtering of the list view. After that, we begin to figure out how to hook together the selections. I think the string list model is actually going to have to store a reference to the corresponding DomModel items, and the DomModel items might have to store a reference to the original nodes in the DomDocument...
I'm slowly coming to the conclusion that it's NOT possible to implement two separate views of the data in the document, in the way I need to implement them. The basic issue is this:
DomModelclass I'm using to create the tree model is implemented as a "lazy" system, which means that data is not provided, and indexes are not created, until they're asked for by the view. That means that only the root elements are processed initially. That, in turn, means that the proxy model is only fed the root elements to construct its list of items with
- Even if I were able to overcome this by forcing the DomModel to fully populate itself initially, I'm still left with the problem that the way the
QSortFilterProxyModelworks makes it impossible to do what I need to do. This is because filtering is accomplished through a
filterAcceptRow()method, which you implement to return true or false. If I implement this so that it returns true only for elements with
@xml:ids, then as soon as it encounters an element which doesn't have one, it has to return false; at that point, the children of the element are not processed. I could try to determine whether each element has any descendants which have
@xml:id, but then I'd be accepting and therefore displaying a whole set of elements which don't actually have
@xml:ids, just so their descendants can display.
I think the best approach is actually going to be to implement a whole different sort of structure, with two different models, built from an underlying DOM document, but encapsulated in one object. It might be easier, then, to keep the two models in sync, especially since we're expecting to allow the document itself to change; each model could be instructed to rebuild a part of itself when a component changes. It might also be easier to manage the selection issues manually in a parent object, rather than try to use the single object. I'm planning this now.
Today I reimplemented the tree view based on a DomModel taken from the SimpleDomModel example, and hooked that up to a QTreeView, replacing the QTreeWidget. This works great. The next phase is to filter that model into QListView, which I'm assured by someone on one of the QT forums can be done by subclassing QSortFilterProxyModel, and implementing filterRows and filterColumns. This I've now done, but the results are not encouraging: nothing shows up in my list. At this point, I'm not sure whether this is because the filter method code is flawed, so it's never accepting a row, or because when a row is rejected, its children are never tested, which means that you can't get down as far as a list of elements which have @xml:ids; or even because child rows are never tested at all, so only the top level nodes get as far as the filter. At the moment, I'm tending towards the last option, because even when I make my function return true in all cases, only the top level nodes show up.
I'm sure I'm on the right track here, but it's going to take some more work...
Changed the list of xml:ids so that it's implemented with a true model based on QStringListModel, proxied through a QSortFilterProxyModel, enabling regular expression filtering. This is based on an example in Blanchette and Summerfield (pp. 250ff). The next step would be to replace the QTreeWidget with a QTreeView and build a similar model there, but I'm not quite sure how I would keep the two models in sync; the thing I don't yet understand is how, or even whether, you can have two distinct models which derive from the same underlying model, or one model which is simultaneously a QStringListModel and a custom tree model.
I'm doing the preliminary planning and reading for a document model which will provide three views on the underlying code in the TEI file:
- A read-only syntax-highlighted text view (MdhXmlEditor).
- A tree view (QTreeView).
- A string list view (QListView).
The last two will have access to right-click options to add new items, edit existing items, and presumably delete. The basic approach that seems best is outlined in this example project, which builds a tree view from a DOM model of a document. However, this example project has some key limitations that I need to work around. First of all, it's a read-only model, which means that it doesn't have to worry about updating itself when changes are made to the underlying document. Secondly, it only provides a single view of the data in a QTreeView; I need to bind the same model simultaneously to at least two different views (and probably three, if #1 above is integrated as a "view" in the model-view architecture rather than being handled in a more ad-hoc way). I now need to find more examples of multiple views, and I need to get a real handle on how views are updated when a model changes. I may even need a third view, which shows only one item and allows it to be edited; that would make things even more complicated. Perhaps the read-only view shouldn't be read-only; it should just show the selected item, and no surrounding code, and it might be the whole editing interface. You could see the whole document by clicking on the root element in the tree view.
This stuff is hard -- for me, anyway -- but it's definitely the correct approach.