Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do you stick a QDialog into a custom delegate?

Tags:

qt

When you create your own custom delegate, you implement createEditor(), setEditorData() and setModelData(). I am facing the following problem. All the examples of createEditor() that I have seen use simple things like QComboBox or QLineEdit, which don't have show() or exec() member functions, and whenever I try to use QDialog, the program has undefined behavior (I think) and the QDialog shows up but acts crazy. I did get my program to work, using some signal/slot magic, but I'd like to implement it using the standard pattern described, for example, here: http://cep.xray.aps.anl.gov/software/qt4-x11-4.2.2/model-view-delegate.html how can I do it?

To elaborate on what happens when I face that undefined behavior, if I set QDialog's parent in createEditor(), then QDialog doesn't show at all, if I don't set it, it shows up and then when I drag it around it disappears (this is wrong anyway and I think I have to always set the parent because otherwise I'll have a memory leak). I guess, now my question boils down to: how can I make QDialog show properly? I tried sticking show() and exec() into different parts of setEditorData(), setModelData() and createEditor() but nothing works properly.

like image 279
Pavel Avatar asked Oct 26 '16 13:10

Pavel


1 Answers

An editor delegate must be a widget that's embedded in the view. It is free to create a top-level window if it wishes so, of course, but it must control that window's visibility and focus appropriately. Namely, if the editor widget's visibility changes, so must the dialog's, and if the editor widget gains focus, you must transfer the focus to the dialog for good UX.

The solution is to have an empty QWidget that has a child QDialog that is a top-level window:

QWidget * MyDelegate::createEditor(QWidget * parent, 
                  const QStyleOptionViewItem &, const QModelIndex & index) const
{
  auto editor = new QWidget{parent};
  auto dialog = new QDialog{editor, Qt::Window};
  ...
  return editor;
}

The reason that your QDialog-editor didn't work is that its geometry and state were managed by the view. The view acts like a layout for the editors/delegates. You need to insert an intervening widget to shield your dialog from such manipulation. Admittedly, the views could check the editor's flags and refrain from adjusting geometry etc. if it had the Qt::Window flag set, but it's so rare that I don't blame anyone for not implementing it. You're free to submit a change to Qt, of course!

like image 137
Kuba hasn't forgotten Monica Avatar answered Sep 18 '22 09:09

Kuba hasn't forgotten Monica