Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to unset a flag in Qt?

Tags:

c++

qt

I am using the following code to disable editing of a cell in a QTableWidget.

ui->tableWidget_1->item(row,col)->setFlags(Qt::ItemIsSelectable|Qt::ItemIsEnabled);

This works fine. I don't understand how to undo this i.e. how do I make the cell editable again?

I've tried calling the function again in case that toggles it. I've tried calling the same function but with a ~ in front of the flags as seen elsewhere. I'm not sure if I really understand how flags work in Qt.

like image 612
t020608 Avatar asked Jul 31 '17 10:07

t020608


2 Answers

Item flags are just bits of an integer number. To set or unset a flag, you need to get that number:

auto currentFlags = ui->tableWidget_1->item(row,col)->flags();

and write one or zero respectively to desired position, leaving other bits untouched. For example, to enable editing you can do the following:

auto currentFlags = ui->tableWidget_1->item(row,col)->flags();
ui->tableWidget_1->item(row,col)->setFlags(currentFlags | Qt::ItemIsEditable‌);

Analogically, this code disables editing:

auto currentFlags = ui->tableWidget_1->item(row,col)->flags();
ui->tableWidget_1->item(row,col)->setFlags(currentFlags & (~Qt::ItemIsEditable‌));

Bitwise oring allows you to set more than one flag at once. Your example works because setting Qt::ItemIsSelectable|Qt::ItemIsEnabled leaves zero at Qt::ItemIsEditable‌ flag's position, as it leaves zeros everywhere except specified flags. setFlags does not raise more flags to one, it just completely overwrites all flags with specified ones.

And this is not only how flags work in Qt, it's how bitwise operations work in C++ in general. Most APIs (including Qt) just use this behavior to implement flags abstraction.

like image 110
Sergey Avatar answered Nov 13 '22 17:11

Sergey


Sergey's answer is usually what people do, but there's also an alternative with Qt.

Qt wraps enum flags in the QFlags class template. This happens automatically for enums defined by Qt.

You can use the setFlag() function to set and unset individual flags:

auto item = item(row, col);
auto flags = item->flags();
flags.setFlag(Qt::ItemIsEnabled, false).setFlag(Qt::ItemIsSelectable, false);
item->setFlags(flags);

setFlag() can be chained (as can be seen in the example) since it returns a reference to the flags object. So you can write something like:

item->setFlags(item->flags()
    .setFlag(Qt::ItemIsEnabled, false)
    .setFlag(Qt::ItemIsSelectable, false));

Which is shorter, but still a bit verbose, which is why some people stick to the bit-wise operators to manipulate the flags (which are bit masks) directly. But using setFlag() is a good option that you might find more readable.

like image 11
Nikos C. Avatar answered Nov 13 '22 18:11

Nikos C.