Results 1 to 16 of 16

Thread: How does QComboBox uses/calls QCompleter ?

Hybrid View

Previous Post Previous Post   Next Post Next Post
  1. #1
    Join Date
    Jan 2008
    Location
    Alameda, CA, USA
    Posts
    5,349
    Qt products
    Qt5
    Platforms
    Windows
    Thanks
    318
    Thanked 872 Times in 859 Posts

    Default Re: How does QComboBox uses/calls QCompleter ?

    In general, you do not derive from QCompleter to create a custom completer. You instead derive from QAbstractItemModel and set that on your QCompleter as the model it uses to find completions for a partial phrase. The combo box and completer handle the interaction between them and you don't need to care how that works, just what your model does when asked.

    If your completions can be simplified to a list of strings, then you can use the version of QCompleter that accepts a QStringList argument, and internally QCompleter will insert that into a QStringListModel.

    If your completions are more complex, then you may need to implement your own model. In this case, you have almost total control over how QCompleter searches your model for completions. For example, if you have a table model, you can tell it which column to use for completions, which model role to use to retrieve candidates, and so forth.

    The QCompleter example in the docs will help. There is a more advanced example as well. In both cases, note that they use a plain old QCompleter and customize it using models.
    <=== The Great Pumpkin says ===>
    Please use CODE tags when posting source code so it is more readable. Click "Go Advanced" and then the "#" icon to insert the tags. Paste your code between them.

  2. The following user says thank you to d_stranz for this useful post:

    boo9 (1st July 2016)

  3. #2
    Join Date
    Jun 2016
    Posts
    19
    Qt products
    Qt5
    Platforms
    Windows
    Thanks
    10
    Thanked 1 Time in 1 Post

    Default Re: How does QComboBox uses/calls QCompleter ?

    I examined above examples but I dont think they answer my question,

    Let me be more specific
    I need a completer that will complete on many words, e.g, user types in "aa bb" into QEditBox edit, and completer should complete a list where each item on the complete list matches (not just begins with) "aa" and "bb".
    that is, the completion for "aa bb" filter from a list {aaa_a, aaa_bbb, aabb, bbb_a}, should be {aaa_bbb, aabb}.

    I managed to do that but I needed to sublcass both qeditbox and qcompleter.
    Is there any way to accomplish that w/o subclassing QEditBox ?

  4. #3
    Join Date
    Jun 2016
    Posts
    19
    Qt products
    Qt5
    Platforms
    Windows
    Thanks
    10
    Thanked 1 Time in 1 Post

    Default Re: How does QComboBox uses/calls QCompleter ?

    I subclassed QCompleter

    Qt Code:
    1. class mySearchFilterComplter : public QCompleter
    2. {
    3. Q_OBJECT
    4. public:
    5. mySearchFilterComplter(QObject * parent) : QCompleter(parent), m_model()
    6. {
    7. setModel(&m_model);
    8. }
    9. public slots:
    10. void update(const QString & text)
    11. {
    12. QDebug() << "update";
    13. m_model.setStringList(QStringList() << "one" << "two" << "three");
    14. complete();
    15. popup()->setCurrentIndex(completionModel()->index(0, 0));
    16. }
    17. private:
    18. };
    To copy to clipboard, switch view to plain text mode 

    then connected combo box editTextChanged() signal to my completer update() slot.

    Qt Code:
    1. mySearchFilterComplter * cc = new mySearchFilterComplter(this);
    2. ui->comboBox->setComplter(cc)
    3. connect(ui->comboBox, SIGNAL(editTextChanged(QString)), cc, SLOT(update(QString)));
    To copy to clipboard, switch view to plain text mode 

    The update() gets called with each keystroke in combo box line edit but there is no popup ?
    What am I doing wrong ?
    I have similar code with subsclassed QLineEdit and subclassed QCompleter and the completer popup works. (but the completer::update() is called from keyPressedEvent() though)

    Qt Code:
    1. class MyCompleter : public QCompleter
    2. {
    3. Q_OBJECT;
    4. public:
    5. inline MyCompleter(const QStringList& words, QObject * parent) :
    6. QCompleter(parent), m_model()
    7. {
    8. setModel(&m_model);
    9. }
    10. inline void update(QString word)
    11. {
    12. m_model.setStringList(QStringList() << "one" << "two" << "three");
    13. complete();
    14. }
    15. private:
    16. QStringList m_list;
    17. };
    18.  
    19. class MyLineEdit : public QLineEdit
    20. {
    21. Q_OBJECT;
    22. public:
    23. MyLineEdit(QWidget *parent = 0);
    24. ~MyLineEdit();
    25. void setCompleter(MyCompleter *c);
    26. MyCompleter *completer() const;
    27. protected:
    28. void keyPressEvent(QKeyEvent *e);
    29. private slots:
    30. void insertCompletion(const QString &completion);
    31. private:
    32. MyCompleter *c;
    33. };
    34.  
    35. MyLineEdit::MyLineEdit(QWidget *parent)
    36. : QLineEdit(parent), c(0)
    37. {
    38. }
    39.  
    40. MyLineEdit::~MyLineEdit()
    41. {
    42. }
    43.  
    44. void MyLineEdit::setCompleter(MyCompleter *completer)
    45. {
    46. if (c)
    47. QObject::disconnect(c, 0, this, 0);
    48.  
    49. c = completer;
    50.  
    51. if (!c)
    52. return;
    53.  
    54. c->setWidget(this);
    55. connect(completer, SIGNAL(activated(const QString&)), this, SLOT(insertCompletion(const QString&)));
    56. }
    57.  
    58. MyCompleter *MyLineEdit::completer() const
    59. {
    60. return c;
    61. }
    62.  
    63. void MyLineEdit::insertCompletion(const QString& completion)
    64. {
    65. setText(completion);
    66. selectAll();
    67. }
    68. void MyLineEdit::keyPressEvent(QKeyEvent *e)
    69. {
    70. if (c && c->popup()->isVisible())
    71. {
    72. // The following keys are forwarded by the completer to the widget
    73. switch (e->key())
    74. {
    75. case Qt::Key_Enter:
    76. case Qt::Key_Return:
    77. case Qt::Key_Escape:
    78. case Qt::Key_Tab:
    79. case Qt::Key_Backtab:
    80. e->ignore();
    81. return; // Let the completer do default behavior
    82. }
    83. }
    84.  
    85. bool isShortcut = (e->modifiers() & Qt::ControlModifier) && e->key() == Qt::Key_E;
    86. if (!isShortcut)
    87. QLineEdit::keyPressEvent(e); // Don't send the shortcut (CTRL-E) to the text edit.
    88.  
    89. if (!c)
    90. return;
    91.  
    92. bool ctrlOrShift = e->modifiers() & (Qt::ControlModifier | Qt::ShiftModifier);
    93. if (!isShortcut && !ctrlOrShift && e->modifiers() != Qt::NoModifier)
    94. {
    95. c->popup()->hide();
    96. return;
    97. }
    98.  
    99. c->update(text());
    100. c->popup()->setCurrentIndex(c->completionModel()->index(0, 0));
    101. }
    102.  
    103. MainWindow::MainWindow(QWidget *parent)
    104. : QMainWindow(parent)
    105. {
    106. MyLineEdit * te = new MyLineEdit();
    107.  
    108.  
    109. MyCompleter * completer = new MyCompleter(QStringList() << "112233" << "223344" << "334455", this);
    110. completer->setCaseSensitivity(Qt::CaseInsensitive);
    111. te->setCompleter(completer);
    112.  
    113. QVBoxLayout * layout = new QVBoxLayout;
    114. layout->addWidget(te);
    115. QWidget *centralWidget = new QWidget;
    116. centralWidget->setLayout(layout);
    117. setCentralWidget(centralWidget);
    118. }
    119.  
    120. MainWindow::~MainWindow()
    121. {
    122.  
    123. }
    To copy to clipboard, switch view to plain text mode 

  5. #4
    Join Date
    Jan 2008
    Location
    Alameda, CA, USA
    Posts
    5,349
    Qt products
    Qt5
    Platforms
    Windows
    Thanks
    318
    Thanked 872 Times in 859 Posts

    Default Re: How does QComboBox uses/calls QCompleter ?

    If you are fixated on subclassing QCompleter, I can't help you.

    You could probably accomplish what you want without subclassing by using a combination of a QSortFilterProxyModel, QStringListModel, and QRegExp to set a filter on the completion strings returned by the string list model. Then all of these behavioral problems you are battling with should magically disappear because you are using a wheel that already works rather than trying to invent your own.
    <=== The Great Pumpkin says ===>
    Please use CODE tags when posting source code so it is more readable. Click "Go Advanced" and then the "#" icon to insert the tags. Paste your code between them.

  6. The following user says thank you to d_stranz for this useful post:

    boo9 (2nd July 2016)

  7. #5
    Join Date
    Jun 2016
    Posts
    19
    Qt products
    Qt5
    Platforms
    Windows
    Thanks
    10
    Thanked 1 Time in 1 Post

    Default Re: How does QComboBox uses/calls QCompleter ?

    > You could probably accomplish what you want without subclassing by using a combination of a QSortFilterProxyModel, QStringListModel, and QRegExp

    You mean to disable default completer on qcombobox and filter items in the combobox directly ?
    e.g, on each combobox::editTextChanged() notification, programatically rebuild new combo box item list ?
    when user enters "aa bb cc" into combobox edit, then leave only items in the combobox list that contain "aa" and "bb" and "cc" ?

  8. #6
    Join Date
    Jan 2008
    Location
    Alameda, CA, USA
    Posts
    5,349
    Qt products
    Qt5
    Platforms
    Windows
    Thanks
    318
    Thanked 872 Times in 859 Posts

    Default Re: How does QComboBox uses/calls QCompleter ?

    ou mean to disable default completer on qcombobox and filter items in the combobox directly ?
    No. The "chain of command" is like this: combo box has a completer, completer has a proxy model, proxy model has the string list model with *all* strings and a regular expression that matches a subset (or none) of the strings.

    You create your complete string model instance and populate it with strings. You also create the proxy model instance and give it the pointer to the string model as its source model. When you call setModel() on the completer, you would give it the pointer to the proxy model. The completer has no idea it is looking at a proxy instead of the full model; the interfaces and interactions are identical, it's just that the proxy is doing some magic to return only a part of the full model to the completer.

    The proxy model does what your manual code does now - it takes the full list of possibilities, applies some logic to select out the matching subset, and passes that to the completer. The "logic" in this case is defined by a QRegExp regular expression.

    You will probably have to create your regular expressions on the fly to match what the user is typing, and it will change with every keystroke. So when the user types "a" and you want to match every string that starts with an "a", then your regular expression is "^a[a-z]*[ _]{0,1}[a-z]*" In English this says, "match any string that starts with lowercase 'a', followed by zero or more lowercase letters of any type, followed by 0 or 1 spaces or underscores, followed by zero or more lowercase letters".

    When the user types "aa bb", then you need "^aa[a]*[ _]{0,1}bb[b]*" which says, match any string starting with two or more lowercase 'a', followed by zero or one underscore or blank space, followed by two or more 'b' characters."

    In essence, you are letting the QRegExp do the filtering for you by changing the rules it uses for filtering. These "rules" would probably be very similar to the "rules" you would be coding by hand, except these are expressed in regular expression syntax rather than a bunch of if / else / endif logic.
    <=== The Great Pumpkin says ===>
    Please use CODE tags when posting source code so it is more readable. Click "Go Advanced" and then the "#" icon to insert the tags. Paste your code between them.

  9. The following user says thank you to d_stranz for this useful post:

    boo9 (3rd July 2016)

  10. #7
    Join Date
    Jun 2016
    Posts
    19
    Qt products
    Qt5
    Platforms
    Windows
    Thanks
    10
    Thanked 1 Time in 1 Post

    Default Re: How does QComboBox uses/calls QCompleter ?

    Thank you for detailed explanation, however RE will not make it in general case.
    For simple searches with two tokens, "aa bb" query means aa followed by bb OR bb followed by aa. One can express that in simple RE
    aa.*bb|bb.*aa

    However when there is more tokens e.g, "aa bb cc dd" permuting all sequences of aa,bb,cc is not feasable.

    3 tokens => 3! = 6 permutations
    4 tokens => 4! = 24 permutations

    cheers

  11. #8
    Join Date
    Jan 2008
    Location
    Alameda, CA, USA
    Posts
    5,349
    Qt products
    Qt5
    Platforms
    Windows
    Thanks
    318
    Thanked 872 Times in 859 Posts

    Default Re: How does QComboBox uses/calls QCompleter ?

    I guess I have no idea what you are trying to do with your completer or what the use case might be.
    <=== The Great Pumpkin says ===>
    Please use CODE tags when posting source code so it is more readable. Click "Go Advanced" and then the "#" icon to insert the tags. Paste your code between them.

  12. The following user says thank you to d_stranz for this useful post:

    boo9 (6th July 2016)

  13. #9
    Join Date
    Jun 2016
    Posts
    19
    Qt products
    Qt5
    Platforms
    Windows
    Thanks
    10
    Thanked 1 Time in 1 Post

    Default Re: How does QComboBox uses/calls QCompleter ?

    > I guess I have no idea what you are trying to do with your completer

    I have a list with 100 items.
    Each list item is a text of 10-50 characters, 2-10 words
    When I type in "aa" I would like only items that contain "aa" filtered
    When I type in "aa bb" I would like only items that contain "aa" AND "bb" filtered, "aa bb" does not mean that bb follows aa, it only means that list item must contain "aa" and "bb" anywhere in the item text.
    When I type in "aa bb cc" I would like only items that contain "aa" AND "bb" AND "cc" filtered, aa,bb,cc can appear at any position in the item text.

  14. The following user says thank you to boo9 for this useful post:

    d_stranz (7th July 2016)

  15. #10
    Join Date
    Jan 2008
    Location
    Alameda, CA, USA
    Posts
    5,349
    Qt products
    Qt5
    Platforms
    Windows
    Thanks
    318
    Thanked 872 Times in 859 Posts

    Default Re: How does QComboBox uses/calls QCompleter ?

    I have a list with 100 items.
    Each list item is a text of 10-50 characters, 2-10 words
    OK... can you please give an example with some of the real strings that you have in your list, and what the user might type? "aa bb cc" is just too abstract for me to understand how you might be using this in a real application.
    <=== The Great Pumpkin says ===>
    Please use CODE tags when posting source code so it is more readable. Click "Go Advanced" and then the "#" icon to insert the tags. Paste your code between them.

  16. #11
    Join Date
    Jun 2016
    Posts
    19
    Qt products
    Qt5
    Platforms
    Windows
    Thanks
    10
    Thanked 1 Time in 1 Post

    Default Re: How does QComboBox uses/calls QCompleter ?

    item1: * (Search resistor range)(res-range) eltype=resistor rlcvalue >= %1 rlcvalue <= %2
    item2: * (Search electrolite capacitor range)(cap-range) eltype=capacitor electrolite rlcvalue >= %1 and rlcvalue <= %2
    item3: * (Search electrolite capacitor range metallic)(metcap-range) ceramic eltype=capacitor rlcvalue >= %1 and rlcvalue <= %2
    ....
    item100: ....

    how I want to quicky find correct itemX without scrolling through a list
    - entering "cap electro" exepect to filter 2
    - entering "cap range" expect to filter 2,3


    I dont understand why such requirements appear strange and uncommon.
    When one searches an email archive and have thousands of item in the mail box, one would expect to search for email message with words/tokens, and would expect the tokens in the mail message would appear in any order, not necessarilly the order they were entered in the search spec.
    Last edited by boo9; 7th July 2016 at 12:09.

  17. #12
    Join Date
    Jan 2008
    Location
    Alameda, CA, USA
    Posts
    5,349
    Qt products
    Qt5
    Platforms
    Windows
    Thanks
    318
    Thanked 872 Times in 859 Posts

    Default Re: How does QComboBox uses/calls QCompleter ?

    OK, now it makes more sense. Take a look at this example of a custom sort/filter proxy model.

    You would re-implement the QSortFilterProxyModel::filterAcceptsRow(), and add your own method to the custom proxy that takes the string typed by the user in the combobox. In this method, split the string into tokens (QString::split()) and save the stringlist as a member variable in your proxy.

    In the filterAcceptsRow() method, you retrieve the full string from your model into a QString (Use QStringListModel::data() and the Qt::DisplayRole ItemDataRole). For each token in the user's input, you call QString::contains() to see if the model string contains the token. If the answer is yes for all of the tokens in the user's string, you return true from filterAcceptsRow, otherwise you return false. Only those entries for which the result is true will be shown as selections in the combobox drop-down list.

    This will accomplish your goals of returning only those strings that contain all of the tokens the user has typed and allowing those tokens to appear in any order.
    <=== The Great Pumpkin says ===>
    Please use CODE tags when posting source code so it is more readable. Click "Go Advanced" and then the "#" icon to insert the tags. Paste your code between them.

  18. The following user says thank you to d_stranz for this useful post:

    boo9 (7th July 2016)

Similar Threads

  1. QComboBox with QCompleter
    By cic in forum Qt Programming
    Replies: 1
    Last Post: 27th September 2013, 19:21
  2. spectrogram calls
    By marc2050 in forum Qwt
    Replies: 1
    Last Post: 5th August 2011, 08:52
  3. Paint() calls
    By alitoh in forum Newbie
    Replies: 1
    Last Post: 10th May 2011, 02:05
  4. How to use IOCTL calls with QT?
    By augusbas in forum Qt Programming
    Replies: 3
    Last Post: 15th November 2010, 07:55
  5. Replies: 1
    Last Post: 12th October 2008, 08:21

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  
Qt is a trademark of The Qt Company.