Qt setFilter searching? [duplicate] - c++

I have a problem with printing in Qt.
I have HTML code in QString variables. In this code I want to insert data from a database.
I get an error:
E:\apprendreQt\gestionstock6\vente.cpp:117: error: invalid operands of types
'const char*' and 'const char [27]' to binary 'operator+'
How can I fix this?
Here is my code:
int num_bl = ui->numeroBLlineEdit->text().toInt() ;
QString html;
QString requette = "select num_facture,date,nom,prenom,code_fiscale,designation,qte_out, prix,(qte_out * prix ) as Montant, sum(qte_out * prix) as Total from ventes join produits_en_ventes join clients join produits on ventes.vente_id = produits_en_ventes.vente_id and ventes.client_id = clients.client_id and produits_en_ventes.produit_id = produits.produit_id where ventes.client_id = :client_id ";
if(!m_db->isOpen())
QMessageBox::critical(this,tr("Inventoria Solution"),m_db->lastError().text()) ;
else{
m_query->clear();
m_query->prepare(requette);
m_query->bindValue(":client_id ", num_bl);
if(!m_query->exec())
QMessageBox::critical(this,tr("Inventoria Solution"),m_query->lastError().text()) ;
else{
html += " <table>"
"<thead>"
"<tr>"
"<th>N°</th>"
"<th>Désignation</th>"
"<th>Qte</th>"
"<th>Prix Unitaire</th>"
"<th>Montant</th>"
" </tr>"
"</thead>";
while(m_query->next())
{
int num_article = 1;
html += "<tr> <td>" + num_article + "</td> <td>"+m_query->value(5).toString()+"</td> <td>"+m_query->value(6).toInt() + "</td> <td>"+m_query->value(7).toInt() + "</td> <td>" + m_query->value(8).toInt() + "</td></tr>";
num_article++;
}
html += "<tfoot>"
"<tr>"
"<td>Total:"+ m_query->value(9).toInt()+"</td>"
"</tr>"
"</tfoot>"
"</table>";
}
print_Html(html);
}

I'm not sure about your error. However, AFAIK a Qstring cannot be concatenated with an int as such.
int myInt = 0;
QString text = "someString" + myInt; // WRONG
int myInt = 0;
QString text = "someString" + QString::number( myInt ); // CORRECT
or
int myInt = 0;
QString text = "someString" % QString::number( myInt ); // CORRECT

If you use operator+, you need to provide QString as an argument, but you use integer values instead: html += "<tr> <td>" + num_article, where num_article is declared as integer. You can replace it with, for example: QString::number(num_article). The same in this line:
"<td>Total:"+ m_query->value(9).toInt()+"</td>"
should be replaced with
"<td>Total:"+ m_query->value(9).toString()+"</td>"

in Qt5 you can use the QStringLiteral macro for each string that doesn't need to be localized to transform all the string literals from const char* (the C++ default) into QString, this will also make creation of those QStrings cheaper (on compilers that support it)
for Qt4 you can use the QString(const char*) constructor or QString::fromAscii(const char*) static function

Related

QSqlQuery, wrong number of parameters for prepared statement error

I am relative new to Qt/QSqlQuery, and in my current project I need to incorporate pgcrypto module, or pgp_sym_encrypt/decrypt function to be exact, into the regular SELECT/INSERT queries.
Here's the code that has been giving me problems:
bool BaseDAO::insertIntoDb(const DataObject &data)
{
QVariantMap dataMap = data.toQVariantMap();
QString rows = getFieldsStringForSql(dataMap);
QString placeholders = getPlaceholderStringForSql(dataMap);
QSqlQuery query = DatabaseDriver::getInstance().prepareQuery(
"INSERT INTO " + getTableName() + " " + rows + " VALUES " + placeholders +
R"( RETURNING ")" + getPKString() + R"(")" );
bindValuesToQuery(query, dataMap);
query.setForwardOnly(true);
query.exec(); // <-- where error occurs
...
...
}
QString BaseDAO::getPlaceholderStringForSql(const QVariantMap& data) const
{
QString fields = "(";
int valueCount = data.count();
const QList<QString> keys = data.keys();
if(valueCount > 0)
fields += ":" + keys[0];
for(int i = 1; i < valueCount; ++i)
{
if(!QString::compare(getTableName(), "patient") && !QString::compare(keys[i], "name"))
fields += ", pgp_sym_encrypt(:name, '" + m_pw + "')"; // need to encrypt name
else
fields += ", :" + keys[i];
}
fields += ")";
return fields;
}
void BaseDAO::bindValuesToQuery(QSqlQuery& query, const QVariantMap& data) const
{
const QVariantList valueList = data.values();
const QList<QString> keys = data.keys();
int valueCount = valueList.count();
for (int i = 0; i < valueCount; i++)
{
const QVariant &val = valueList[i];
switch(val.type()) {
case QVariant::Date:
query.bindValue(":" + keys[i], val.toDate().toString("yyyy-MM-dd"));
break;
case QVariant::Time:
query.bindValue(":" + keys[i], val.toTime().toString("hh:mm:ss.zzz"));
break;
case QVariant::DateTime:
query.bindValue(":" + keys[i], val.toDateTime().toString("yyyy-MM-ddThh:mm:ss.zzz"));
break;
default:
query.bindValue(":" + keys[i], val);
break;
}
}
}
I printed out the INSERT query before it got executed with query.lastQuery() and it looks like this:
INSERT INTO patient ("birthDate", "isMarked", "isProtected", "isTemporary", "modificationDate", "modificationTime", "name", "patientID", "permissionGroup", "sex")
VALUES
(:birthDate, :isMarked, :isProtected, :isTemporary, :modificationDate, :modificationTime, pgp_sym_encrypt(:name, 'password'), :patientID, :permissionGroup, :sex)
RETURNING "idx"
and this is the error message I got:
Fatal Error: wrong number of parameters for prepared statement "qpsqlpstmt_4"
DETAIL: Expected 11 parameters but got 1.
QPSQL: Unable to create query, Query: <<***>>.
The error totally got me confused. There are 10 parameters, but it somehow expects 11 and only gets 1? Any help is greatly appreciated!
I would recommend to rewrite getPlaceholderStringForSql
void BaseDAO::bindValuesToQuery(QSqlQuery& query, const QVariantMap& data) const
{
for(const QString & key : data.keys())
{
const QVariant &val = data.value(key);
// According to Qt doc: Note that the placeholder mark (e.g :) must be included
// when specifying the placeholder name.
const QString placeholder = QString(":%1").arg(key);
switch (val.type()) {
case QVariant::Date:
query.bindValue(placeholder,val.toDate().toString( "yyyy-MM-dd"));
break;
case QVariant::Time:
query.bindValue(placeholder,val.toTime().toString("hh:mm:ss.zzz"));
break;
case QVariant::DateTime:
query.bindValue(placeholder,val.toDateTime().toString("yyyy-MM-ddThh:mm:ss.zzz"));
break;
default:
query.bindValue(placeholder,val);
break;
}
}
Use raw litteral string for pgp_sym_encrypt(:name, '" + m_pw + "')"
R"(pgp_sym_encrypt(:name, ')" + m_pw + R("'))"
The main problem of this code is that you suddenly add a database dependency in an API (QSqlDatabase and your base code using QSqlDatabase) which shall remain database independant. A much better solution would be to use c++ directly to encrypt ans decrypt the name. Or if you absolutely want to use SQL, you should probably create two stored procedure (encrypt_field and decrypt_field) encapsulating pgp_sym_encrypt and pgp_sym_decrypt. Then you should be able to make a query via a QSqlQuery calling this stored procedures. The result of encrypt_field can be add in the insert/update SQL query while the result of decrypt_field wil be used after a SELECT query.

What wrong I have done? The function of GetDiskFreeSpaceExA didn't work at all

I tried to use GetDiskFreeSpaceExA function, but it doesn't work:
int drvNbr = PathGetDriveNumber(db7zfolderw);
if (drvNbr == -1) // fn returns -1 on error
{
const char * errmsg = "error occured during get drive number";
strcpy_s(retmsg, strlen(errmsg) + 1, errmsg);
return -3;
}
char driverletter = (char)(65 + drvNbr);
string driverstr(1, driverletter);
driverstr = driverstr + ":";
PULARGE_INTEGER freespace = 0;
PULARGE_INTEGER totalnumbtype = 0;
PULARGE_INTEGER totalnumberfreebyte = 0;
fileSize = SzArEx_GetFileSize(&db, i);
BOOL myresult=GetDiskFreeSpaceExA(
driverstr.c_str(),
freespace,
totalnumbtype,
totalnumberfreebyte
);
The value of variable freespace is 0. I have no idea why it didn't work if the value of variable which is driverstr.c_str() was D:?
Thanks for your help.
You need to supply pointers to variables that will hold the value returned. Right now you a re supplying null pointers so nothing is retured:
::ULARGE_INTEGER freespace{};
::ULARGE_INTEGER totalnumbtype{};
::ULARGE_INTEGER totalnumberfreebyte{};
::BOOL myresult
{
::GetDiskFreeSpaceExA
(
driverstr.c_str()
, &freespace
, &totalnumbtype
, &totalnumberfreebyte
)
};
It would also be a good idea to use wide char versions of these functions.

Concatenating TFields values

I have a calculated fields in a client dataset named full address of type Memo.
I want to concatenate address fields, something like this:
TField* f = customersCDS->FieldByName("full_address");
if(f)
{
f->Value = customersCDS->FieldByName("address_line1")->Value;
f->Value += "\n";
f->Value += customersCDS->FieldByName("address_line2")->Value;
..
}
However, the above don't work. I get compiler error:
E2015 Ambiguity between '_fastcall operator Variant::float() const' and '_fastcall operator Variant::double() const'
In the end, I want to bind the calculated field with a TMemo, showing the full address on multiple lines.
TField::Value is a property. You cannot use compound assignment operators, like +=, with properties. You have to use + and = separately, eg:
TField* f = customersCDS->FieldByName("full_address");
if (f)
{
f->Value = customersCDS->FieldByName("address_line1")->Value;
f->Value = f->Value + String("\n");
f->Value = f->Value + customersCDS->FieldByName("address_line2")->Value;
..
}
In which case, you are better off using a variable instead:
TField* f = customersCDS->FieldByName("full_address");
if (f)
{
String s = customersCDS->FieldByName("address_line1")->Value;
s += "\n";
s += customersCDS->FieldByName("address_line2")->Value;
//...
f->Value = s;
}

Parameterized Query Returns no Results using C++ .Net MySQL Connector

I cannot seem to find any resolution to this issue on my own. I use this generic function to retrieve data from a database like so:
int id = 29
ArrayList^ classes = getClassesGeneric("dep_id", "=", id.ToString());
However, this returns no results. If I query the database through MySQL Workbench or without parameters it works fine. What am I missing?
ArrayList^ Accessor::getClassesGeneric(String^ col, String^ op, String^ value)
{
ArrayList^ result = gcnew ArrayList();
this->cmd = gcnew MySqlCommand("SELECT * FROM rpos_db.classes WHERE #col #op #value;", this->con);
try
{
this->cmd->Parameters->AddWithValue("#col", col);
this->cmd->Parameters->AddWithValue("#op", op);
this->cmd->Parameters->AddWithValue("#value", value);
this->cmd->Prepare();
MySqlDataReader^ r = this->cmd->ExecuteReader();
while (r->Read())
{
Class^ c = gcnew Class();
c->id = r->GetInt32(0);
c->dep_id = r->GetInt32(1);
c->name = r->GetString(2);
c->code = r->GetString(3);
result->Add(c);
}
r->Close();
}
catch (Exception^ ex)
{
MessageBox::Show(ex->StackTrace, ex->Message);
}
return result;
}
Using the function like this produces the indented result:
classes = getClassesGeneric("1", "=", "1");
Parameters can only be used to replace literals, not object names or syntactic elements, such as the = operator. You'd either have to hardcode it. If you want to pass them dynamically, you'd have to use string manipulation:
ArrayList^ Accessor::getClassesGeneric(String^ col, String^ op, String^ value)
{
ArrayList^ result = gcnew ArrayList();
this->cmd = gcnew MySqlCommand
("SELECT * FROM rpos_db.classes WHERE " +
col + " " + op + " #value;", this->con);
try
{
this->cmd->Parameters->AddWithValue("#value", value);
this->cmd->Prepare();
MySqlDataReader^ r = this->cmd->ExecuteReader();

How can i convert entity character(Escape character) to HTML in QT?

I want to convert entity character(Escape character) to HTML in QT, please help me....
i.e: I want to replace " with ", > with >
=====This is my code that not worked====
QString MyApp::ReplaceString(const QString Data, const QString &Before, const QString &After)
{
QString Result = Data;
Result.replace(Before, After, Qt::CaseInsensitive);
return Result;
}
========
QTextCodec *codec = QTextCodec::codecForName("UTF-8");
QByteArray data=pReply->readAll();
QString str = codec->toUnicode((const char *)data);
str = Qt::escape(str);
str = ReplaceString(str, """, "\"");
str = ReplaceString(str,">", ">");
I'm not sure I understand what you want, just guessing. You can use QTextDocument. Try something like this:
QTextDocument text;
text.setHtml("<>"");
QString plain = text.toPlainText();
qDebug("%s.", qPrintable(plain));
Remember that QTextDocument needs the gui module.
I think this will solve your problem.
QString escaped=
QString(myhtml).replace("&","&").replace(">",">").replace("<","<");
Test escape() function:
QString plain = "#include <QtCore>"
QString html = Qt::escape(plain);
// html == "#include <QtCore>"
and convertFromPlainText() function:
QString Qt::convertFromPlainText ( const QString & plain, WhiteSpaceMode mode = WhiteSpacePre )
Hello to convert non ASCII character to &#XXX; (where XXX is a number):
/***************************************************************************//*!
* #brief Encode all non ASCII characters into &#...;
* #param[in] src Text to analyze
* #param[in,opt] force Force the characters "list" to be converted.
* #return ASCII text compatible.
*
* #note Original code: http://www.qtforum.org/article/3891/text-encoding.html
*
* #warning Do not forget to use QString::fromUtf8()
*/
QString encodeEntities( const QString& src, const QString& force=QString() )
{
QString tmp(src);
uint len = tmp.length();
uint i = 0;
while( i<len )
{
if( tmp[i].unicode() > 128 || force.contains(tmp[i]) ){
QString rp = "&#"+QString::number(tmp[i].unicode())+";";
tmp.replace(i,1,rp);
len += rp.length()-1;
i += rp.length();
}else{
++i;
}
}
return tmp;
}
/***************************************************************************//*!
* #brief Allows decode &#...; into UNICODE (utf8) character.
* #param[in] src Text to analyze
* #return UNICODE (utf8) text.
*
* #note Do not forget to include QRegExp
*/
QString decodeEntities( const QString& src )
{
QString ret(src);
QRegExp re("&#([0-9]+);");
re.setMinimal(true);
int pos = 0;
while( (pos = re.indexIn(src, pos)) != -1 )
{
ret = ret.replace(re.cap(0), QChar(re.cap(1).toInt(0,10)));
pos += re.matchedLength();
}
return ret;
}
Basic usage:
qDebug() << encodeEntities(QString::fromUtf8("éà#<>hello the world €"),QString("<>"));
// Will print: éà#<>hello the world €
qDebug() << decodeEntities("aßéplopéàçê€");
// Will print: hello world