You already are using a delegate to draw the checkbox. You just need to subclass it and draw something different instead of what the default delegate draws, for example by reimplementing QItemDelegate::drawCheck().
montylee (18th December 2008)
I am back with another doubt
I want to add a new row (this should be the 1st row in th table) in my table view with a push button or a label. The label or push button will be named "ALL" and i need to trap the click event on the label/button.
Basically the "ALL" button/label will be used for checking/unchecking all checkboxes at once. So, if user wants to click all checkboxes in the 4th column, he'll click on the "ALL" button in the 4th column to check all checkboxes.
Now, is it possible to add push button or a label in the table model? i used the following code to add one additional row for the push button/label in the table:
So, i have added 1 to the number of rows to add one extra row. But the problem is that the new row is added to the bottom of the table i.e. after all model data. I want to add it to the top of the table.int TableModel::rowCount(const QModelIndex &parent) const
{
Q_UNUSED(parent);
return m_tableData.size() + 1;
}
Secondly, i think i can't return a widget pointer from data() function of the model, so i tried creating a label using the following code in data() function:
This shows a label named "ALL" in the 4th column and last row of the table. Now, how can i trap the click of this and select all checkboxes?if (role == Qt:isplayRole && index.row() >= m_tableData.size() && index.column() == 3) {
return QVariant("ALL");
}
Edit: It seems i can trap the click of the label by trapping click() signal of QAbstractItemView() so it shouldn't be a problem.
But how can i make the label/push button appear on the 1st row instead of the last row? and for selecting all checkboxes, i can use setData() function and pass the value (check or uncheck) in the 2nd argument. Is it correct?
Last edited by montylee; 23rd December 2008 at 22:37.
My GNU/Linux Blog:
http://funwithlinux.blogspot.com
bump.
Anybody knows a solution to my problem?
My GNU/Linux Blog:
http://funwithlinux.blogspot.com
Adding a button to the model doesn't make sense, this would break the logic-presentation separation. What you want is to modify the view. The usual way to do what you want would be simply to make it so that if you click on the header in the appropriate column (the one with checkboxes) all checks will go on or off. But if you want to do it "your way", you can use QAbstractItemView::setIndexWidget() for instance or you can use QAbstractScrollArea::setViewportMargins() to move the viewport down and place the button in the extra space between the header and the viewport.
Of course you might also make the header checkable as in the image below.
thanks! Actually i have placed the button to select all checkbox outside the QTableView for now. Based on the requirement i might be required to place it inside QTableView but still instead of the button i'll simply use a clickable label or icon for the same.
My GNU/Linux Blog:
http://funwithlinux.blogspot.com
ah, i am still working on the checkbox thing. I am able to display a custom checkbox image by subclassing QItemDelegate::drawCheck(). The drawCheck code is as under:
Qt Code:
void CheckboxDelegate::drawCheck(QPainter *painter, const QStyleOptionViewItem &option, const QRect &rect, Qt::CheckState state) const { painter->fillRect(r, brush); r = rect.adjusted(20, -5, 25, 0); if (state == Qt::Checked) /*else painter->drawPixmap(r, QPixmap());*/ }To copy to clipboard, switch view to plain text mode
So, when i select the checkbox, my custom image is displayed. Now, i have some problems:
1) When the QTableView row is highlighted, the row highlight color is drawn over my checkbox and the checkbox doesn't show up on the selected row.
2) How can i give a different checkbox image for the case when a row is highligted? Basically i want to show 2 different checkbox images for highlighted and un-highlighted rows. But since drawCheck() doesn't have QModelIndex as argument, i am not able to find the model index for which drawCheck() is being called. If i can find the model index, i can compare it with the current highlighted row and show a different image for that row.
3) If i don't use this custom delegate, i get a checkbox in the 3rd column properly but the checkbox is displayed to the extreme left (see attached normal_checkbox.png). If i use my custom checkbox (see attached custom_checkbox.png), i see the checkbox properly but if i click on it, it doesn't toggle the checbox. Actual toggle is done when i click on the extreme left on the cell, so inspite of drawing a custom checkbox, the actual checkbox is to the left. Ideally, the toggle should be done, if user clicks anywhere in the cell.
In addition, as you can see from custom_checkbox.png, when a row is selected, the checkbox is not shown. Instead a blue area depicting the actual checkbox is shown.
My GNU/Linux Blog:
http://funwithlinux.blogspot.com
Have you tried using stylesheets instead of doing everything manually? Maybe they would give enough control for you.
no, i am not using style sheets for now. I can't use style sheets as it's not in the project scope and schedule for now.
Please suggest something about my queries...
My GNU/Linux Blog:
http://funwithlinux.blogspot.com
If you are to do what you are currently doing then it certainly is in scope. You are trying to change the looks of the application, that's exactly what they are for.
ya, actually i want to use style sheets but as i mentioned the schedule of project is tight and i can't switch to style sheets as of now. Currently i read all widget coordinates, color values and other stuff from a text file. We need to migrate from text file to CSS but it would most probably be in the next version of the application.
As of now, i have to stick to reading information from a text file and displaying widgets according to the information in the text file.
Please go thru my queries and if you know answer to any of them, it would be of great help to me.
My GNU/Linux Blog:
http://funwithlinux.blogspot.com
You can read settings from a text file and apply them using stylesheets.
From what I see you are doing it the wrong way. You can't modify the rect you paint on. This is the rect that Qt gives you to draw the check on and it supplies the option object to read and apply parameters of the check drawn. If you want something different then provide a full-blown delegate derived from QAbstractItemDelegate. Currently you are strained by the classes you use and instead of getting rid of those constraints you try to work around them, this is not the way.Please go thru my queries and if you know answer to any of them, it would be of great help to me.
hmmm maybe. i'll explore about this. So, if i use CSS can i customize everything i have mentioned in my queries?
okie, so i should not modify the rect argument in the drawCheck() function.
I suppose, if i subclass QAbstractItemDelegate then i can fully customize the checkbox look.
One query:
I have basically no idea about QPainter yet, so does the QPainter code i shared earlier (in void CheckboxDelegate::drawCheck) look ok (except modifying the rect offcourse)? I mean if i subclass QAbstractItemDelegate and rewrite the paint function. In the paint function, i'll just display a checkbox pixmap. In the paint() function, i'll get the information about the current model index too:
so i can display different images when a row is highlighted.virtual void paint ( QPainter * painter, const QStyleOptionViewItem & option, const QModelIndex & index ) const = 0
Now, in this case, can i specify my own rect and draw the checkbox image as i like? You said that in QItemDelegate:drawCheck(), i can't modify the rect but here i am not getting any rect as argument, so is it ok to specify my own desired rect and display the pixmap within that rect?
My GNU/Linux Blog:
http://funwithlinux.blogspot.com
Well... so far we were basically tallking about a custom checkbox, so yes.
Correct.okie, so i should not modify the rect argument in the drawCheck() function.
Yes, but then you also have to handle clicking on the checkbox yourself (detecting the hit area, modifying the model and handle drawing).I suppose, if i subclass QAbstractItemDelegate then i can fully customize the checkbox look.
Yeah, it looks fine although it doesn't do much - you force a fill of a rect with a specified colour and then render a pixmap on top of it. I don't see the point of neither making the fill nor filling with that colour and not some other, but the code itself is ok.One query:
I have basically no idea about QPainter yet, so does the QPainter code i shared earlier (in void CheckboxDelegate::drawCheck) look ok (except modifying the rect offcourse)?
Basically you have to look inside the QStyleOptionViewItem object and fetch all the necessary info from it (like the palette, areas to paint, current state of the item, etc.).I mean if i subclass QAbstractItemDelegate and rewrite the paint function. In the paint function, i'll just display a checkbox pixmap. In the paint() function, i'll get the information about the current model index too:
so i can display different images when a row is highlighted.
Yes, you get the area for the whole item and its current state and you can draw as many checks or other things as you like.Now, in this case, can i specify my own rect and draw the checkbox image as i like?
Yes, provided the rect is within the item's rect which you receive inside the option argument. The painter is clipped anyway, so you wouldn't be able to draw outside of the rectangle even if you wanted to.You said that in QItemDelegate:drawCheck(), i can't modify the rect but here i am not getting any rect as argument, so is it ok to specify my own desired rect and display the pixmap within that rect?
montylee (14th January 2009)
wow, thanks for the reply
things seem a bit clear now, i hope i am able to implement it properly.
BTW, i downloaded ur new article which was in the Qt quarterly newsletter. You really are a Qt guru
Thanks for your help! I might bug you later on again
My GNU/Linux Blog:
http://funwithlinux.blogspot.com
hey, i tried using style sheets in my application. They seem to be so simple and i am able to set most of the things. But i have a problem.
I am using QWidget::setStyleSheet to set the style for widgets especially my QTableView. I am able to set the background color, highlight color etc...
Now the problem is how to set background color or image for the checkbox? Since the checkbox is displayed through the delegate automatically, i am not able to modify it.
I tried using QWidget::setStyleSheet in the QItemDelegate::drawCheck() method but it gives a compilation error since setStyleSheet method can be used only for QApplication and QWidget classes.
Now, you said that using Style sheets i would be able to custom display the checkbox, but i am not able to find any info about using style sheets in delegate drawing. Please help me.
My GNU/Linux Blog:
http://funwithlinux.blogspot.com
I was able to display a checkbox icon in the entire table view cell. I subclassed QStyledItemDelegate class and rewrote the paint function. Here's the code for reference:
Qt Code:
void CheckboxDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const { if (index.column() == 3) { if (state == Qt::Checked) { // Calculate rectangle to draw the checkbox icon // Fill the highlight rectangle painter->fillRect(option.rect, option.palette.highlight()); // Draw "ALL" icon in the first row and checkbox icons in other rows if (index.row() == 0) else } else { if (index.row() == 0) else } } else { painter->fillRect(option.rect, option.palette.highlight()); if (index.row() == 0) } } else { QStyledItemDelegate::paint(painter, option, index); } }To copy to clipboard, switch view to plain text mode
My GNU/Linux Blog:
http://funwithlinux.blogspot.com
georgep (15th February 2009)
Thanks for great advice on this great thread !!!!
Problem: can anyone tell me how to move the checkbox to the RIGHT ??
I think it has something to do with const QStyleOptionViewItem &option;
but i simply cant do: option.decorationPosition=QStyleOptionViewItem::Ri ght;
I am subclassing QStyledItemDelegate if it matters...
Check box is not a decoration so you can't do it this way. You have to provide your own delegate that handles painting and clicking the box in the new position. There is a chance you can move the checkbox to the right if you manage to convince the item it should be there in the first place (for example by reimplementing a proper function from the QStyle subclass you use).
Bookmarks