Qt/C++: Signal for when a QListWidgetItem is checked? - c++

In my form I have a QListWidget which contains checkable QListWidgetItems. I'm looking for a way to capture the event of a QListWidgetItem being checked/unchecked. I don't see any such signal existing for this but maybe I'm wrong. What I'm currently doing is using the QListWidget::itemClicked() signal and checking the checkState of the QListWidgetItem, but this isn't what I want because this event happens any time the item is clicked, not just went the checkmark is toggled. Can anyone give some assistance? Thanks!

Apparently no such signal is provided, your best bet is to use QListWidget::itemChanged(QListWidgetItem* item) , and scan the resulting item->checkState(). This should be a slight improvement over using itemClicked

An extra option is to use your own QAbstractListModel with a QListView. At first this does add some extra code as you need to add your own management code . But you do get a lower level access. Basically because the QListView will ask your model what to do. It will also relay input back to your listmodel where you can hook into it.
Alternatively you could subclass QStandardItemModel and catch certain edits related to changing the checkbox.

Related

Qt combobox: Event when item is selected

i need to know what is the way to run a function when one item of the combobox is selected/clicked, i tried with the standar connect:
connect(ui->combobox,SIGNAL(clicked()),this,SLOT(clickedaction()));
... but it doesnt work.
I dont even need a custom action per element, just the same for all.
Thanks in advance.
There is no signal clicked() in QComboBox.
If you need to detect the item activation either by mouse click or enter pressed then use activated(int index).
connect(ui->combobox,SIGNAL(activated(int)),this,SLOT(clickedaction(int)));

setSelectionModel in QListWidget stops emission of itemSelectionChanged signal

In my QListWidget subclass, when I replace its QItemSelectionModel using setSelectionModel, the list widget stops emitting its itemSelectionChanged signal. In the real code, I'm doing this to install a subclass of QItemSelectionModel, but the problem appears even if I use just a new QItemSelectionModel.
MyListWidget::MyListWidget(QWidget* parent)
: QListWidget(parent)
{
QItemSelectionModel* oldSelectionModel = selectionModel();
QItemSelectionModel* newSelectionModel = new QItemSelectionModel(model(), oldSelectionModel->parent());
setSelectionModel(newSelectionModel);
oldSelectionModel->deleteLater();
}
In the debugger, I can see QItemSelectionModel emit its selectionChanged signal, but QListWidget never emits its corresponding itemSelectionChanged signal.
If I comment out the body of this constructor, things work fine. As before, I can see QItemSelectionModel emit its selectionChanged signal, but now that triggers QListWidget to emit itemSelectionChanged.
It looks as if my call to setSelectionModel causes the connection between QItemSelectionModel::selectionChanged and QListWidget::itemSelectionChanged to break.
By the way, I checked to see if I'm passing the wrong arguments to my new QItemSelectionModel. After I create it, model() and parent() of newSelectionModel are identical to those of oldSelectionModel. I also tried commenting out the call to deleteLater, but that didn't help.
Any help much appreciated.
As per the Qt documentation of QAbstractItemView, setSelectionModel replaces the current selection model and it won't work if setModel() is called after this.
Note that, if you call setModel() after this function, the given
selectionModel will be replaced by one created by the view.
Also, from QListWidget documentation,
QListWidget is a convenience class that provides a list view similar
to the one supplied by QListView, but with a classic item-based
interface for adding and removing items. QListWidget uses an internal
model to manage each QListWidgetItem in the list.
it looks like whenever you add items, the model gets updated / refreshed invalidating your custom selection model (just my thought).
Also, you don't need to delete the old selection model as per Qt docs
Note: It is up to the application to delete the old selection model if
it is no longer needed; i.e., if it is not being used by other views.
This will happen automatically when its parent object is deleted.
However, if it does not have a parent, or if the parent is a
long-lived object, it may be preferable to call its deleteLater()
function to explicitly delete it.
if you want that level of customisation, QListView might be a better option.
QListWidget
QAbstractItemView
Just wondering, have you tried setting custom selection model after adding all the items to the list widget?
This turned out to be a Qt bug. See my two posts on the Qt Forums and the bug report:
http://forum.qt.io/topic/63676/qlistwidget-how-to-prevent-unselect-all/2
http://forum.qt.io/topic/63674/qlistwidget-setselectionmodel-stops-emission-of-itemselectionchanged-signal
https://bugreports.qt.io/browse/QTBUG-50891

QTreeWidgetItem Change - Detect Enter/ESC

I'm developing a Qt/C++ app with a QTreeWidgetItem. When a new item is created I set it setEditable and it allow me to fill directly in the UI the new name.
I'm currently using itemChanged as shown below to catch the change and save it. By default, I set the new item name to new folder and after I can change it manually. My issue is when I'm creating the item, it becomes editable and if I press Enter or Esc without any changes, the itemChanged is not generated.
Is there a command I can use based on SIGNAL/SLOT which can catch the Enter/Esc event. The goal is to triggered the same signals
connect(this, SIGNAL(itemChanged(QTreeWidgetItem*, int)),
this, SLOT(onTreeItemChanged(QTreeWidgetItem*)));
I want to connect Enter/Esc signals to onTreeItemChanged as it's done for itemChanged.
I have tried the use of itemActivated, but it's not triggered even if Enter is pressed.
connect(this, SIGNAL(itemActivated(QTreeWidgetItem*, int)),
this, SLOT(onTreeItemChanged(QTreeWidgetItem*)));
Any idea,
Seb
Sorry to write this in answer, but i still cant comment:
I had some (maybe) similar problems concerning a class derived from QCombobox, which had some spetial behaviour, when to show the popup and when not to.
Everytime Return was pressed domething happend but it wasent a QEventKeyEvent, the solution was to catch QEvent::Shortcut, because the element interpreted this key as shortcut for accept.
-- EDIT --
In such cases i often install a event fiolter and let it just write the events to the output, using a switch statement to filter out uninteresting elements, till i get the culprit.

How to get UI objects to only appear in dialog AFTER button is clicked

I have a dialog that initially has several buttons, let's call them Write, View, OK, and Cancel.
The way it should to is to have the dialog upon creation only have those three buttons and nothing more.
When the Write button is cancelled, it's supposed to create a QLineEdit object in the window above the buttons where the user can enter a new string,which when OK is then clicked will be added to an external QStringList.
When View is clicked, LineEdit should go away (if it's up) and a QListView to come up instead to view everything in that list.
The problem is, I know how to use hide() to get objects that are already in the dialog to NOT appear.
but I am having trouble figuring out how to get an object not currently on the table to appear. I'm new to using Qt so it may be something easy I'm just accidentally overlooking (in fact I hope it is).
Could anyone please offer advice? Thanks!
Just create the items normally and then set:
ui->control->setVisible(false);
after you have created the UI (after ui->setupUi(this);) possibly in the constructor (in case you use code generated by Qt Creator).
And when you need them:
ui->control->setVisible(true);
Doc for this:
http://qt-project.org/doc/qt-4.8/qwidget.html#visible-prop
when using a QListView you should also have a QListModel that provides the data to it, if you only have QStrings then a QStringListModel is premade for you to use
to add a row you can do:
int rows = model->rowCount();
model->addRow(rows,1);
QModelIndex index = model->index(rows,0);
model->setData(index, string);

Qt -how to know whether content in child widgets has been changed?

In QMainWindow I have 2 QSplitters. In that splitters I have QTextEdit, QLineEdits, QTableWinget, Ragio buttons and so on... I want to know if somthing has been chaged after pressing File->New menu button. Is there any general method for doing this?
Somwhere I have read that it is recomended to use isWindowModified() function of QMainWindow, but seems it doesn't work.
setWindowModified() does not propagate the windowModified flag to the parents. This bug is described here: https://bugreports.qt.io/browse/QTBUG-20150. I have just tried it and indeed it did not work.
The isWindowModified() could be useful here since according to http://doc.trolltech.com/4.6/qwidget.html#windowModified-prop it propagates up to the parent.
However, I think you would need to set this yourself. For example, if you clicked the new button which leads to some text being inserted into a QTextEdit, you still need to call QTextEdit's setWindowModified() function - which will then propagate up to your QMainWindow - and you can just check QMainWindow afterwards. (However, you wouldn't know which children were modified)
Maybe you should have a look at QWidget::changeEvent.