ChatGPT解决这个技术问题 Extra ChatGPT

Why Qt is misusing model/view terminology?

I think that the terminology used in Qt with model/view controls is flawed. On their explanation page they state, that they simplified the MVC to MV by merging View and Controller and they are giving the following picture:

https://i.stack.imgur.com/z7v18.png

However I think, they misnamed the roles of objects and I think that,

What they call View with merged Controller is in fact a View only. What they call Model is in fact Controller only. If you really want to have a model it would be somewhere where their "Data" is.

I am speaking about usual and sane way you would use Qt model/view component in your app. Here are the reasons:

This is typically Qt component which is used as is, without adding any Controller logic specific to your objects) This is hardly a Model, just because you should implement several Qt methods like rowCount, columnCount, data etc. which have nothing to do with your model. In fact there are typical model methods found in Controllers. Of course, you can implement both Controller and Model logic here, but first it would be quite bad code design and secondly you would merge Controller and Model not Controller and View as they state. As said in reason 2. if you want to separate Model logic that it is surely not the blue box on the picture, but rather the dashed "Data" box (communicating to real Data of course).

Is Qt wrong in their terminology, or it is just me who does not understand? (BTW: The reason why it is not academic question is that I have started to code my project following their naming and I have soon found out, that the code clearly is not right. It was only after that when I realized, that I should not try put Model logic in what they call Model)

MFC set the standard for 2part model/view guis with CDoc and CView - there is no reason that a particular MVC is 'correct'
@Martin B: I will have a look at MFC, however even if there are different MVC models I think they should be consistent in their terminology and I think I have presented valid arguments, why the terminology used is not consistent in this particular case. They simply state that they have combined View and Controller but I thing it is just plain misleading in the case. I do not think there is a MVC model where all application specific logic be it presentation or model logic has to be put in one object called Model.
@Martin B: Also under the qt terminiology all Models have common api which has nothing to do with Model structure, but everything to do with general Controller structure, which is clearly sign that it is not right to call it Model. I an not saying there is ONE correct MVC model, but it does not mean than anything can be called MVC model. Maybe it is flawed in MFC as well and I can have a look at it, but I am more interested in Qt getting it right, that MFC which I do not intend to use. Do you have any good link where MFC model/view separation is explained?
MVC terminology is by no means unanimously agreed upon so your question could be considered argumentative. Many will agree however with the excellent work done by Martin Fowler (martinfowler.com/eaaDev/index.html). Usually, the controller handles user input and in this sense, Qt widgets most definitely combine view and controller.
I understand that MVC has many flavours but it does not mean that anything can be MVC. Qt has crossed the line and I gave several reasons. Martin Fowler does explain different types of MVC, but neither of them is similar enough to what Qt pronounces MVC. The most similar is martinfowler.com/eaaDev/PresentationModel.html, but this distinhuishes between Presentation Model=Controller (user interaction) part and Model (data logic). So although there is no precise definition of MVC, Qt does not follow any of them. If you can give me a link to such definition, please do so.

l
leemes

Short answer

Qt's MVC only applies to one data structure. When talking about an MVC application you should not think about QAbstractItemModel or QListView.

If you want an MVC architecture for your whole program, Qt hasn't such a "huge" model/view framework. But for each list / tree of data in your program you can use the Qt MVC approach which indeed has a controller within its view. The data is within or outside of the model; this depends on what type of model you are using (own model subclass: probably within the model; e.g. QSqlTableModel: outside (but maybe cached within) the model). To put your models and views together, use own classes which then implement the business logic.

Long answer

Qt's model/view approach and terminology:

Qt provides simple views for their models. They have a controller built in: selecting, editing and moving items are something what in most cases a controller "controls". That is, interpreting user input (mouse clicks and moves) and giving the appropriate commands to the model.

Qt's models are indeed models having underlying data. The abstract models of course don't hold data, since Qt doesn't know how you want to store them. But you extend a QAbstractItemModel to your needs by adding your data containers to the subclass and making the model interface accessing your data. So in fact, and I assume you don't like this, the problem is that you need to program the model, so how data is accessed and modified in your data structure.

In MVC terminology, the model contains both the data and the logic. In Qt, it's up to you whether or not you include some of your business logic inside your model or put it outside, being a "view" on its own. It's not even clear what's meant by logic: Selecting, renaming and moving items around? => already implemented. Doing calculations with them? => Put it outside or inside the model subclass. Storing or loading data from/to a file? => Put it inside the model subclass.

My personal opinion:

It is very difficult to provide a good and generic MV(C) system to a programmer. Because in most cases the models are simple (e.g. only string lists) Qt also provides a ready-to-use QStringListModel. But if your data is more complex than strings, it's up to you how you want to represent the data via the Qt model/view interface. If you have, for example, a struct with 3 fields (let's say persons with name, age and gender) you could assign the 3 fields to 3 different columns or to 3 different roles. I dislike both approaches.

I think Qt's model/view framework is only useful when you want to display simple data structures. It becomes difficult to handle if the data is of custom types or structured not in a tree or list (e.g. a graph). In most cases, lists are enough and even in some cases, a model should only hold one single entry. Especially if you want to model one single entry having different attributes (one instance of one class), Qt's model/view framework isn't the right way to separate logic from user interface.

To sum things up, I think Qt's model/view framework is useful if and only if your data is being viewed by one of Qt's viewer widgets. It's totally useless if you're about to write your own viewer for a model holding only one entry, e.g. your application's settings, or if your data isn't of printable types.

How did I use Qt model/view within a (bigger) application?

I once wrote (in a team) an application which uses multiple Qt models to manage data. We decided to create a DataRole to hold the actual data which was of a different custom type for each different model subclass. We created an outer model class called Model holding all the different Qt models. We also created an outer view class called View holding the windows (widgets) which are connected to the models within Model. So this approach is an extended Qt MVC, adapted to our own needs. Both Model and View classes themselves don't have anything to do with the Qt MVC.

Where did we put the logic? We created classes which did the actual computations on the data by reading data from source models (when they changed) and writing the results into target models. From Qt's point of view, this logic classes would be views, since they "connect" to models (not "view" for the user, but a "view" for the business logic part of the application).

Where are the controllers? In the original MVC terminology, controllers interpret the user input (mouse and keyboard) and give commands to the model to perform the requested action. Since the Qt views already interpret user input like renaming and moving items, this wasn't needed. But what we needed was an interpretation of user interaction which goes beyond the Qt views.


The most irritating thing is, that you have to implement totally different Qt Model classes depending on the view you want. A model for a list view will not properly support a tree view and vice versa. A canonical MVC model can support a plethora of different view types.
@smerlin: I don't think that is correct. Both a QListView and a QTreeView only require an QAbstractItemView interface, meaning that a custom subclass of that, or a concrete class like QStandardItemModel should fullfil that requirement for both. You can drive a tree and list off one model.
@jdi: there are cases where your data is both, a list and a tree... e.g. you could like to display your file system as a tree, or all files as a list. Qts models dont allow that properly. A implemention of QAbstractItemModel supporting tree views, allows only to display all files/directories in your root directory as a list, but you cant display all files as a list. And dont say that displaying tree data as a list cant be useful. E.g., you can for example easily sort them to find the file with the greatest filesize if you display your files as a list, tree views would not allow that.
That said, the proxy model is more something of your view (since it modifies how the data is viewed) and thus should belong to your view. If you read my long answer: In the "big" View class you should add the proxy model, which has the tree model as its underlying model and is used by your file system list view. As you're saying: there should be no two models for the same data. Never! (But proxy models don't count as separate models.)
@SamPinkus That's because there is no clear yes or no to this question. Also, there are different implementations of QAbstractItemModel, some of which are models in the sense of MVC and some of them aren't.
B
Bart

I agree with you that Qt's naming is misleading. In my opinion however, the problem is not Qt's alone, but is shared by all frameworks that allow us to adhere to the principle of separation of concerns when implementing our UIs. When someone comes up with such a framework, and finds a good way to keep "things" separated, they always feel obliged to have modules that they call "Model" and others that they call "View". Over the years I have worked with these frameworks:

MFC

Qt

Swing

SWT

WPF with MVVM

If you compare how the terms "Model" and "View" are used in these frameworks, and what responsibilities the classes in the "View", the "Model", and the "Controller" (if there is one) have, you will find that there are very big differences. It would certainly be useful to have a comparison of the different concepts and terminologies, so that people switching from one framework to another have a chance to stay sane, but that would require a lot of work and research. A good read is Martin Fowler's overview.

Since there are so many different ideas what an MVC pattern can look like, which one is correct? In my opinion, the people who invented MVC should be turned to when we want to know how it is supposed to be implemented "correctly". In the original smalltalk paper it says:

The view manages the graphical and/or textual output to the portion of the bitmapped display that is allocated to its application. The controller interprets the mouse and keyboard inputs from the user, commanding the model and/or the view to change as appropriate. Finally, the model manages the behavior and data of the application domain, responds to requests for information about its state (usually from the view), and responds to instructions to change state (usually from the controller).

In light of that I would answer your three main concerns thusly:

In fact a Qt component "manages the graphical [...] output", and "interprets the mouse and keyboard inputs", so it could indeed be called merged View and Controller with respect to the definition above. I agree that you are/would be forced to merge Controller and Model (again with respect to the definition above). I agree, again. The Model should only manage the data of the application domain. This is what they call "data". Clearly, dealing with rows and columns for example has normally nothing to do with our applications domain.

Where does it leave us? In my opinion, it is best to figure out what Qt really means when the terms "Model" and "View" are used and use the terms in their manner while we are programming with Qt. If you keep being bothered it will only slow you down, and the way things are set up in Qt does allow elegant design - which weighs more that their "wrong" naming conventions.


I would say that the delegate is the Qt's controller, since delegates receives and send the input to the model, which updates the view through signals.
a
arnt

The terminology isn't right or wrong, it's useful or useless.

You might change the question a bit and ask why Qt isn't more MVC-friendly. The answer to is that the early Qt developers believe that decoupling V from C in GUI applications makes for bad Vs and Cs both. QWidget's design tries to make it simple to bind mouse input interperation closely with pixel output decisions, and you can see how that's not the road towards MVC.


I see your point and basically I WOULD ask why Qt is not more MVC friendly, but it is very hard to do when MVC terminology used in Qt documentation is DIFFERENT from for what MVC is normally used (as I explained in the question). And when there is widely used terminology and someone uses it very differently from the rest of the world, I tend to think that it is not only useless, but that it plain WRONG and confusing (that confusion led me to ask the question in the first place). I would be very interested if you have any links to these things being discussed or explained somewhere. Thanks
I can't say anything about why the Qt docs now talk about MVC in the way they do. I left Trolltech long ago, and am puzzled by some of the things that have been done to the documentation since I left. (On my blog I do sometimes rant a bit about that, though.)
Do you have any insight how the MVC terminology has been agreed on in Qt. Was it used during writing the code, or only later during the documentation process.
We did not use the word "MVC" in the Qt documentation during my time at Trolltech. In general I think it's best to document what's there, not write about what's not there. However, over on gitorious you can find out who added that text and add that person directly.
A different comment. We did discuss MVC during the design and early implementation phrase of Qt (when Trollech was a three-person company), and we evaluated a GUI toolkit that used MVC "properly", I can't remember its name. Our opinion was that that toolkit was terrible to use, and that MVC was much of the reason for that.
L
Lenin

As Model function is to respond to requests for information, I think there is nothing wrong in defining such methods as rowCount, columnCount, etc. I think Model is some kind of wrapper for data source (no matter what is it SQL table or just an array), it provides data in standard form, and you should to define methods depends on your data source structure.


C
Chris Morlier

I believe their terminology is correct...although in real applications I find it can be very easy to blur the lines between model, view, and controller depending on your level of abstraction: one level's view may be a higher level's model.

I feel the confusion arises from their QAbstractModelItem class. This class isn't a model item, but rather it is an interface to a model. To make their view classes interface with the model, they had to create a generic abstract interface to the model. However, a model can be a single item, a list of items, a table of 2 or more dimensions of items, etc; so their interface has to support all these model variations. Admittedly, this makes the model items fairly complex, and the glue code to make it work with an actual model does seem to stretch the metaphor a bit.


Althought I agree with you with QAbstractModelItem class I do also think that even without this complication their MVC is misnamed. Could you explain why you think that their terminology is correct. I would love to hear why i am not correct in any of my three arguments.
A
Arthur Tacca

I think that ... What they call Model is in fact Controller only.

No, their "model' is definitely not a controller.

The controller is the part of user visible controls that modify the model (and therefore indirectly modify the view). For example, a "delete" button is part of the controller.

I think there is often confusion because many see something like "the controller modifies the model" and think this means the mutating functions on their model, like a "deleteRow()" method. But in classic MVC, the controller is specifically the user interface part. Methods that mutate the model are simply part of the model.

Since MVC was invented, its distinction between controller and view has become increasingly tense. Think about a text box: it both shows you some text and lets you edit it, so is it view or controller? The answer has to be that it is part of both. Back when you were working on a teletype in the 1960s the distinction was clearer – think of the ed – but that doesn't mean things were better for the user back then!

It is true that their QAbstractItemModel is rather higher level than a model would normally be. For example, items in it can have a background colour (a brush technically), which is a decidedly view-ish attribute! So there's an argument that QAbstractItemModel is more like a view and your data is the model. The truth is it's somewhere in between the classic meanings of view and model. But I can't see how it's a controller; if anything that's the QT widget that uses it.