PDA

View Full Version : Adjusting the text in a header of a QTableView



Momergil
22nd July 2014, 20:21
Hello!

In one of my apps I have a QTableView implemented with a QTableModelView as model. I have the QVariant headerData(...) method reimplemented in my model's definition and it's supposed to retrieve a junction of two QStrings: one containing a given physical quantity and the other, inside "[ ]", its unity, such as in the image below:

10522

The image shows the result of what I have implemented by now. As you can see, what happens is that the name of some physical quantities are bigger then others (or the name of a pq's unity is bigger then others), leading to the situation you see on the picture. But what I would like to have implemented is a formatted pattern where the pq's unity (with the "[ ]") is always at the far right of the header 'label' while only the PQ's name is at the far left.

How can I implement this?


Thanks,

Momergil

d_stranz
23rd July 2014, 05:34
Derive a class from QHeaderView and use the QTableView::setVerticalHeader() method to install it on your QTableView.

For your custom QHeaderView class, reimplement the QHeaderView::paintSection() method to format the text the way you want (e.g. one call to QPainter::drawText() for the physical quantity text using a left alignment flag, the other for the unit text with a right alignment flag).

You can use the QAbstractItemModel::headerData() method to retrieve your text from the model, just as Qt's own QHeaderView does, using QHeaderView::model(). The logicalIndex argument passed into the paintSection() method is the index into the headerData.

d_stranz
23rd July 2014, 19:35
After thinking about this overnight, it might also be possible to do this without a custom QHeaderView. You may be able to format the string returned by headerData() as Rich Text, and embed the formatting in that using HTML formatting. I do not know if QHeaderView can accept Rich Text for labels, but I would be sort of surprised if it didn't.

Edit: No, it doesn't look like this will work. Formatting a header string with "<b>Some text</b>" results in a header that contains "<b>Some text</b>" :(

Momergil
29th July 2014, 22:54
Thanks for you replies, d_stranz (and for meditating about this "overnight" :P). I'll try to implement your first solution, then, and return here with further questions if necessary.


Thanks,

Momergil

d_stranz
29th July 2014, 23:23
Please post a screen shot when you get it working.

Momergil
30th July 2014, 16:08
Please post a screen shot when you get it working.

WHEN I get it working - what is certainly not what I have now :x

For now I did managed to do what I want, but not properly. If I reimplement the QHeaderView::paintSection() method this way:



void paintSection(QPainter* painter, const QRect& rect, int logicalIndex) const
{
const QString strTemp1 = model()->headerData(logicalIndex,Qt::Vertical).toString().s ection("[",0,0);
const QString strTemp2 = model()->headerData(logicalIndex,Qt::Vertical).toString().s ection("[",1,1);

painter->drawText(rect,Qt::AlignLeft,strTemp1);

if (!strTemp2.isEmpty())
painter->drawText(rect,Qt::AlignRight,"[" + strTemp2);

QHeaderView::paintSection(painter,rect,logicalInde x);
}


what I get is nothing different from standart implementation, since the default implementation of that method takes care of hiding the effects of my modifications. Removing the call to QHeaderView::paintSection() show the text formatted as I want, but all else in the header drawing is not drawn:

10537

So it would seem that I need to Ctrl+C / Ctrl+V the original code inside QHeaderView::paintSection() and edit it as needed, but that move has two problems:

* First, that code calls a private member "d" all the time to see the header's display configuration, and while some of the calling things of "d" can be replaced (e.g.: "d->model" for "model()"), others can't (e.g.: d->clickableSections or d->isSectionSelected(logicalIndex)). At the end I have to comment parts of the code resulting in a partial visualization of the header;
* Second, the text shown by the default QHeaderView::paintSection() uses a QStyleOptionHeader object that has a single QString to be shown, not two to make the compound image, and if I comment its usage and call QPainter::drawText instead, no text is shown.


So how to get around this situation? :S

Momergil
28th August 2014, 21:23
Someone? Help? :)

ChrisW67
28th August 2014, 22:51
Don't call the parent class implementation, because you do not want it drawn that way. You need to work out how the base code draws the cell content including borders, margins, highlighting and mimic that. You cannot, as you note, copy the Qt private code verbatim.

Have you tried simply putting a tab character between the label and unit, i.e. " label\t[unit]", to see what the default rendering does with that?

Another approach. It would be quite easy if the header font was fixed width. Then you could make each string, say, 20 chars and construct with the appropriate number of spaces in between label and unit.

Another approach. Do not display the unit in the label but as a tool tip on the header view cell.

Momergil
29th August 2014, 15:39
Have you tried simply putting a tab character between the label and unit, i.e. " label\t[unit]", to see what the default rendering does with that?

Yes: it puts a space instead of a tab \o/ (that happens both when using the model's headerData() reimplementation as well as when reimplementing QHeaderView's paintSection().



Another approach. It would be quite easy if the header font was fixed width. Then you could make each string, say, 20 chars and construct with the appropriate number of spaces in between label and unit.

Yeah, I did think about a similar solution, but it was quite inefficient... The only difference is that the header should not be size fixed (the result from using a size-fixed font plus a fixed number of letters on each string), so the calculation was based on largest of strings using a QLabel::width() comparison after calling adjustSize(). So as you can see, quite inefficient and it was abandoned =T


Another approach. Do not display the unit in the label but as a tool tip on the header view cell.

No way: its part of the software specification that the header should be so, and it's for a touchscreen embedded Linux device so tool tips are not welcome :)