PDA

View Full Version : How to make QListWidget items editable?



montylee
29th September 2008, 11:43
I am using Qt 4.3.4. I have created a list widget having some items. I want the items to be editable so that user can modify the contents of the list widget dynamically by double clicking on the list widget item.

Here's what i am doing:


connect (sampleList, SIGNAL (itemDoubleClicked (QListWidgetItem *)), this, SLOT (test (QListWidgetItem *)));

void test (QListWidget *item)
{
sampleList->editItem (item);
}

While creating the list widget items, i am setting the item flags as:


item->setFlags (item->flags () & Qt::ItemIsEditable);


Now, when i run my application, and double click on the list widget item to edit, i get the following error on the terminal:


"edit: editing failed"

Now, my query is that how can i make the list widget items editable? I tried modifying the test () function given above as:


void test (QListWidget *item)
{
sampleList->openPersistentEditor (item);
}

Using this code, i am able to edit the item but i am not sure if this is the correct way of doing it. Also, i am not sure about the usage of openPersistentEditor ().

jpn
29th September 2008, 18:22
Here's what i am doing:


connect (sampleList, SIGNAL (itemDoubleClicked (QListWidgetItem *)), this, SLOT (test (QListWidgetItem *)));

void test (QListWidget *item)
{
sampleList->editItem (item);
}

This is not needed, you can safely throw this piece of code to trash. :) See QAbstractItemView::editTriggers.



While creating the list widget items, i am setting the item flags as:


item->setFlags (item->flags () & Qt::ItemIsEditable);

It should be:

item->setFlags (item->flags () | Qt::ItemIsEditable);

montylee
30th September 2008, 07:47
wow, thanks a lot!!!
The solution you gave worked :) I just had to replace "&" with "|" and the code worked.

Strangely, even if i don't give edittrigger, i am able to edit it but i am still using edit triggers as "QAbstractItemView::AllEditTriggers".

Thanks a lot for your help!!!

Now, i have to check whether the data entered by the user in the list box item is a number or not. If it is not a number, i have to revert it to the original contents. Other option is to allow the user to enter only numeric values... if you have any idea about that, then please post...i think Qt has a built-in class for validating the input. I'll try to search the QT documentation.

jpn
30th September 2008, 08:37
Now, i have to check whether the data entered by the user in the list box item is a number or not. If it is not a number, i have to revert it to the original contents. Other option is to allow the user to enter only numeric values... if you have any idea about that, then please post...i think Qt has a built-in class for validating the input.
The delegate is responsible for creating editors. You could reimplement QItemDelegate::createEditor() or QStyledItemDelegate::createEditor(), call the base class implementation to create the editor, check if it's a QLineEdit, and install a validator if it is.

montylee
30th September 2008, 13:14
is it necessary that i used a delegate for this?
Can i use the existing code and add number validation to it?

jpn
30th September 2008, 14:12
What's wrong with delegates? :) Well, QStandardItemEditorCreator is the other way but then you'll have to subclass QLineEdit (and you'll loose the "ExpandingLineEdit" which is provided by the editor factory by default). I'd definitely go with delegates myself.

montylee
1st October 2008, 05:58
my doubt is whether i can use delegates with my existing code or do i have to modify my existing code?
The existing code just uses "IsEditable" flag and i am able to get a line edit when i click on the editable field. I am not attaching any line edit explicitly with the list widget. Can i use delegate with my existing code?

Actually i have no idea about delegates, so where should i start? Is Qt documentation enough or should i use any other good online tutorial?
I think there is a input validation example given along with Qt, i'll try to go through it.

montylee
1st October 2008, 07:44
Just checked the LineEdit example that came with Qt. For allowing only integer values in a line edit, following can be used:


QValidator *validator = new QIntValidator(100, 999, this);
QLineEdit *edit = new QLineEdit(this);

// the edit lineedit will only accept integers between 100 and 999
edit->setValidator(validator);

Now, since i don't have an explicit Line edit attached to the List widget item, i am trying to find out if i can set the validator for the defaul line edit i am getting when i edit the list box item.

Is it possible?

spirit
1st October 2008, 08:12
use a delegate, Qt Assistant is enough for this. look also an example in QTDIR/examples/itemviews/spinboxdelegate/. you don't need to change your code, you only need to create a new class inherits from QStandartItemDelegate and set it for a view using


void QAbstractItemView::setItemDelegate ( QAbstractItemDelegate * delegate )


so, in you case (of cource if you already created a delegate) setting the delegate should look like:


....
m_myListWidget = new QListWidget(this);
m_myListWidget->setItemDelegate(new MyItemDelegate());
...

montylee
1st October 2008, 13:02
Thanks for the replies!

I was able to use the delegate in a small application having a QListWidget but the same code is not working in my application :(

I am using same code as given in the QTDIR/examples/itemviews/spinboxdelegate example. I have made changes to the main.cpp of the example. Here are the contents:


#include <QApplication>
#include <QtGui>
#include <QString>
#include <QListWidget>
#include <QListWidgetItem>

#include "delegate.h"

int main(int argc, char *argv[])
{
QApplication app(argc, argv);
QListWidget *list = new QListWidget;

SpinBoxDelegate delegate;
list->setItemDelegate(&delegate);

QListWidgetItem *Item1 = new QListWidgetItem(list);
Item1->setText("1");
Item1->setFlags (Item1->flags () | Qt::ItemIsEditable);
QListWidgetItem *Item2 = new QListWidgetItem(list);
Item2->setText("2");
QListWidgetItem *Item3 = new QListWidgetItem(list);
Item3->setText("3");

list->setWindowTitle(QObject::tr("List Box Delegate"));
list->show();
return app.exec();
}

Now, this code is working properly i.e. when i double click on the 1st list widget item, a combo box appears which allows me to choose or enter only integer values.

When i used the same code in my application, it didn't work. In my application i created a list widget having 3 items. The list widget items are visible normally but when i set the delegate using "setItemDelegate", the list widget comes out as empty i.e. no contents are getting displayed in the list widget.

Here's a part of my code:
The header consists of several classes, i have added the delegate class to the same header.

test.h:

// Class for custom spin box delegate
class SpinBoxDelegate : public QItemDelegate
{
Q_OBJECT

public:
SpinBoxDelegate(QObject *parent = 0);

QWidget *createEditor(QWidget *parent, const QStyleOptionViewItem &option,
const QModelIndex &index) const;

void setEditorData(QWidget *editor, const QModelIndex &index) const;
void setModelData(QWidget *editor, QAbstractItemModel *model,
const QModelIndex &index) const;

void updateEditorGeometry(QWidget *editor,
const QStyleOptionViewItem &option, const QModelIndex &index) const;
};

// Class for "Test" Screen Dialog
class Test: public QDialog
{
Q_OBJECT

public:
Test();

private:
QListWidget *m_pList;
};


test.cpp


Test::Test ()
{
m_pList = new QListWidget;
m_pList->setAlternatingRowColors (TRUE);

// Set delegate to combo box while editing the scenario events list widget
SpinBoxDelegate delegate;
m_pList->setItemDelegate (&delegate);

QListWidgetItem *Item1 = new QListWidgetItem (m_pList);
Item1->setText (tr ("1"));
Item1->setFlags (Item1->flags () | Qt::ItemIsEditable);
QListWidgetItem *Item2 = new QListWidgetItem (m_pList);
Item2->setText (tr ("2"));
QListWidgetItem *Item3 = new QListWidgetItem (m_pList);
Item3->setText (tr ("3"));

m_pList->setCurrentRow (0);

QVBoxLayout *verLayout1 = new QVBoxLayout;
verLayout1->addWidget (someLabel);
verLayout1->addWidget (m_pList);
}



As i mentioned, my code works normally and all items inside the list widget are visible. But when i use setItemDelegate(), everything disappears from the list widget. Only the List widget is visible.

Any ideas?

jpn
1st October 2008, 13:07
The delegate goes out of scope. Allocate it on the heap:


SpinBoxDelegate* delegate = new SpinBoxDelegate(m_pList);
m_pList->setItemDelegate(delegate);

spirit
1st October 2008, 13:10
try to create a delegate in the heap, i.e. using new operator.
so, code should like this


m_pList->setItemDelegate (new SpinBoxDelegate);

montylee
1st October 2008, 13:27
wow!!! it worked...
my problem is now resolved.
thanks a lot to both of you!

I have one more query:
I am not sure why the delegate goes out of scope...is it because the List widget variable is not local?

spirit
1st October 2008, 13:30
because, QListWidget has global scope in a class and the delegate local scope in ctor of the class.

montylee
3rd October 2008, 10:57
thanks for the clarification :)