PDA

View Full Version : How to issue signal each time a row is edited in QListWidget?



TheIndependentAquarius
23rd February 2012, 10:13
class genericTaskList : public QListWidget
{
Q_OBJECT
public:
QListWidgetItem *defaultText;

genericTaskList (QWidget *parentWidget)
{
setParent (parentWidget);
setFixedSize (445, 445);

defaultText = new QListWidgetItem ("Double click here to compose the task");
defaultText->setFlags (defaultText->flags () | Qt :: ItemIsEditable);

insertItem (0, defaultText);

QObject :: connect (this, SIGNAL (currentRowChanged (int)), this, SLOT (addDefaultText (int)));
}

public slots:
void addDefaultText (int rr)
{
std::cout << "\ndsklfjsdklfhsdklhfkjsdf\n";

insertItem (++rr, defaultText);
}
};

This code is supposed to issue a signal each time the row gets edited.
After I call "insertItem" in the constructor, the signal is issued. But, that's it. It never gets issued after that - no matter how many times I edit the row.

What am I missing?

mentalmushroom
23rd February 2012, 10:37
currentRowChanged signals that another row is active (not that data changed), e.g. when you select a different item. Take a look at dataChanged signal.

TheIndependentAquarius
23rd February 2012, 10:44
That is VERY helpful again. Thanks very much. BTW, signal's name is "itemChanged", not "datachanged".

See: from here: http://developer.qt.nokia.com/doc/qt-4.8/qlistwidget.html#currentItemChanged


void QListWidget::currentItemChanged ( QListWidgetItem * current, QListWidgetItem * previous ) [signal]
This signal is emitted whenever the current item changes.
previous is the item that previously had the focus; current is the new current item.




void QListWidget::currentRowChanged ( int currentRow ) [signal]
This signal is emitted whenever the current item changes.
currentRow is the row of the current item. If there is no current item, the currentRow is -1.


How could I have guessed that that changes the selection not the text?

mentalmushroom
23rd February 2012, 10:58
I didn't try itemChanged, but I suppose it is not the one you need again. It's all about current item, row etc. As far as I understood you need to handle the event when text is changed (not the focus or selection). So dataChanged should be the right one. It is inherited from QListView.

Apologize, itemChanged seems to be the right one, somehow I was thinking about currentItemChanged.

lclemens@gmail.com
20th June 2015, 21:49
At first it seems like QListWidget::itemChanged is the way to go, but soon you run into a problem: the signal is sent for everything - inserts, removes, changing colors, checking boxes, etc! So then you end up trying to put in flags and filter everywhere by intercepting various signals to find out if editing was the actual event. It gets very messy.

There is also QAbstractItemModel::dataChanged , which would seem like a good solution. It even has a parameter "const QVector<int>& lstRoles" so you could scan for Qt::EditRole and see if it was really edited. Alas, there's a catch - it gets called for everything just like QListWidget::itemChanged and unfortunately, for QListWidget anyway, the roles parameter is always empty when it's called (I tried it). So much for that idea...

Fortunately, there's still hope... This guy's solution does the trick! :

http://falsinsoft.blogspot.com/2013/11/qlistwidget-and-item-edit-event.html

He uses QAbstractItemDelegate::closeEditor, but I prefer using QAbstractItemDelegate::commitData.

So make a connect like so...



connect(ui.pLstItems->itemDelegate(), &QAbstractItemDelegate::commitData, this, &MyWidget::OnLstItemsCommitData);


Then implement the slot like this...



void MyWidget::OnLstItemsCommitData(QWidget* pLineEdit)
{
QString strNewText = reinterpret_cast<QLineEdit*>(pLineEdit)->text();
int nRow = ui.pLstItems->currentRow();
// do whatever you need here....
}


Now you have a slot that gets called only when the list item's text has been edited!