Search bar for QSqlTableModel in QTableView



  • Hello. I have an SQL table read into a QSqlTableModel and displayed in QTableView. I need a Search bar that a user could type in a word or set of numbers and have atleast 4 different columns (I'd prefer the whole table) searched through and then only records that contain what was entered be displayed.

    For example if the user enters "Sam" all records that contain "Sam" would be displayed. That could be the name "Sam" or "Samantha" or a feild containing "Sample".

    Anyone have any ideas on how to do this?

    thanks for any help!



  • Hi there, Think you have to make your own function in your model (or give your model a "show this data only" qstring. Maybe check how many rows are needed to show the filtered data. Set the new number of rows. Then emit the "datachanged" signal to the view. It will use the "data" function to start reading the values. In here you simple only give the filtered values.
    I think I would try something like that.
    Happy coding!



  • Try placing QSortFilterProxyModel between your model and view, and set the proxy models filter appropriately, e.g. @setFilterWildcard("sam")@



  • DerManu can you show me more of what this would look like?

    I tried
    @model->clear();
    model->setTable("MySQLTable");
    model->setSort(Service_Date, Qt::AscendingOrder);
    model->setEditStrategy(QSqlTableModel::OnManualSubmit);

    model->select();
    
    searchText = searchBar->text().trimmed();
    QSortFilterProxyModel proxy;
    proxy.setSourceModel(model);
    proxy.setFilterWildcard(searchText);
    
    view->verticalHeader()->setResizeMode(QHeaderView::ResizeToContents); 
    view->setModel(cfpm);
    view->resizeColumnsToContents();
    

    @
    and put that where I originally show the table and tried putting it in a function called when return is pressed in the searchbar but niether place did anything



  • proxy is a model just like your original one, with the difference that it acts as a filtering/sorting layer. This means it needs to exist as long as your model/view exist. Currently you're creating the model on the stack:
    @QSortFilterProxyModel proxy;@
    when you probably want to create it on the heap (as your model seems to be):
    @QSortFilterProxyModel *proxy = new QSortFilterProxyModel;@
    so it doesn't get deleted as soon as the function returns.

    Further you must set the view to access the proxy:
    @view->setModel(proxy);@
    currently you're setting it to cfpm, don't know what that is.



  • Oo yeah thats my bad, cfpm is another model used to make a column have checkboxes in it I just didnt copy that part in here since it didn't seem relavant to this and would just cause the code to look more confusing.

    I changed the two things you said and it now looks like this
    @
    searchText = searchBar->text().trimmed();
    QSortFilterProxyModel *proxy = new QSortFilterProxyModel;
    proxy->setSourceModel(model);
    proxy->setFilterFixedString(searchText);
    //proxy->setFilterWildcard(searchText);

    view->setModel(proxy);
    

    @
    I have it connected to a a SLOT called when return is pressed and when I press it after typing info into the searchbar all the records disappear. I tried it with setFilterWildcard, which I don't exactly understand what it does, and setFilterFixedString but that didn't effect it at all. Do you know why its doing this?

    Also does it matter if I have this where the original model and view are defined or have it called when return is pressed or is one better that the other?

    thanks for all your help!



  • [quote author="confused" date="1345052894"]Also does it matter if I have this where the original model and view are defined or have it called when return is pressed or is one better that the other?[/quote]
    Yes that matters alot. As I said, treat your proxy just like your original model. Create it when it is created (presumably once at the start of the program), and delete it when it is deleted (at the end of the program). Currently you're creating new proxy models at every button click and you're leaking their memory (not deleting them).

    setFilterWildcard sets a filter based on the rules given by
    http://qt-project.org/doc/qt-4.8/qregexp.html#wildcard-matching
    so basically a QRegExp with pattern syntax set to QRegExp::Wildcard which results in a simpler (but less powerful) syntax than true regular expressions.

    In your slot that gets called upon hitting return in the search line edit, just set the corresponding new wildcard/regEx/fixedString on the proxy. No need to touch original model or view there. If all entries disappear upon that, the filter just doesn't match any. Try
    @a@
    (with wildcard matching), which should show all entries containing an "a".

    //EDIT: Oh yes, and make sure you're familiar with all the mechanisms of QSortFilterProxyModel. Read the documentation, especially setFilterKeyColumn and setFilterRole.



  • You sir are a God send! It finally worked!! I have been trying to figure this out for a long time and I'm close to my deadline and I thought I wasn't going to be able to.

    Thank you so much for all your help!



  • 1 more question though, how do I make sure it is deleting when the program ends? Do I put it in the deconstructor and say something like
    @
    delete modelName;
    @
    I think I have a lot of memory leaks because I tried to make a deconstructor a little while ago from some examples I saw but I got an error so I currently just have
    @
    window::~window()
    {

    }
    @



  • Make yourself familiar with basic C++ memory management and Qt techniques for memory management (e.g. http://stackoverflow.com/questions/2491707/memory-management-in-qt and http://qt-project.org/doc/qt-4.8/objecttrees.html )


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.