QSortFilterProxyModel strange behavior with QRegExp
-
My pattern looks like this:
[...] if(name.contains(QRegExp("\\s"))) { QStringList word = name.split(QRegExp("\\s")); regExp.setPattern("^" + QRegExp::escape(word[0]) + "\\w*\\s" + QRegExp::escape(word[1]) + "\\w*"); } else { regExp.setPattern("^" + QRegExp::escape(name) + "\\w*");; } [...]
The debugger shows following, if I type:
bol -> ^bol\w*
bol whit space like "bol " -> ^bol\w*\s\w*
bol edu -> ^bol\w*\sedu\w*@SGaist said in QSortFilterProxyModel strange behavior with QRegExp:
Note that you should really use the proper overloads.
Sorry I don't know what you mean. Please make an example for my code.
-
My pattern looks like this:
[...] if(name.contains(QRegExp("\\s"))) { QStringList word = name.split(QRegExp("\\s")); regExp.setPattern("^" + QRegExp::escape(word[0]) + "\\w*\\s" + QRegExp::escape(word[1]) + "\\w*"); } else { regExp.setPattern("^" + QRegExp::escape(name) + "\\w*");; } [...]
The debugger shows following, if I type:
bol -> ^bol\w*
bol whit space like "bol " -> ^bol\w*\s\w*
bol edu -> ^bol\w*\sedu\w*@SGaist said in QSortFilterProxyModel strange behavior with QRegExp:
Note that you should really use the proper overloads.
Sorry I don't know what you mean. Please make an example for my code.
@Gabber
I don't claim to know what is going on. And if you sayIf I then delete " edu" again, so that I only have "bol" again, everything that starts with "bol" also appears. Only if I enter "bol" to start the program, the search does not work.
that sounds odd, because you are claiming you end up with the same reg exp as you started with but different behaviour. Which sounds like a
QSortFilterProxyModel
rather than a reg exp thing.Just a couple of suggestions:
-
Try using
\S
in place of\w
. Any difference? -
Try using
.
, or even(.|\n)
, in place of\w
. Any difference? -
You are going to move over from
QRegExp
toQRegularExpression
, aren't you? Do so now. If by any chance it's aQRegExp
issue withQSortFilterProxyModel
which works withQRegularExpression
, it's not worth the effort to deal with.
-
-
@JonB said in QSortFilterProxyModel strange behavior with QRegExp:
Try using \S in place of \w. Any difference?
No difference.
@JonB said in QSortFilterProxyModel strange behavior with QRegExp:
Try using ., or even (.|\n), in place of \w. Any difference?
No difference.
@JonB said in QSortFilterProxyModel strange behavior with QRegExp:
You are going to move over from QRegExp to QRegularExpression, aren't you?
I switched to QRegularExrpession. Now my code looks like this:
void MainWindow::on_searchbar_textChanged(const QString &name) { QRegularExpression regularExpression; regularExpression.setPatternOptions(QRegularExpression::CaseInsensitiveOption); ui->selection->setCurrentIndex(0); if(ui->selection->currentIndex() == 0) { mFungusProxyModel->setFilterCaseSensitivity(Qt::CaseInsensitive); mFungusProxyModel->setFilterKeyColumn(1); if(name.contains(QRegularExpression("\\s"))) { QStringList word = name.split(QRegularExpression("\\s")); regularExpression.setPattern("^" + QRegularExpression::escape(word[0]) + "\\w*\\s" + QRegularExpression::escape(word[1]) + "\\w*"); } else { regularExpression.setPattern("^" + QRegularExpression::escape(name) + "\\w*"); } mFungusProxyModel->setFilterRegularExpression(regularExpression); ui->listView->setModelColumn(1); ui->listView->setModel(mFungusProxyModel); } }
Here's what else I found out: If I enter "bole" instead of "bol" then the search starts and lists all names that start with "bole".
I suspect it is the QSortFilterProxyModel. Can I somehow say there I want to search for 3 letters? Unfortunately I didn't find anything in the documentation.
Do you have any other idea how I can implement this differently?
-
@JonB said in QSortFilterProxyModel strange behavior with QRegExp:
Try using \S in place of \w. Any difference?
No difference.
@JonB said in QSortFilterProxyModel strange behavior with QRegExp:
Try using ., or even (.|\n), in place of \w. Any difference?
No difference.
@JonB said in QSortFilterProxyModel strange behavior with QRegExp:
You are going to move over from QRegExp to QRegularExpression, aren't you?
I switched to QRegularExrpession. Now my code looks like this:
void MainWindow::on_searchbar_textChanged(const QString &name) { QRegularExpression regularExpression; regularExpression.setPatternOptions(QRegularExpression::CaseInsensitiveOption); ui->selection->setCurrentIndex(0); if(ui->selection->currentIndex() == 0) { mFungusProxyModel->setFilterCaseSensitivity(Qt::CaseInsensitive); mFungusProxyModel->setFilterKeyColumn(1); if(name.contains(QRegularExpression("\\s"))) { QStringList word = name.split(QRegularExpression("\\s")); regularExpression.setPattern("^" + QRegularExpression::escape(word[0]) + "\\w*\\s" + QRegularExpression::escape(word[1]) + "\\w*"); } else { regularExpression.setPattern("^" + QRegularExpression::escape(name) + "\\w*"); } mFungusProxyModel->setFilterRegularExpression(regularExpression); ui->listView->setModelColumn(1); ui->listView->setModel(mFungusProxyModel); } }
Here's what else I found out: If I enter "bole" instead of "bol" then the search starts and lists all names that start with "bole".
I suspect it is the QSortFilterProxyModel. Can I somehow say there I want to search for 3 letters? Unfortunately I didn't find anything in the documentation.
Do you have any other idea how I can implement this differently?
@Gabber
Using the regular expression filter inQSortFilterProxyModel
is only a "convenience" for you, you don't have to use it. You can subclass and and implement your own code for virtual protected bool QSortFilterProxyModel::filterAcceptsRow() if you cannot get the regular expression to work right for some reason. -
The length of the expression should have no importance as long it's properly written.
Can you write a minimal compilable example that uses a QStandardItemModel with some suitable entries and your proxy setup so that we can test it ?
Note that you can also to some testing with the QRegularExpression tool from Qt's examples.
-
The length of the expression should have no importance as long it's properly written.
Can you write a minimal compilable example that uses a QStandardItemModel with some suitable entries and your proxy setup so that we can test it ?
Note that you can also to some testing with the QRegularExpression tool from Qt's examples.
@SGaist
I have made a very simple example that corresponds to what I want to search. If I take the QStandardItemModel my QRegularExpression also works as expected with QSortFilterProxyModel. Here is my code.main.cpp
#include "mainwindow.h" #include <QApplication> int main(int argc, char *argv[]) { QApplication a(argc, argv); MainWindow w; w.show(); return a.exec(); }
mainwindow.cpp
#include "mainwindow.h" #include "ui_mainwindow.h" MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) , ui(new Ui::MainWindow) { ui->setupUi(this); ui->comboBox->addItem("Vollnamen"); ui->comboBox->setCurrentText("Vollnamen"); QStringList fungusList{ "Boletus aereus Bulliard ex Fr.", "Boletus betulicola (Vassilkov) Pilat & Dermek", "Boletus carpinaceus Velen.", "Boletus edulis Bulliard", "Boletus edulis var.arenarius Engel, Krglst. & Dermek", "Boletus edulis var.clavipes Peck", "Abortiporus biennis (Bull.) Singer", "Adustomyces spec.", "Euryachora spec", "Diaporthe strumella (Fries) Fuckel", "Cudonia spec." }; mFungusListModel = new QStandardItemModel(fungusList.count(),0); for(int row=0; row<mFungusListModel->rowCount(); row++){ QStandardItem *item = new QStandardItem(QString(fungusList.at(row))); mFungusListModel->setItem(row,0,item); } mFungusProxyModel = new QSortFilterProxyModel(); mFungusListModel->sort(0); mFungusProxyModel->setSourceModel(mFungusListModel); ui->listView->setModel(mFungusProxyModel); ui->listView->setModelColumn(0); } MainWindow::~MainWindow() { delete ui; } void MainWindow::on_lineEdit_textChanged(const QString &name) { QRegularExpression regularExpression; regularExpression.setPatternOptions(QRegularExpression::CaseInsensitiveOption); ui->comboBox->setCurrentIndex(0); if(ui->comboBox->currentIndex() == 0) { mFungusProxyModel->setFilterCaseSensitivity(Qt::CaseInsensitive); mFungusProxyModel->setFilterKeyColumn(0); if(name.contains(QRegularExpression("\\s"))) { QStringList word = name.split(QRegularExpression("\\s")); regularExpression.setPattern("^" + QRegularExpression::escape(word[0]) + "\\w*\\s" + QRegularExpression::escape(word[1]) + "\\w*"); } else { regularExpression.setPattern("^" + QRegularExpression::escape(name) + "\\w*"); } mFungusProxyModel->setFilterRegularExpression(regularExpression); ui->listView->setModelColumn(0); ui->listView->setModel(mFungusProxyModel); } }
mainwindow.h
#ifndef MAINWINDOW_H #define MAINWINDOW_H #include <QMainWindow> #include <QSortFilterProxyModel> #include <QStandardItemModel> QT_BEGIN_NAMESPACE namespace Ui { class MainWindow; } QT_END_NAMESPACE class MainWindow : public QMainWindow { Q_OBJECT public: MainWindow(QWidget *parent = nullptr); ~MainWindow(); private slots: void on_lineEdit_textChanged(const QString &name); private: Ui::MainWindow *ui; QSortFilterProxyModel *mFungusProxyModel; QStandardItemModel *mFungusListModel; }; #endif // MAINWINDOW_H
mainwindow.ui
<?xml version="1.0" encoding="UTF-8"?> <ui version="4.0"> <class>MainWindow</class> <widget class="QMainWindow" name="MainWindow"> <property name="geometry"> <rect> <x>0</x> <y>0</y> <width>424</width> <height>590</height> </rect> </property> <property name="windowTitle"> <string>MainWindow</string> </property> <widget class="QWidget" name="centralwidget"> <layout class="QVBoxLayout" name="verticalLayout"> <item> <widget class="QLineEdit" name="lineEdit"/> </item> <item> <widget class="QComboBox" name="comboBox"/> </item> <item> <widget class="QListView" name="listView"/> </item> </layout> </widget> <widget class="QMenuBar" name="menubar"> <property name="geometry"> <rect> <x>0</x> <y>0</y> <width>424</width> <height>23</height> </rect> </property> </widget> <widget class="QStatusBar" name="statusbar"/> </widget> <resources/> <connections/> </ui>
What could be the problem now? Do you have another idea? Do you need any code to analyze the problem? I hope we can work this out somehow. The search function is the most important thing in the program.
Thanks already :)
-
@Gabber said in QSortFilterProxyModel strange behavior with QRegExp:
If I take the QStandardItemModel my QRegularExpression also works as expected with QSortFilterProxyModel.
Do you mean that with the QStandardItemModel the erroneous behaviour does not trigger ?
-
@Gabber said in QSortFilterProxyModel strange behavior with QRegExp:
If I take the QStandardItemModel my QRegularExpression also works as expected with QSortFilterProxyModel.
Do you mean that with the QStandardItemModel the erroneous behaviour does not trigger ?
@SGaist said in QSortFilterProxyModel strange behavior with QRegExp:
Do you mean that with the QStandardItemModel the erroneous behaviour does not trigger ?
Yes, that's what I mean. My search works exactly as I imagine it.
-
In that case, the problem might be with mFungusModel.
-
@SGaist
I have created a file DatabaseManager.cpp. The following function exists in it:QSqlTableModel *DatabaseManager::fungusTable() const { QSqlTableModel *model = new QSqlTableModel(); model->setTable("Pilze"); model->setSort(1, Qt::AscendingOrder); model->select(); return model; }
In my mainwindow.h I do this:
private: Ui::MainWindow *ui; DatabaseManager *mDatabaseManager; SettingsManager *mSettingsManager; QDataWidgetMapper *mFungusMapper; QSqlTableModel *mFungusModel;
And in my constructor in my mainwindow.cpp I assign the data from the DatabaseManager to mFungusModel.
[...] if(isStandardDatabasePathSet) { const QString standardDatabase = mSettingsManager->loadStandardDatabase(); mDatabaseManager->openDatabase(standardDatabase); ui->selection->setCurrentText("Vollnamen"); mFungusMapper = new QDataWidgetMapper(); mFungusProxyModel = new QSortFilterProxyModel(); mFungusModel = mDatabaseManager->fungusTable(); mFungusProxyModel->setSourceModel(mFungusModel); ui->listView->setModel(mFungusProxyModel); ui->listView->setModelColumn(1); } [...]
That's all what I'm doing in my constructor of mainwindow.cpp
-
Can someone please give me a hint what I can do now?
Why does the search work when I type four characters or type three characters and delete one?
I have no idea what to look for to solve / address this problem.
Tips are gratefully accepted.
-
My problem was solved in this Thread:
https://forum.qt.io/topic/131616/does-qsqltablemodel-have-a-limit-of-records