How to disable whole column selection of QTableView? - c++

void setSelectionBehavior ( QAbstractItemView::SelectionBehavior behavior )
This function accepts one of three values: for selecting items, for selecting rows and selecting cells.
Question:
I need the case when clicking a cell, it is selected, when clicking row index, row is selected but when clicking column header the whole column is not selected. As I understand this cant be done using this function.
I need the tableview to behave exactly same as when SelectionBehavior::selectItems is set.
But when user clicks on header the column should not be selected.
I am thinking about disabling column selection from QHeaderView but can't find how?

From my application:
// get header from QTableView tableView (replace with your widget name)
QHeaderView *header = new QHeaderView(Qt::Horizontal, tableView);
#if QT_VERSION < 0x50000
// Qt 4.8.1
header->setResizeMode(QHeaderView::ResizeToContents);
#else
// Qt 5.2.0
header->setSectionResizeMode(QHeaderView::ResizeToContents);
#endif
header->setHighlightSections(false); // this is what you want
setHighlightSections(bool) slot is valid for Qt 4 and Qt 5
EDIT:
Excuse for carelessness! This only works if you use SelectRows or SelectItems with SingleSelection. You can find proof in the sources qheaderview.cpp and qtableview.cpp, slots voidQHeaderView::mousePressEvent(QMouseEvent *e); and voidQTableViewPrivate::selectColumn(int column, bool anchor);
For SelectItems can be used this slot:
header->setClickable(false);

Related

QTreeWidgetItem setting not selectable clears the selection

I have a QTreeWidget and I want certain rows to be non select-able, which can be achieved by QTreeWidgetItem::setFlags(treeWidgetItem->flags() & ~Qt::ItemIsSelectable).
The problem is that I have an existing row that is already selected and later I click on the non select-able row, selectedItems() returns an empty list. I want the selected row to keep its selection if the user tries to select a non select-able row.
Should I keep track of the selection and handle this scenario in the code, or this can be achieved somehow else. I'd rather not reinvent the wheel.
Thank you.
Cause
Calling QTreeView::mousePressEvent(event) clears the selection when clicked on a non-selectable item if the selection mode is set to QAbstractItemView::SingleSelection.
Solution
My solution would be to either:
Set the selection mode to QAbstractItemView::MultiSelection,
or (in case this is not desired):
Reimplement the mouse events in a subclass of QTreeWidget in order to bypass the default behavior.
Note: In either case, use the QItemSelectionModel::selectionChanged signal to get the list of the selected items.
Example
Here is an example re-implementation of the mouse events in MyTreeWidget preventing the selection of being cleared by clicking a non-selectable item. The top item is expanded/collapsed on a double click:
void MyTreeWidget::mousePressEvent(QMouseEvent *event)
{
if (indexAt(event->pos())->flags() & Qt::ItemIsSelectable)
QTreeWidget::mousePressEvent(event);
}
void MyTreeWidget::mouseDoubleClickEvent(QMouseEvent *event)
{
QTreeWidget::mouseDoubleClickEvent(event);
QTreeWidgetItem *item = itemAt(event->pos());
if (item && item->childCount())
item->setExpanded(!item->isExpanded());
}
The modified in the described manner version of the provided example is available on GitHub.
Improvements
Special thanks to #eyllanesc for making this example more waterproof by:
adding a check if item is not NULL
replacing itemAt with indexAt

qt QTableWidget programattic select of cell - how to make ready with cursor in?

Environment:
Qt 4.7.1
Qt Creator 2.1.0
c++
Problem:
I have a QTableWidget. I add a row, and then select the first cell.
What I want is to be able to immediately type into the cell after the program selects it, so I don't have to reach for the mouse.
The behavior of the select is to highlight the cell, not put a cursor in it. I have to click on the cell with the mouse before I can type.
Everything I've found so far to do with selection behavior has to do with row, column, or cell selection options; nothing about what the selection of a cell actually does.
Here's my code thus far, works as described; rc is the index to the last row, already determined:
ui->thetable->scrollToBottom();
QModelIndex index = ui->thetable->model()->index(rc, 0);
ui->thetable->selectionModel()->select(index,QItemSelectionModel::Select);
You can use the edit method this way:
ui->thetable->edit(index);
using the index you already computed, or you could connect a custom signal of yours to void QAbstractItemView::edit ( const QModelIndex & index ) slot inherited by QTableWidget's items.

Select item from one ComboBox and remove that item from other ComboBoxes

Im writing an QT application, where I have 3 QComboBoxes, with a list of values. I'm trying to do so, when I select one item in a QComboBox, I will remove it from the other QComboBoxes, and when I select another or nothing, it will reappear in the other QComboBoxes again.
Do you have any ideas for this?
Edit:
I have tried to use QStringList, where I had a slot, which removed it from the other QComboBoxes, but it was very bugged and often inserted 2 whitespaces and the same drink twice.
If all comboboxes contain the same items, then you can use the current index of one combobox to disable and hide that index of other comboboxes.
You can just subclass QComboBox and create a slot like this:
void MyComboBox::disableItem(int index)
{
QListView *list_view = qobject_cast<QListView*>(view());
if(list_view)
{
QStandardItemModel *model = qobject_cast<QStandardItemModel*>(list_view->model());
list_view->setRowHidden(index, true);
if(model)
{
model->item(index, 0)->setEnabled(false);
}
}
}
Then you just connect the QComboBox::currentIndexChanged(int index) signal from other comboboxes to this slot. Do this for all 3 comboboxes.
You should also create a logic for enabling and showing the items again when they shouldn't be disabled. It's almost the same function as the one above. You could just create a list of indexes that should be hidden for that combobox and use that to show all the other indexes.

Trouble embedding a QComboBox in a QTableWidget

I'm making a GUI using QT, and I'd like to have the final entry in my table be a combo box. The idea is to allow the user to chose new items to put in the table from a drop-down list.
What I seem to be having trouble with is embedding this combo box inside a table cell. I've tried this:
table_widget = new QTableWidget(1, 9, Dialog);
table_widget->setObjectName(QStringLiteral("table_widget"));
add_part_combo = new QComboBox(table_widget);
add_part_combo->setObjectName(QStringLiteral("add_part_menu"));
add_part_combo->addItem(QStringLiteral("Import New Items..."));
table_widget->setCellWidget(1, 1, add_part_combo);
If I construct the combo box with Dialog, it puts the combo box in the upper left corner of the dialog (somewhat under the table). If I instead construct it with table_widget, the combo box appears in the upper left of the table (on top of the first header cell). If I don't supply a parent widget, then it doesn't appear at all.
But in no circumstance does the widget actually appear in cell 1,1.
What am I doing wrong?
The row and column parameters passed to setCellWidget are zero-indexed. Also, you don't need to provide a parent for the QComboBox since the QTableWidget will assume ownership of it when you call setCellWidget. As such, your code should be as follows:
add_part_combo = new QComboBox;
add_part_combo->setObjectName(QStringLiteral("add_part_menu"));
add_part_combo->addItem(QStringLiteral("Import New Items..."));
// Note: Row and column 0, not 1.
table_widget->setCellWidget(0, 0, add_part_combo);

QTreeView and QTabWidget to display only selected items of QTableViews

Given two SQLite tables addresses and messages, what is the best way to map them to a QTreeView and QTabWidget in such a way, that if I select one row in a QTableView (which is either mapped to addresses or messages), the selected item is
opened as a new tab to display its contents, and
inserted as an item in the QTreeView to represent an "opened" item.
I've managed to open new tabs by creating two custom QWidgets, one for addresses and one for messages. On selecting a row in the QTableView, the correct (either addresses or messages) QWidget is created and fed with the SQL model and the index. The widget then creates a QDataWidgetMapper and displays the given index. AddressWidget example:
AddressWidget::AddressWidget(QSqlRelationalTableModel *model, QModelIndex &index, QWidget *parent) :
QWidget(parent)
{
// ...
// set up widget mapper
mapper = new QDataWidgetMapper(this);
mapper->setModel(this->model);
mapper->addMapping(streetEdit, this->model->fieldIndex("street"));
mapper->addMapping(houseNumberEdit, this->model->fieldIndex("houseNumber"));
mapper->addMapping(zipEdit, this->model->fieldIndex("zip"));
mapper->addMapping(cityEdit, this->model->fieldIndex("city"));
mapper->setCurrentModelIndex(index);
}
How can I extend this to the QTreeView, so that the tree displays opened items? Each tab in the QTabWidget should have a corresponding item in the QTreeView.
If there is a right way of doing this, please add it or replace my scenario entirely.