In Qt, there are 3 classes that interact with each other: Style, Option and Widgets. When a widget is being prepared to be drawn, it is passed to an Option. The Option is essentially a state from the Widget. This Option is then passed to the Style, which will use these parameters/variable from the Option to render it to the screen.
My question is, what purpose does the Option serve? Why would the Style not take the Widget as a parameter to be drawn and pull the attributes directly anyway, it does this for the Option? It seems that everything the Option does, could be moved to the Style and save creating this container class. Additionally, why it is called an "option", I find the name very misleading as options generally refers to a series of choices, nothing to do with a data transfer object.
While the main purpose of QStyleOption classes is to be used when a widget has to be drawn, their utility is far broader and not limited to that.
This is partially explained in the Style and Style Aware Widgets documentation:
Thanks to QStyleOption, it is possible to make QStyle draw widgets without linking in any code for the widget. This makes it possible to use QStyle's draw functions on any paint device, i.e., you can draw a combobox on any widget, not just on a QComboBox.
This means that we could virtually draw any standard Qt widget even in a basic QWidget. Including drawing a non existing widget on a pixmap.
Interestingly enough, this is also what some widgets and styles do. For instance, QStyleOptionFrame is normally used by QFrame classes to draw its borders (and, possibly, the background), but that option is also used by QLineEdit, which does not inherit from QFrame, to draw the "inset border" of its field.
For example, an item view could just display (draw) a combo box, and create a real one only when user interaction is required, which is clearly better than creating hundreds or thousands of widgets even if only one will always be used at the same time.
Some styles use the same function to draw the indicator of a QCheckBox and that of a checkable item in a model view, but with different QStyleOption classes. That wouldn't be possible if the style could only draw things by querying the widget, and would require separated functions and parameters.
The style option also provides an abstraction layer between the widget and the style, so that the style doesn't need to continuously query the widget for any of its internal functions: once the option is initialized (possibly, by the widget), everything is already set on a simpler object that also has faster access to its members for performance reasons[1].
Moreover, as explained above, an option could be used for a different widget for practical reasons. If QStyleOptions didn't exist, the style would need to query the widget, possibly differentiating depending on the type, and all that by calling widget functions. The style option makes that easier, as the style already has everything it needs in a separate, simpler object that is easier to access and much more flexible.
In fact, a style option instance may also be reused or easily copied, so that there is again no need to continuously querying the widget (possibly for the same result). Qt item views normally create just one QStyleOptionViewItem when painting begins, and only updates it when necessary, then finally discards it when painting ends.
Some styles often internally create copies (direct or derivate) of a received style option in order to make complex function calls or proper compositing in drawing.
The simplicity of QStyleOptions is also useful for some complex widgets (for example, spin boxes): with a simple initStyleOption()
function call, all the current states of the widgets are set, and the style will only need to check what it matters to it. Again, if no QStyleOptions existed, the style would need to make individual (and costly) function calls every time.
Another important aspect is that widgets may use QStyleOptions to query the style about aspects that may not be reflected by the current widget state. A typical case is for sizeFromContents()
which may result in a widget state/size change depending on a possible state (eg. a currently empty QComboBox). That wouldn't be easy without an intermediate abstraction object.
Finally, the naming aspect is trivial. While I may agree that the term "option" could be misleading, it probably originated in earlier Qt versions[2] when QStyleOptions were an optional argument and contained specific options for a widget, which the style might have chosen to use (or ignore). That name remained (probably for backward compatibility), even though the "option" is now mandatory for almost all QStyle functions.
[1] When using Python, the only difference in accessing "values" of a QObject or QStyleOption is that the former is normally done with getter and setter functions (which need to be called), while style option attributes are direct, similarly to object attributes; in C++ the difference is that style option members are accessed using .
(as in Python) or the ->
operator, which provides better performance for things that need to respond fast as things like painting or layout management require.
[2] see the archives: "Some QStyle functions take an optional argument specifying extra information that is required for a paritical primitive or control. So that the QStyle class can be extended, QStyleOption is used to provide a variable-argument for these options." (emphasis mine).