PDA

View Full Version : tablemodel row, set / reset background color



linoprit
13th December 2013, 15:28
Hi everybody,
I'm struggling around with a propably simple problem. I use a QSqlQueryModel to display some data. When a cell is double-clicked, the whole row should be marked by changing the background color. This is done by reimplementing the model and overload the data function.
But: when another row is double-clicked the previous coloured row stays marked (but should not). When a button is clicked, or the window is resized, the marking vanishes.
Can I emit some signal to redraw the table view? What happens, when a button is clicked - can I do the same?
I also tried to emit dataChanged and layoutChanged signals from within the data function, but because it's const this seems not to work (compiler complains: passing 'const MyModel' as 'this' argument of 'void QAbstractItemModel::layoutChanged()' discards qualifiers [-fpermissive])

Also I tried repaint(), it had no effect.



QVariant MyModel::data(const QModelIndex &item, int role) const
{
QVariant result = QSqlQueryModel::data(item, role);

int row = item.row();
int col = item.column();

// generate a log message when this method gets called
qDebug() << QString("row %1, col%2, role %3").arg(row).arg(col).arg(role);

switch(role){
case Qt::BackgroundRole:
if (row == active_row) // member active_row is set by a funciton call
{
QBrush redBackground(Qt::red);
return redBackground;
}
break;
}

return result;
}

anda_skoa
13th December 2013, 16:33
If you set active_role in a function call, shouldn't that function emit the signals?
After all that function changes what data() will return afterwards.

Cheers,
_

linoprit
13th December 2013, 20:53
I wasn't clear enough in my description. The QSqlQueryModel is derived to MyModel:


MyModel::MyModel(QObject *parent)
:QSqlQueryModel(parent)
{
active_row = -1; // no row will be colored
}


So, I have nothing to do with setting the color in the application code. All that must be done is to set the active row.


void MyModel::setActiveRow(int row) // called from slot doubleClick
{
active_row = row;
}

The workaround I found meanwhile, is to implement a function, that emits the protected signal "layoutChanged":

void MyModel::__layoutChanged()
{
emit layoutChanged();
}

I have to call it after calling setActiveRow. That's no clean interface, further on there must be a reason, why the signal is protected.
It works so far, but is there any better solution?

anda_skoa
14th December 2013, 10:54
So, I have nothing to do with setting the color in the application code. All that must be done is to set the active row.


void MyModel::setActiveRow(int row) // called from slot doubleClick
{
active_row = row;
}


This method changes the model's data, i.e. MyModel::data() returns different values after that call changed active_row.
So naturally it is the place to emit change signals.



void MyModel::setActiveRow(int row)
{
if (active_row == row)
return; // no change

int oldRow = active_row;
active_row = row;

// de-highlight previously active row
if (oldRow > -1) {
QModelIndex rowBegin = index(oldRow, 0);
QModelIndex rowEnd = index(oldRow, columnCount() - 1);
emit dataChanged(rowBegin, rowEnd);
}

// highlight newly active row
if (row > -1) {
QModelIndex rowBegin = index(row, 0);
QModelIndex rowEnd = index(row, columnCount() - 1);
emit dataChanged(rowBegin, rowEnd);
}
}


Cheers,
_

linoprit
14th December 2013, 20:49
Thank you very much! That was what I didn't understand.
The set-function has to control which parts need to be redrawn, not the data-function.

Code is working. Great!

Cheers,
Harald