Issue when searching QTableWidget using wildcards - c++

In my Qt C++ application I have several items in a qtablewidget. A QLineEdit along with a button are used by me in order to search the QTableWidget when a particular word is given to the line edit and the search button is clicked. Following is my code:
bool found=false;
QString Line= ui->search->text();
for(int i=0;i<100;i++){
if(ui->tableWidget->item(i,0)->text()== Line){
found = true;
break;
}
}
if(found){
ui->tableWidget->clear();
ui->tableWidget->setItem(0,0,new QTableWidgetItem(Line));
}
else{
QMessageBox::warning(this, tr("Application Name"), tr("The word you are searching does not exist!") );
}
This code works if an exact word in the table widget is given but if I use
ui->tableWidget->item(i,0)->text()=="%"+ Line+"%";
It won't work for the wild card scenario so that I can search even part of a word is given. How can I correct this issue?

The == operator compare two strings and return true if they are exacly equals.
If you want to use wildcards, I suggest to use QRegExp and use QRegExp::Wildcard as pattern syntax.
Example 1:
QString line = "aaaaLINEbbbb";
QRegExp rx("*LINE*");
rx.setPatternSyntax(QRegExp::Wildcard);
rx.exactMatch(line); //should return true
However, if you want to test only if a string contains a substring, I suggest to use bool QString::contains(const QString &str, Qt::CaseSensitivity cs) that can be faster.
Example 2:
QString line = "aaaaLINEbbbb";
QString searchWord = "LINE";
line.contains(searchWord); //should return true
See:
QRegExp
QRegExp::PatternSyntax
Wildcard Matching
QString::contains

Related

Execute Command with QProcess and Store result in QStringList

I have written the following function which executes a windows enumeration command for getting shared folders and store the result in a QString.
QProcess p;
p.setProgram("wmic");
p.setArguments({"share", "get", "name"});
p.start();
if (!p.waitForFinished()) {
return;
}
const QString output = p.readAllStandardOutput();
qDebug () << output;
const QString error = p.readAllStandardError();
if (!error.isEmpty()) {
qDebug () << error;
}
But the output has a lot of delimiters like "\n\r" ... so I wanted to strip all of those delimiters from my string output. In the next step, you consider we will have a result like the following one:
C$
D$
E$
IPC$
So I wanted to save these names in a QStringList, or something like a list which I can append those names in combo widget independently. How can I do that?
You could just use qstring split:
QStringList list = output.split("\n", QString::SkipEmptyParts);
If you need a more "intelligent" split that you can pass in a regex:
list = output.split(QRegExp("...some regex..."));
The skip empty parts just "removes"/ignores any values that would be empty - I don't think you need that in this case

C++ Qt - Reading specific portion of a text file

I want to read a specific portion of a text file in a list widget. I have try different ways and looked online for some solutions but I couldn't find much. Im new using Qt but getting along well with it for the most part.
QFile YearInfo("C:/Users/Documents/info.txt");
YearInfo.open(QIODevice::ReadWrite | QIODevice::Text);
if(YearInfo.isOpen()){
QTextStream in(&YearInfo);
bool readEnabled = false;
QString outputText, startToken = line, endToken = "*"; // line = "2019"
while(!in.atEnd()){
QString getLine = in.readLine();
if(getLine == endToken){
readEnabled = false;
}
if(readEnabled){
outputText.append(getLine + "\n");
}
if(getLine == startToken){
readEnabled = true;
}
}
ui->listWidget->addItem(outputText);
}
YearInfo.flush();
YearInfo.close();
Text File contains:
2019
Position Division Title Date (W.M./R.M./J.R)
*
2020
Position Division Title Date (P.M./V.R/S.T)
*
The code that you have written works as long as you are trying to extract a section of text formatted in the following way
2019
Position Division Title <~~ this line is extracted
Date (W.M./R.M./J.R) <~~ this line is extracted
More stuff <~~ this line is extracted
*
If you have something formatted in the following way
2019 Position Division
Title Date (W.M./R.M./J.R) *
2019 Position Division Title Date (W.M./R.M./J.R) *
nothing will be extracted because you start the extraction when you find a line that contains only the startToken. Same thing for the end token.
You could try to modify the while loop in your code in the following way
while(!in.atEnd()){
QString getLine = in.readLine().trimmed();
if(getLine.startsWith(startToken)){
readEnabled = true;
}
if(readEnabled){
outputText.append(getLine + "\n");
}
if(getLine.endsWith(endToken)){
readEnabled = false;
}
}
Now you are checking if the line startsWith the startToken. Here I also added a trimmed instruction to remove white spaces at the beginning and at the end of each line (just in case...). The same thing is done with endsWith for the endToken.
Also it would be best to open the device in read-only mode, since you are not modifying it anyway
YearInfo.open(QIODevice::ReadOnly | QIODevice::Text);
and also the flush at the end is redundant.
Hope this helps =)
To find the entry of a string, I use QRegExp. Please note that since you have a stopToken like a special symbol for QRegExp it might be changed for "\*:
#include <QRegExp>
#include <QDebug>
QStringList tokenize(QString line, QString start, QString end)
{
QRegExp rx(start+".*"+end);
rx.indexIn(line);
return rx.capturedTexts();
}
void test()
{
qDebug()<<tokenize("2019 Position Division Title Date (W.M./R.M./J.R) *", "2019", "\\*");
// returned ("2019 Position Division Title Date (W.M./R.M./J.R) *")
qDebug()<<tokenize("2020 Position Division Title Date (P.M./V.R/S.T) *", "2019", "\\*");
// returned ("")
}
Your function must be look like this:
...
while(!in.atEnd()){
QString getLine = in.readLine();
QStringList strL = tokenize(getLine, startToken, stopToken);
if (strL.size())
ui->listWidget->addItem(strL[0]);
}
QFile YearInfo("C:/Users/Documents/info.txt");
YearInfo.open(QIODevice::ReadOnly | QIODevice::Text);
if(YearInfo.isOpen()){
QTextStream in(&YearInfo);
bool readEnabled = false;
QString outputText = "", startToken = line.trimmed(), endToken = "*";
while(!in.atEnd()){
QString getLine = in.readLine().trimmed();
if(getLine == startToken){
readEnabled = true;
}
if(readEnabled){
outputText.append(getLine + "\n");
}
if(getLine == endToken){
readEnabled = false;
}
}
ui->listWidget->addItem(outputText);
}
YearInfo.close();

how to use QRegExp to grep the last line of output of process?

am using QRegExp to grep the last line of the QProcess output via
QString str (process->readAllStandardOutput());
now i want read the last line of str and show that in Statusbar
please how can get the last line only :(
got a working solution using QRegExp
Code sample
QString line(download->readAllStandardOutput());
QString progress;
QString timeRemaining;
if (line.contains(QString("[download]"), Qt::CaseInsensitive)) {
QRegExp rx("(\\d+\\.\\d+%)");
timeRemaining = line.right(5);
rx.indexIn(line);
if(!rx.cap(0).isEmpty()) {
progress = rx.cap(0);
progress.chop(3);
ui->downloadProgressBar->setValue(progress.toInt());
ui->downloadProgressBar->setAlignment(Qt::AlignCenter);
ui->downloadProgressBar->setFormat(timeRemaining);
ui->statusBar->showMessage(line);

Qt4.8: How to make LineEdit show text in uppercase always and still have a RegExp

I'm making a gui app on Qt 4.8 which contains some lineedits to let the user introduce some information.
Normally you can write in 4 different ways the text "hello":
Caps Off, no shift pressed = "hello"
Caps Off, shift pressed = "HELLO"
Caps ON, no shift pressed = "HELLO"
Caps ON, shift pressed = "hello"
What I want is that no matter how the user writes, the line edit must show it in caps always ("HELLO").
What I was using now is:
Myclass.cpp:
auto validatorA = new MyValidator(parent);
myLineEdit->setValidator(validatorA);
Myclass.h (after includes and before class MyClass: ...)
class MyValidator: public QValidator {
public:
MyValidator(QObject* parent=nullptr): QValidator(parent) {}
State validate(QString& input, int&) const override {
input = input.toUpper();
return QValidator::Acceptable;
}
};
It works perfect but I also need this line edit to accept only letters, spaces and numbers (no symbols acepted) so after set the validatorA I need to set:
QRegExp rx("[A-Z\\.\\- 0-9]{0,30}");
QValidator *validator7 = new QRegExpValidator(rx, this);
myLineEdit->setValidator(validator7);
I've noticed that the last validator designed is the one who decides the behaviour, so I can't use both.
If I use the validator7 it works fine but it fails with the case number 4: if caps on and presses shift, then nothing is written, its like if the user were not typing even if he is clubbing the keyboard.
So I don't know how to be able to set both validators (I hav eother line edits with other different RegExp).
So... how can I make my lineedits follow RegExp and show always text in caps no matter the keyboard combination of caps+shift?
Thank you so much
Use the validator for input with the following modification
QRegExp rx("[a-z-A-Z\\.\\- 0-9]{0,30}");
QValidator *validator7 = new QRegExpValidator(rx, this);
ui->lineEdit->setValidator(validator7);
And for the upper case use the textEdited signal from the LineEdit like this
void MainWindow::on_lineEdit_textEdited(const QString &arg1)
{
ui->lineEdit->setText(arg1.toUpper());
}
If you want only show letters in caps mode - you can set custom font to lineedit with:
QFont f = font();
f.setCapitalization(QFont::AllUppercase);
lineEdit->setFont(f);
But you still need regex to validate input.
The regexp doesn't come in contact with your uppercase code.
First define your regular expression in a validator and setValidator and then:
You can simply try this for showing the text in uppercase:
connect(lineEdit,SIGNAL(textEdited(QString)),this,SLOT(toUpper(QString));
and in the definition of the slot:
void MainWidget::toUpper(QString txt)
{
lineEdit.setText(txt.toUpper());
}
Connect QLineEdit signal textChanged() with slot:
connect(lineEdit, SIGNAL(textChanged(const QString &)), this, SLOT(toUpper(const QString &)));
And do like this:
void MainWindow::toUpper(const QString &text)
{
QLineEdit *le = qobject_cast<QLineEdit *>(sender());
if (!le)
return;
le->setText(text.toUpper());
}
Works fine for me.

Check if two consts are empty

I'm kind of new to the C++ scene so I'm wondering how I'd verify both fields have some text entered, here's the current code which is only verifying one field
void App::requestLogin(const QString &email, const QString &password) {
if (m_active)
return;
//how can I do both password and email here????
const QStringList list = email.split(QRegExp("\\s+"), QString::SkipEmptyParts);
if (list.isEmpty()) {
m_errorMessage = "please complete both fields";
m_error = true;
emit statusChanged();
return;
}
}
It is hard to understand what you mean, but this is my wild guess based on your error message. You do not even need a regex for this. Even if you needed, you should use QRegularExpression rather than the much slower QRegExp.
void App::requestLogin(const QString &email, const QString &password) {
if (m_active)
return;
...
if (email.isEmpty() || password.isEmpty()) {
m_errorMessage = "please complete both fields";
m_error = true;
emit statusChanged();
return;
}
}
This operation is also more logical than && as you wrote in your comment because usually you need to supply both email and password. Basically the condition will meet if either of those meets. That means if any of the input fields kept empty, you will raise the error which seems a reasonable behavior.
Something along these lines:
if (list.isEmpty() && password.isEmpty())
I'm not sure why you are "splitting" the email. If it's just an email address used for login purposes, you should be able to do email.isEmpty() rather than using the regexp splitting.