PDA

View Full Version : Safe to share a QCompleter?



ChrisW67
5th May 2009, 05:17
Hi All,

Is it safe to share a single QCompleter instance between several line edits on the same dialog? For example, is this safe:


// Set up a completer for the acType
QSqlQueryModel * typeModel = new QSqlQueryModel(this);
typeModel->setQuery("select name from acType", m_model->database());
QCompleter *typeCompleter = new QCompleter(typeModel, this);
typeCompleter->setCaseSensitivity(Qt::CaseInsensitive);
m_ui->acTypeEdit->setCompleter(typeCompleter);
m_ui->acAltTypeEdit->setCompleter(typeCompleter);

Cheers,
Chris

munna
5th May 2009, 06:13
Yes it is safe to share QCompleter. Since QDialog is the parent of the QCompleter object, it gets deleted only when the dialog gets deleted and not when one of the line edits.

ChrisW67
5th May 2009, 08:09
Thanks.
I was more wondering whether the activation of QCompleter on one line edit will adversely affect its operation on another. I guess it comes down to what, if any, state is kept between activations of the QCompleter class.

wysota
5th May 2009, 09:27
I wouldn't share completers among different widgets. You can share the model behind the completers though.

emobemo
5th June 2014, 16:58
wysota, please specify the reason why you would not use one QCompleter for multiple widgets. I am using shared QCompleter now and it works but I want to know if there are some hidden dangers of doing so.

wysota
6th June 2014, 10:14
wysota, please specify the reason why you would not use one QCompleter for multiple widgets. I am using shared QCompleter now and it works but I want to know if there are some hidden dangers of doing so.

If you have more than one widget using the same completer then how are you going to share the completion prefix between them? If one widget contains text "abcd" and the other contains "klmnopq" then you have to ensure every focus change of the widget is going to reset the completion prefix.

Consider the following code (Qt5 + C++11):


#include <QtWidgets>

int main(int argc, char **argv) {
QApplication app(argc, argv);
QWidget w;
QVBoxLayout *l = new QVBoxLayout(&w);
QLineEdit *le1 = new QLineEdit;
QLineEdit *le2 = new QLineEdit;
l->addWidget(le1);
l->addWidget(le2);
QCompleter *cpl = new QCompleter(&w);
le1->setCompleter(cpl);
le2->setCompleter(cpl);
QStringListModel model({"abcde", "abcdef", "abcdefg", "klmno", "klmnopq", "klmnopqr"});
cpl->setModel(&model);
QObject::connect(le1, SIGNAL(returnPressed()), cpl, SLOT(complete()));
QObject::connect(le2, SIGNAL(returnPressed()), cpl, SLOT(complete()));
le1->setText("abc");
le2->setText("klm");
w.show();
return app.exec();
}

See what happens if you request completion (by pressing return key) after switching focus to the other widget -- it shows completions for a wrong widget. In addition to that even if you do update the prefix as the focus changes, you'll get a performance hit as the model has to be refiltered each time. QCompleter is just a couple of bytes of additional memory used, why bother "saving" those several bytes if it can get you in trouble?

emobemo
6th June 2014, 11:47
See what happens if you request completion (by pressing return key) after switching focus to the other widget -- it shows completions for a wrong widget. In addition to that even if you do update the prefix as the focus changes, you'll get a performance hit as the model has to be refiltered each time. QCompleter is just a couple of bytes of additional memory used, why bother "saving" those several bytes if it can get you in trouble?

When you setText() on the QLineEdit the completion prefix of the completer does not change since it changes on keyPressEvent(), so even if you remove the second QLineEdit from the sample code the full list will popup. The other issue about the completer is that it not just keeps couple of bytes of additional memory. The QCompleter has its own internal proxy model to filter and sort data from the source model and if you have a lot of completers you will also have a lot of internal proxy models. However the documentation doesn't say that it should be used only on one widget at a time, but it slightly implies so with the setWidget() method, which in my opinion is redundant. I was wondering if there is some posibility of chrash or other dangerous behaviour when sharing QCompleter.

wysota
6th June 2014, 11:58
When you setText() on the QLineEdit the completion prefix of the completer does not change since it changes on keyPressEvent(), so even if you remove the second QLineEdit from the sample code the full list will popup.
That's not the issue I meant (the one you say is easily avoided by connecting textChanged signal to setCompletionPrefix slot). Focus on first line edit, press "d", focus on second line edit, press return. You'll get completions for the first widget while being focused on the second widget. This cannot be countered using signals and slots (you can do it using event filters though however this makes the objects more tightly coupled).