How Can I deserialize the output QVariant to std::string without using QT.
by reqs, My program could not include a Qt.
QVariant.toString().toStdString();
Example.
file.ini (write with QSetting)
..
ID="\x1\0\0\0\xd0\x8c\xd9\xec\xfb*"
profile_program /* Pseudo Code */
int main ()
{
void* IDQt =getIDFromIniFile("file.ini");
std::string myId = convertID(IDQt);
process(myID);
}
Look in the sources, probably src/corelib/kernel/qvariant.cpp for QDataStream& operator<<(QDataStream&, const QVariant&). That way you'll know what gets written during serialization.
Once you do, you'll see that the operator<< calls QVariant::save(QDataStream&). What's written is as follows:
quint32 QVariant::type()
quint8 QVariant::isNull()
if type()==UserType
QString MetaType::typeName(userType())
end
if the variant is not valid
QString empty
else
-- MetaType::save(...)
end
You need to drill down into QString and QMetaType to figure out how those are serialized.
Related
This is a follow-on from this question.
That article should explain why I am using a quint16 to extract the variant type.
I have derived class MyVariant from QVariant and implemented the QDataStream read operator.
This allows constructs like:
MyVariant vt;
str >> vt;
This is the streaming implementation:
QDataStream& operator>>(QDataStream& str, MyVariant& vt)
{
vt.clear();
quint16 type;
str >> type;
const QMetaType vtype(type);
if (vtype.isValid()) {
vt.create(type, nullptr);
if (!QMetaType::load(str, type, const_cast<void *>(vt.constData()))) {
Q_ASSERT_X(false, "MyVariant", qPrintable(QString("Cannot load type %u").arg(type)));
str.setStatus(QDataStream::ReadCorruptData);
}
}
else {
Q_ASSERT_X(false, "MyVariant", qPrintable(QString("Type %1 is not supported").arg(type)));
}
return str;
}
When the stream comes across a QColor (67), this code fails to create a valid QMetaType for it. QMetaType::isValid() returns false.
What could I possibly have forgotten to do?
Not sure if it matters, but I have added QT += gui to my .pro file.
Edit
I have added...
int type = qRegisterMetaType<QColor>("QColor");
... to my main function.
It returns 67, yet when I hit my streaming function the QMetaType creation still fails.
Okay, I solved this one by pure luck.
In my main, I register the type using...
qRegisterMetaTypeStreamOperators<QColor>("QColor");
And now it works!
Let me know in the comments if I did the right thing or not.
i have a very simple question here, How can i send a string with
tcpserver->write(string);
I tried:
tcpserver->write("string")
and it works, but if i want to input a string in there, i get a "no matching function to call to 'QtcpSocket::write(QString)'"
error,
so i tried converting the string to "data" and then send it, but i got a ton of errors...
And my question is: How can i easly send a string thru my tcpserver?
(I should also mention, that i am very new to programming)
You need to convert string to QByteArray, for example:
tcpserver->write(string.toLocal8Bit());
tcpserver->write(string.toUtf8());
Try tcpserver->write((const char *)string.data(), string.length()*sizeof(QChar));
QTcpSocket has 3 overloads for write () function
qint64 write (const char *data);
qint64 write (const char *data, qint64 len);
qint64 write (const QByteArray &data);
So Convert QString to any of them. Just try
tcpserver->write (string.toLatin1 ());
I am trying to learn how to use JSON and the Qt JSON classes. For example I wnat to create a simple QJsonDocument, save it to a file, load it into a different QJsonDocument and compare results.
I managed to create a QJsonDocument. However there is no simple command in the QJsonDocument interface to save it to a file. The same goes for loading the document from a file.
#include <QJsonObject>
#include <QJsonDocument>
#include <QVariant>
int main()
{
QVariantMap map;
map.insert("integer", 1);
map.insert("double", 2.34);
map.insert("bool", QVariant(true));
map.insert("string", "word");
QJsonObject object = QJsonObject::fromVariantMap(map);
QJsonDocument document;
document.setObject(object);
// ?? save document to file
// ?? load file to document
return 0;
}
This answer shows how to load the document by
reading to a QFile
converting QFile to a QString
converting the QString to a QByteArray
constructing the QJsonDocument from the QByteArray
Is there a more straightforward way to do this?
Personally, I think that code [that you linked to] looks a bit messy. Warning: head compiled code follows.
QJsonDocument loadJson(QString fileName) {
QFile jsonFile(fileName);
jsonFile.open(QFile::ReadOnly);
return QJsonDocument().fromJson(jsonFile.readAll());
}
void saveJson(QJsonDocument document, QString fileName) {
QFile jsonFile(fileName);
jsonFile.open(QFile::WriteOnly);
jsonFile.write(document.toJson());
}
This may not be perfect: it assumes QFile instead of QIODevice, but if you're dealing with only local files maybe it won't matter. You can then use these functions instead of repeating the Json load/save code everytime you need to load/save Json.
No need for converting to string and back. With QSettings and QVariant classes you can easily do that. Create QVariant object from QJsonDocument and save it with QSettings. Look at functions QJsonDocument::fromVariant and QJsonDocument::toVariant. Combine them with QSettings class and specifically void QSettings::setValue ( const QString & key, const QVariant & value ) method, that works well with QVariant and that's it.
Also QSettings class has this constructor QSettings::QSettings ( const QString & fileName, Format format, QObject * parent = 0 )
that would allow you to set path to the file - fileName variable
This is a follow up to a previous question: Qt ActiveX
I am trying to use an ActiveX control in my program.
QAxWidget* mAX = new QAxWidget();
mAX->setControl("{XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX}");
I know that there is a function like the one below (used getDocumentation()):
SendCommand(QString input, QString& output)
But when I try to execute it:
QString returString;
mAX->dynamicCall("SendCommand(QString,QString&)","something",returnString);
I always get:
returString = "";
I searched the web and saw a similar bug which was reported on their bug tracker. It does not seem fixed yet:
Calling functions through dynamicCall() don't return values by QVariant
Also a post where someone seems to have the same problem:
QAxObject and dynamicCall
Anybody know of a solution/work around ?
EDIT:
The original function is SendCommand(LPCTSTR command,BSTR* ret).
Maybe an issue with the way the BSTR* is handled as a &QString ?
you can use this solution
QString strRetVal;
QVariant returnValue("");
QVariant param1("something");
QList<QVariant> inplist;
inplist<<param1;
inplist<<returnValue;
mAX->dynamicCall("SendCommand(QString,QString&)",inplist );
strRetVal=inplist.at(1).toString();
From looking at the documentation, you are not calling the function correctly. You are passing in a QString, yet the function takes a QVariant. Since QVariant doesn't have explicit constructors (by design), a temporary QVariant is created and passed to dynamicCall. As a consequence your returnValue doesn't get updated.
QVariant dynamicCall( const char * function, const QVariant & var1 = QVariant(), ...
, const QVariant & var8 = QVariant() )
I think that everything will work when you use a QVariant instead.
QVariant returnValue;
mAX->dynamicCall("SendCommand(QString,QString&)", "something", returnValue );
Well, what i want is to implement functions that works like the macros SIGNAL and SLOT but with my own implementation, so the goal is that the function (or my own macro if i can create it) receive a parameter like an String "mycustomsignal" and he return a const char* "2mycustomsignal(double,int)" so i do that using a QMap for store this asociation QMap<"signal name","signal signature">, i fill it in another function.
in this case my QMap is this->signals so i search the signature "mycustomsignal(something)" with the key "mycustomsignal" and prepend the code that QObject::connect recognize for signals and i get "2mycustomsignal(something)" so i convert it in const char* because QObject::connect have this parameters in this format and i want to use also in conjuntion with SIGNAL and SLOT MACROS like this:
QObject::connect(customwidget, customwidget->getSignal("somesignal"),
somewidget, SLOT(someslot()));
the function that i use is (only for undertand what i do):
const char* SomeClass::getSignal(QString signalName) {
QString signalsignature = this->signals.value(signalName);
signalsignature.prepend(QString::number(QSIGNAL_CODE));
QByteArray ba = signalsignature.toLatin1();
return signalformated; //Here is the lost of data because QByteArray only exist in the function
}
but this return a pointer to local and the source of the data is destroyed when the function ends, so how i could do this with a function or creating my own MACRO?
Thanks for any help or suggestion.
You have to return QByteArray from your method, return ba;, then get the const char* from the return value:
QObject::connect(customwidget, customwidget->getSignal("somesignal").constData(),
somewidget, SLOT(someslot()));
If you really want to return char pointer, then you have to keep the QByteArray around, for example by adding it to a QList member variable of the same object, so it will get destructed when the instance gets destructed.