Select item from one ComboBox and remove that item from other ComboBoxes - c++

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.

Related

How to get different items on qlistwidgets

is it possible to make it so that when selecting different rows from qtablewidget, different text is displayed in qlistwidget? data is added to qlistwidget from qcombobox, and to qcombobox from qstringlist
void MainWindow::on_addService_clicked()
{
auto item = ui->serviceBox->currentText();
ui->serviceListWidget->addItem(item);
}
I called itemSelectionChanged signal processing, but I do not know what to do?
I tried to clear the data from qlistwidget every time I selected a new line, but that's not what I wanted, when I selected a new line, there was a new text in qlistwidget
You can use the itemSelectionChanged signal of the tablewidget and connect it a slot which manipualtes the data in the listwidget.
For details:
https://doc.qt.io/qt-6/qtablewidget.html#itemSelectionChanged
https://doc.qt.io/qt-6/qtablewidget.html#selectedItems

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

Making only one column of QTreeWidget editable // troubleshooting

Mind that this question isn't a duplicate of question Making only one column of a QTreeWidgetItem editable, as it's proposed solution doesn't work.
Hello, so I just want to make only ONE column of my treeWidget editable.
propertyItems.push_back(new QTreeWidgetItem); //gets filled by the while-loop
propertyItems[propertyItems.size()-1]->setText(0, prop.name); //sets the text of the item
propertyItems[propertyItems.size()-1]->setText(1, prop.value);//set the text of the other item
propertyItems[propertyItems.size()-1]->setFlags(Qt::ItemIsEditable);
ui->treeWidget_3->insertTopLevelItem(ui->treeWidget_3->topLevelItemCount(), propertyItems[propertyItems.size()-1]); //appends the items
counter ++;
and
void MainWindow::onTreeWidget3ItemDoubleClicked()
{
if (ui->treeWidget_3->currentColumn() == 2) {
ui->treeWidget_3->editItem(ui->treeWidget_3->currentItem(), ui->treeWidget_3->currentColumn());
}
}
is my approach. ontreeWidget3ItemDoubleClicked is connected with treeWidget::doubleClicked, treeWidget_3 has NO edit-triggers
BUT: when I execute the programm, the QTreeView is just grayed out.
That said, I also tried
propertyItems[propertyItems.size()-1]->setFlags(propertyItems[propertyItem.size()].flags | Qt::ItemIsEditable);
The treeWidget_3 isn't grayed off anymore, but it is still uneditable...
How can I fix this?
BTW: I am a newb to Qt so I might have forgotten something crucial. Sorry in this case.
As mentioned in the documentation:
The QTreeWidgetItem class provides an item for use with the QTreeWidget convenience class.
It means that it won't work for all use cases. The solution is to create your own model and overload the flags(const QModelIndex& index) method returning the appropriate values (basically Qt:: ItemIsEnabled for read-only columns and Qt:: ItemIsEnabled | Qt::ItemIsEditable for the editable one). You can get the column from index.column().
Qt provides an example to start with trees and models.

QTreeView clear selection if selected item is filtered

I have a QTreeView that displays items and a QSortFilterProxyModel for filtering. The QTreeView is configured for SingleSelection and SelectRows.
If a selected item is removed using the filter, the next non-filtered item is selected. I want to change this behaviour. My current idea is to connect to rowsAboutToBeRemoved() and clear the selection if the selected item is removed.
connect(_ui.treeView->model(), &QAbstractItemModel::rowsAboutToBeRemoved,
[this] (const QModelIndex & parent, int start, int end) {//check and clear selection});
However, QT changes the selection to the next item before the rowsAboutToBeRemoved() signal is triggered. So I cannot test if the removed item is the selected item.
Is there a better way to clear the selection if the item gets filtered? I would prefer a solution that does not involve deriving from QTreeView.
rowsAboutToBeRemoved is not a signal, it is a virtual method.
See: http://doc.qt.io/qt-4.8/qtreeview.html
It is not QTreeView, but the ItemModel that has signals for it:
http://doc.qt.io/qt-4.8/qitemselectionmodel.html#selectionChanged
The QTreeWidget has the signal on it's own:
http://doc.qt.io/qt-5/qtreewidget.html#itemSelectionChanged
But for a QTreeView one has to use the ItemModel and/or ItemDelegate.

How to disable the multiple selection of qgraphicsitem?

I am new to Qt. It seems the default for multiple selection of qgraphicsitem is to press ctrl button.
But is it possible to disable this function? Or reload this function?
This is controlled by the items' flags. To disable selection for a particular item, do
item->setFlag(QGraphicsItem::ItemIsSelectable, false);
If you want to completly disable selecting items for a QGraphicsScene regardless of the item flags I would recommend to connect QGraphicsScene::selectionChanged to QGraphicsScene::clearSelection.
If you want to disable multiple selection I suggest the following:
Subclass QGraphicsScene and keep a pointer lastSelection to a QGraphicsItem around
Create a slot connected to QGraphicsScene::selectionChanged
Check selectedItems:
it's empty: nothing to do (=nothing selected)
contains only lastSelection: nothing to do (=selection didn't really change)
contains one item, not lastSelection: set lastSelection to that item (=one item selected for the first time)
contains two items: One must be lastSelection. Remove that one from the selection (lastSelection->setSelected(false);), set lastSelection to the remaining item. (=another item was selected, move selection to it)
You might need to block signals during modifying the selection inside the slot.
The simple way to disable multiple selection is:
Create your own Dirived class from QGraphicsItem.
Overload the protected mousePressEvent function and disable ControlModifier:
protected:
void YourOwnQGraphicsItem::mousePressEvent(QGraphicsSceneMouseEvent *mouseEvent) Q_DECL_OVERRIDE
{
if(mouseEvent->modifiers() & Qt::ControlModifier)
{
mouseEvent->ignore();
}
else
{
QGraphicsItem::mousePressEvent(mouseEvent);
//Do what you want...
}
}