Check if two consts are empty - c++

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.

Related

Qt error: QSqlQuery::value: not positioned on a valid record when trying to retrive a stat from a table (QComboBox)

this is the code I'm using to get the GoalsFor stat from this table after the user chooses a team from a ComboBox like this using this code:
void MainWindow::on_hometeam_currentIndexChanged(const QString &hometeam)
{
QString hteam(hometeam);
QSqlQuery q("SELECT GoalsForH FROM teams WHERE TEAM=hteam");
q.exec();
int fieldNo = q.record().indexOf("hometeam");
q.next();
qDebug() << q.value(fieldNo).toInt();
}
But this is what the debugger always shows whenever I choose a team:
QSqlQuery::value: not positioned on a valid record
0
I tried everything I came across on the net and it seems like I'm doing exactly what other users or even the documentation say yet to no avail, any help would be appreciated, thanks !
The problem seems to be with the SQL itself; since hteam isn't actually defined in SQL. I would instead recommend using the prepare function, which can also deal with filtering strings to prevent SQL injections. Something like the below should give you the result you are looking for.
void MainWindow::on_hometeam_currentIndexChanged(const QString &hometeam)
{
QString hteam(hometeam);
QSqlQuery q;
q.prepare("SELECT GoalsForH FROM teams WHERE TEAM=:hteam");
q.bindValue(":hteam", hteam);
if ( !q.exec() ) {
qDebug() << q.lastError();
} else {
int fieldNo = q.record().indexOf("GoalsForH");
while ( q.next() ) {
qDebug() << q.value(fieldNo).toInt();
}
}
}
You were also grabbing indexOf("hometeam"), which isn't actually returned by the query. This then returns -1 which wouldn't be valid. Change this to "GoalsForH" to get the proper column index.

QSyntaxHighlighter and multiline comments

I am using Qt's QSyntaxHighlighter to color some C like syntax in a QML TextEdit
Everything works great except for multiline comments.
I am detecting them this way :
void highlightBlock(QString const& text) override {
bool inMultilineComment = previousBlockState() == STATES::COMMENT;
bool inSingleLineComment = false;
int previousIndex = 0;
QRegularExpression expr("(\\/\\*|\\*\\/|\\/\\/|\n)"); // will match either /**, /**, // or \n
QRegularExpressionMatchIterator it = expr.globalMatch(text);
while(it.hasNext()) {
QRegularExpressionMatch match = it.next();
const QString captured = match.captured(1);
if(captured == "/*" && !inSingleLineComment) {
inMultilineComment = true;
previousIndex = match.capturedStart(1);
}
if(captured == "*/" && inMultilineComment) {
inMultilineComment = false;
setFormat(previousIndex, match.capturedEnd(1) - previousIndex, _commentFormat);
}
if(captured == "//" && !inMultilineComment) {
inSingleLineComment = true;
}
if(captured == "\n" && inSingleLineComment) {
inSingleLineComment = false;
}
}
if(inMultilineComment) {
setFormat(previousIndex, text.size() - previousIndex, _commentFormat);
setCurrentBlockState(STATES::COMMENT);
}
else {
setCurrentBlockState(STATES::NONE);
}
}
It works until I take a multiline comment already colored and I remove the /* at the begining. Only the block that contains the /* is processed and recolored, but not the following ones, which means that they continue to appear commented when they are not.
Is there an easy way to tell QSyntaxHighlighter to re-process the following blocks to prevent such mis-colorations ?
I ran into this same problem recently and discovered that Qt actually should be handling this for you, assuming that you set your blockState correctly.
If you look at the sourceCode for QSyntaxHighlighterPrivate::reformatBlocks in the Qt5 source code, you'll see
while (block.isValid() && (block.position() < endPosition || forceHighlightOfNextBlock)) {
const int stateBeforeHighlight = block.userState();
reformatBlock(block);
forceHighlightOfNextBlock = (block.userState() != stateBeforeHighlight);
block = block.next();
}
retrieved from https://code.woboq.org/qt5/qtbase/src/gui/text/qsyntaxhighlighter.cpp.html#165
That code (which is fired by a contentsChange signal from the QTextDocument your highlighter is on) will iterate through each block (line) starting from the block that was just modified. Assuming that the state of the block changed based on the typing change that just happened, it will continue to process the following blocks. This means that you need to get your userState correct for every line and Qt should handle the rest.
Given the example
/*
* This is a comment
*
* That I made
*/
You would want to start in the condition where every line had the STATES::COMMENT set except for the last line which should be set to STATES::NONE. Once you do something like deleting the initial /* you need to make sure that the block state is reset to STATES::NONE. That will trigger Qt to rerun the next block, which will also need to change its state, etc.
In my (python) code, I ended up using a combination of print statements and real debugging to track the propagation of state changes and figured out where it was not correctly updating and breaking the chain of updates. Your code looks superficially correct, though I did not try to compile and run it, but I suspect there is a some case being triggered where the state is not being updated correctly after an edit.

Issue when searching QTableWidget using wildcards

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

Creating a QVariantMap in Qt with strings

Apologies for asking something this trivial but I just can't seem to get it right so I guess I've completely misunderstood everything I thought I knew about memory management.
I have a function that parses a network reply for some data and it looks like this:
// Call from another function
QVariantMap *mappedResult = handleReply(reply);
...
// Function
QVariantMap *handleReply(QNetworkReply *reply) {
QVariantMap *result = new QVariantMap;
QVariant testvalue = new QVariant("testvalue");
result->insert("testkey", testvalue);
if (reply->error() > 0) {
qDebug() << "Error number = " + reply->errorString();
QVariant variant = QVariant.fromValue(reply->errorString());
result->insert("error", variant);
} else {
QJsonDocument jsonResponse = QJsonDocument::fromJson(jsonString.toUtf8());
QJsonObject jsonResponseObject = jsonResponse.object();
*result = jsonResponseObject.toVariantMap();
}
return result;
}
If there is no error, the result is parsed fine by the built in toVariantMap function. When there is an error however, I would like to create an entry in the result that is sent back from the function. As you can see in the function, I'm trying to create QVariants from Strings in two different ways.
The first approach gives an error like this:
C:\Qt\5.2.0\mingw48_32\include\QtCore\qvariant.h:466: error: 'QVariant::QVariant(void*)' is private inline QVariant(void *) Q_DECL_EQ_DELETE;
^
The second approach like this:
[PATH] error: expected primary-expression before '.' token QVariant variant = QVariant.fromValue(reply->errorString());
I've also tried setting the values like this:
result->insert("testkey", "testvalue");
result->insert("error", reply->errorString());
The last approach doesn't give compile errors but the result variable in the return statement cannot be inspected in the debugger and as soon as the return statement is executed the application crashes with memory problems indicating I'm not using "new" properly.
"Error accessing memory address 0x...".
If someone with at least a little knowledge could help me sort out how to perform this simple task, I would be very greatful. How can I return a QVariantMap from my function with custom strings as key/value pairs?
Cheers.
I would write your function in the following way (with fixes):
QVariantMap *handleReply(QNetworkReply *reply) {
QVariantMap *result = new QVariantMap;
QVariant testvalue("testvalue"); // <- fixed here
result->insert("testkey", testvalue);
if (reply->error() > 0) {
qDebug() << "Error number = " + reply->errorString();
QVariant variant(reply->errorString()); // <- fixed here
result->insert("error", variant);
} else {
QJsonDocument jsonResponse = QJsonDocument::fromJson(jsonString.toUtf8());
QJsonObject jsonResponseObject = jsonResponse.object();
*result = jsonResponseObject.toVariantMap();
}
return result;
}
However it is still unclear, why do you need to work with a pointer to the variant map instread of passing it by value?

Qt check for valid URL

I am trying to create a Qt application which checks if a URL entered by the user into a text edit is valid.
This is what I have so far but it only ever says the URL entered is valid, even when I enter one which is not.
bool checkUrl(const QUrl &url) {
if (!url.isValid()) {
//qDebug(QString("Invalid URL: %1").arg(url.toString()));
return false;
}
return true;
}
void MainWindow::on_pushButton_clicked()
{
QString usertext = ui->plainTextEdit->toPlainText();
QUrl url = QUrl::fromUserInput(usertext);
if (checkUrl(url))
ui->textEdit->setPlainText("Valid URL.");
else
ui->textEdit->setPlainText("Invalid URL.");
}
Also on the qDebug line there is an error:
/home/user/HTML/mainwindow.cpp:32: error: no matching function for call to ‘qDebug(QString)’
Does anyone know what the problem is as it keeps returning true?
You should use qDebug like this:
qDebug() << QString("Invalid URL: %1").arg(url.toString());
also note that QUrl::isValid() does not check syntax of url. You may want to use regular expressions to validate urls.
QUrl::isValid() only basically checks if the character encoding is right. What are you considering a wrong url?
Re qDebug, the form you use basically encapsulates printf, so it doesn't work with QString. You want to do:
qDebug() << QString("Invalid URL: %1").arg(url.toString());