PDA

View Full Version : Help using the QTreeWidget persistent editor.



Billy Lee Black
29th June 2007, 17:15
Hello guys, I´m new here and I am working with QT4.

I want to use the persistent editor of the QTreeWidget in order to edit the contents of it.

So, I connect the double click signal with a slot that calls the QTreeWidget::openPersistentEditor.

The problem is that I need to catch when the user finishes editing the item or when it loses focus.

I connected the itemChanged signal with a slot that calls the QTreeWidget::closePersistentEditor.

It works fine when the user actually edit the item and presses the "Enter" button on the keyboard. But when the user presses the keyboard "Enter" without changing the item content, the signal itemChanged is not emitted and I can´t close the editor!

Another way I found to use this editor was creating another slot connected with the double clicked signal that instead of calling the openPersistenEditor method, it does like this:

item->setFlags(item->flags() | Qt::ItemIsEditable);
treewidget->editItem(item, 0);
item->setFlags(item->flags() & ~Qt::ItemIsEditable);


It works fine, the editor closes when it loses focus or when the user presses "Enter".

But, I really need to catch when this editor is closed to do some checking in the contents of the item modified.

Is there any signal that is called when this editor is closed?



I thank any help!!!!

marcel
29th June 2007, 23:09
You could implement a simple version of an item delegate, based on the default, except you override QAbstractItemDelegate::editorEvent.

Here you can see when the enter key gets pressed and emit any signal or do whatever you need.

Regards

jpn
29th June 2007, 23:17
I want to use the persistent editor of the QTreeWidget in order to edit the contents of it.
...
The problem is that I need to catch when the user finishes editing the item or when it loses focus.
I'm not sure if I missed something but do you actually need persistent editors at all? Is a normal editor somehow insufficient?


Is there any signal that is called when this editor is closed?
QAbstractItemDelegate::closeEditor()

Billy Lee Black
2nd July 2007, 14:51
Yes, I need to use the persistent editor because it is quicker and easier for the user to use it.

Well, I´ve never used these itemDelegates, can you explain me how to use it?

Can I use it along with the QTreeWidget?

The QTreeWidget emits this QAbstractItemDelegate::closeEditor() signal????

thanx again for the help!

jpn
2nd July 2007, 15:03
Yes, I need to use the persistent editor because it is quicker and easier for the user to use it.
One could get pretty similar functionality by QAbstractItemView::setEditTriggers(QAbstractItemVi ew::CurrentChanged) (http://doc.trolltech.com/4.3/qabstractitemview.html#editTriggers-prop) too. This way an editor would be opened up right away after user switches current item in the view. Still there would be only one editor open at time which would save resources quite a bit.


Well, I´ve never used these itemDelegates, can you explain me how to use it?
Delegate Classes (http://doc.trolltech.com/4.3/model-view-delegate.html)


Can I use it along with the QTreeWidget?
Yes, delegates can be used with any view inheriting QAbstractItemView, see QAbstractItemView::itemDelegate().


The QTreeWidget emits this QAbstractItemDelegate::closeEditor() signal????
No, it's the delegate. Again, see QAbstractItemView::itemDelegate(). :)


connect(treeWidget->itemDelegate(), SIGNAL(closeEditor(QWidget*,QAbstractItemDelegate: :EndEditHint)), ...);

Billy Lee Black
2nd July 2007, 16:26
Ok, I have used this connect you told me:

connect(treeWidget->itemDelegate(), SIGNAL(closeEditor(QWidget*,QAbstractItemDelegate: :EndEditHint)), ...);


Still, it isn´t emiting this closeEditor signal when the QTreeWidget´s persistent editor is closed.

I´ve tried implementing a delegator and reimplementing that QAbstractItemDelegate::editorEvent.

But, I will have to check if teh item loses focus, if the user presses enter to end the item editing and other events so I can manually close the editor.

Isn´t there any other easier way to use de persistent editor of the QtreeWidget?

As I said, using this code here, works fine, making the editor open and it will close if the item loses focus or the user presses enter:

item->setFlags(item->flags() | Qt::ItemIsEditable);
treewidget->editItem(item, 0);
item->setFlags(item->flags() & ~Qt::ItemIsEditable);

But still, I can´t catch when the editor is closed. The default QTreeWidget delegate doesn´t emit the closeEditor() signal.

With QT3 this was so easy to do, the QListView emitted the QListView::itemRenamed signal whenever the persistent editor of it was closed, even if the item name didn´t changed at all.

The QTreeWidget doesn´t emit the itemChanged signal if the user opens de persistent editor but do not change the text of the item.

jpn
2nd July 2007, 18:24
I'd like to try to help out with implementing it without the need of persistent editors. I'm convinced it's possible to achieve (of course not identical functionality, but very close to), but I'd need to know more about the task. For example, what does have to be done when an editor loses focus? A screenshot could help in understanding the problem too. :)

Filling a view with persistent editors is basically same than filling a layout of editor widgets and not using a view at all. Unfortunately, using lots of child widgets is a bit inefficient and eats resources a lot more than a view with a single editor.

Billy Lee Black
3rd July 2007, 02:38
Well, let me try to describe:

I have a QTreeWidget and I need to use the persistent editor to edit the text of it´s items because it is better in an aplication than opening a small dialog for the user to edit the item.

What I need to do, is check every time the user edits the text of an item if it isn´t equal to the text of the other items. In order to do that, I have to catch when the editor gets closed (know when the user has finished editing the item). So, if there is another item with the same text, than I show a QMessageBox warning the user the item must have a different text, so I open the persistent editor again for the user to change the text.


That´s about it.

Thanx for all your help people!

jpn
3rd July 2007, 09:43
What I need to do, is check every time the user edits the text of an item if it isn´t equal to the text of the other items. In order to do that, I have to catch when the editor gets closed (know when the user has finished editing the item).
QLineEdit is used as editor provided that it's textual data. Perhaps you could make use of QLineEdit::editingFinished()?


class ItemDelegate : public QItemDelegate
{
Q_OBJECT

public:
ItemDelegate(QObject* parent = 0)
: QItemDelegate(parent) { }

QWidget* createEditor(QWidget* parent, const QStyleOptionViewItem& option, const QModelIndex& index) const
{
QWidget* editor = QItemDelegate::createEditor(parent, option, index);
// following cast & check aren't actually needed for the connect
// you'll get a warning if it's not a QLineEdit (in case of other than textual data)
QLineEdit* lineEdit = dynamic_cast<QLineEdit*>(editor);
if (lineEdit)
connect(lineEdit, SIGNAL(editingFinished()), this, SIGNAL(editingFinished()));
return editor;
}

signals:
void editingFinished();
};

// usage:
treeWidget->setItemDelegate(new ItemDelegate(treeWidget));
connect(treeWidget->itemDelegate(), SIGNAL(editingFinished()), ...);

You could also use QSignalMapper if you want to pass the editor widget as signal parameter.



So, if there is another item with the same text, than I show a QMessageBox warning the user the item must have a different text, so I open the persistent editor again for the user to change the text.
Idea: make corresponding editor backgrounds red or something instead of popping up annoying message boxes ;)

Billy Lee Black
3rd July 2007, 15:48
Well, thanx man, now I advanced a lot with my problem.

But now I have another.

I do this connect you said, but my dialog doesn´t catch that signal.

I did like this in my dialog:

treeWidget->setItemDelegate(new ItemDelegate(treewidget));
connect(treeWidget->itemDelegate(), SIGNAL(finishedEditing()), this, SLOT(closedEditor()));

I checked to see if the delegate is really emiting the signal and it is emiting alright. But this connect simply doesn´t catch the signal.

And in the output window, there is no message form QT warning that the signal or the slot do not exist.

Do you have any idea why is this happening?

jpn
3rd July 2007, 19:09
Just to assure, did you rename the signal to "finishedEditing" or could it be a typo? Can you see a warning by QObject::connect() if you make it fail on purpose?

Billy Lee Black
3rd July 2007, 21:07
Yes, I just renamed the signal.

And no, that´s the strange part. I don´t get any warning about the signal or the slot, not even when my application is running.

joshlareau
7th July 2007, 22:25
Billy Lee, I implemented the custom delegate just like jpn suggested and I'm able to successfully connect the editingFinished() signal to a suitable slot in my application. I'm not sure what is happening with your implementation. Are you sure that the MOC is being run on your custom delegate class? Did you define it in it's own header? Have you checked the response from connect to make sure it's true?

Billy Lee Black
18th July 2007, 20:59
Sorry for replying so later.

Well, I couldn´t make it work here, so I ended up doing things in another way. I check the items only when I click the window´s apply button.


But thanks for your help, people.
Perhaps later I will try making a new code just to test this delegate better. Than I will post the results here.


Thanks again.