PDA

View Full Version : How to handle QTableView's behaviour



alitoh
11th May 2011, 14:47
Hello,

I have a QTableWidget item and I'm using delegates with it. One particular case, that proves useful to demonstrate my problem, is with ComboboxDelegate. If I assign a combobox delegate to a certain column of the grid, it goes nice and dandy but on runtime, I need to double click it to start behaving like a combobox.

To better show my problem, here is a picture;
6403http://i.imgur.com/aGL6e.png

So, what I want to happen is that, right when I load that dialog window, for the QTableWidget to make that particular column have a dropDown frame (with the arrow-ey button).

I've tried with

this->setEditTriggers(QAbstractItemView::CurrentChanged | QAbstractItemView::SelectedClicked);
and while it makes it appear as soon as I highlight it, it still doesn't quite feels right.

wysota
11th May 2011, 15:24
Have a look at QAbstractItemView::openPersistentEditor().

alitoh
12th May 2011, 20:11
So ... I was finally able to fix that AND create a proper Colorlist delegate for my QTableView.

Now I want to fix an issue that the QT demos also have; once the delegate's editor closes, the only thing that remains in the cell is the colour's name, not the square with the colour.

As always, I attack a picture to explain it better than I can:

6410
I managed to figure out the fault is with
void ColorlistDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const
{
QItemDelegate::paint(painter, option, index);
}, but I can't quite grasp how to figure out the cells' ( X , Y ) position in relation to the QTableView.

norobro
12th May 2011, 22:23
but I can't quite grasp how to figure out the cells' ( X , Y ) position in relation to the QTableView.See QStyleOptionViewItem::rect


In your paint function, get the color name from your model, convert it to a QColor and call QPainter::fillRect().

alitoh
13th May 2011, 13:27
I can get that much done, but now I can't get the cell to change colour/colour name past the initial setting (whichever it might be). In the previous picture, for example, if I select anything other than Aliceblue, I still get aliceblue on the cell, regardless of my choice in the editor. This is because I changed the default
QItemDelegate::paint(painter, option, index); with something like this
QColor color = index.data().Color;

painter->setBrush(Qt::SolidPattern);
painter->setBrush(color);
painter->setPen(thisPen);
painter->drawRect(option.rect.x() + 5, option.rect.y() + 5, 20, 20);
painter->drawText(option.rect.x() + 27, option.rect.y() + 20, color.);
What does QItemDelegate::paint do in order to handle parameters like it does? I can only find a qitemdelegate.h, but not the implementation.

wysota
13th May 2011, 13:34
You need to implement setEditorData() in the delegate if you want the editor to update its contents on model data change.

alitoh
13th May 2011, 13:46
You need to implement setEditorData() in the delegate if you want the editor to update its contents on model data change.
I already have ColorlistDelegate::setEditorData in my delegate.

my 3 functions are:


void ColorlistDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const
{
//If you remove this line and comment everything else, you'll get the same result as the demo examples. If you dont, you get a colored rect, but not updating accordingly
//QItemDelegate::paint(painter, option, index);
QPen thisPen;
QColor color = index.data().Color;

painter->setBrush(Qt::SolidPattern);
painter->setBrush(color);
painter->setPen(thisPen);
painter->drawRect(option.rect.x() + 5, option.rect.y() + 5, 20, 20);
painter->drawText(option.rect.x() + 27, option.rect.y() + 20, color.name());
}

QWidget *ColorlistDelegate::createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const
{
QComboBox *combo = new QComboBox(parent);
QString cadena = index.data().toString();

QStringList colorNames = QColor::colorNames();
foreach (QString name, colorNames)
{
QPixmap pix(24, 24);
pix.fill(QColor(name));
combo->addItem(QIcon(pix), name, QColor(name));
}

int indice = combo->findText(cadena);
if (indice >= 0)
{
combo->setCurrentIndex(indice);
}

// colorName. cadena;
return combo;
}

void ColorlistDelegate::setEditorData(QWidget *editor, const QModelIndex &index) const
{
QString cadena = index.model()->data(index, Qt::DisplayRole).toString();

QComboBox *comboBox = qobject_cast<QComboBox *>(editor);
int indice = comboBox->findText(cadena);
if (indice >= 0)
comboBox->setItemText(indice, cadena);
}

wysota
13th May 2011, 13:51
Do any of them get executed when the data in the model changes?

alitoh
13th May 2011, 13:58
Yes, they do. I just threw a bunch of breakpoints in the signatures and they all were processed.

Also, QItemDelegate::paint(painter, option, index); DOES update properly, inside ColorlistDelegate::paint, so it must have something to do with me not doing something right in the paint function.

norobro
13th May 2011, 14:26
In paint() try:

QColor color = index.data().value<QColor>();

wysota
13th May 2011, 14:28
What's wrong is probably you querying the model for the default role when looking for the colour. Based on the rest of your code I can assume you use DisplayRole for keeping something else than the colour.

alitoh
13th May 2011, 14:50
In paint() try:

QColor color = index.data().value<QColor>();

Great. Thanks a lot.

Now the updating works, but the name is kinda messed up, for it shows it's hex value instead of the proper noun. Still, this is quite an improvement.
Care to explain a little more what's going on in that line, because I'm barely keeping up with delegates, to be honest.

norobro
13th May 2011, 22:48
. . . I'm barely keeping up with delegates, to be honest.Looks to me like you are handling delegates pretty well :)

Take a look at QVariant::value() in the docs. As long as the color name in your cell is recognized by Qt that statement will work. To see the list of Qt recognized color names use:
qDebug() << QColor::colorNames(); My Debian system lists 148 colors.

Regarding the text, use:
painter->drawText(option.rect.x() + 27, option.rect.y() + 20, index.data().toString());