I wish to gain access to the serialization technique used by QSettings and QVariant. For example, if you create a QRect object and store it to an INI file with QSettings you get a line that looks lik开发者_JAVA技巧e this:
value=@Rect(1 2 3 4)
Most of the standard Qt types, and custom ones, have a similar string serialization format for saving/loading. How can I do the same thing?
That is, I have a QVariant and wish to save the data it contains then later load that data back. The saved form should be textual data (like the above) to be usable in normal config files (like INI) or the registry.
Hmm, I looked at the QSettings
source code and it just has hard-coded handling for some common types and then used QDataStream for the rest. That would imply there is no generic way to serialize the data in a textual form.
Qt meta-object system is able to register a large number of operators for custom types. One of them is the StreamOperator. This operator is used by QSettings to write and read QVariant in a configuration file.
So first of all, you will need to implement the two stream operators for the custom type as mentioned by @divanov
QDataStream & operator<< ( QDataStream & stream, const YourClass & yourObject );
QDataStream & operator>> ( QDataStream & stream, YourClass & yourObject );
After that, you need to register these two operators for the custom type to the Qt meta-object system using qRegisterMetaTypeStreamOperators.
The following example describe all steps previously mentioned with the custom type Color.
#include <QMetaType>
#include <QDataStream>
#include <QSettings>
#include <cassert>
// Custom type 'Color'
struct Color
{
uint8_t _red;
uint8_t _green;
uint8_t _blue;
// Stream operator used by QSettings to save a value of type Color
// to configuration file
friend QDataStream& operator<<(QDataStream& out, const Color& color)
{
out << color._red;
out << color._green;
out << color._blue;
return out;
}
// Stream operator used by QSettings to load a value of type Color
// from a configuration file
friend QDataStream& operator>>(QDataStream& in, Color& color)
{
in >> color._red;
in >> color._green;
in >> color._blue;
return in;
}
};
Q_DECLARE_METATYPE( Color )
int main(int argc, char* argv[])
{
Q_UNUSED(argc)
Q_UNUSED(argv)
// Register Color to qt meta-object system
qRegisterMetaType<Color>();
// Register its two streams operator to qt meta-object system
qRegisterMetaTypeStreamOperators<Color>();
// Test it with QSettings!
QSettings configFile("config.ini");
// Save the color
Color saveColor { 12, 13, 14 };
configFile.setValue("Color", QVariant::fromValue(saveColor));
// Load the color
Color loadColor = configFile.value("Color", QVariant()).value<Color>();
// Asserts are successful
assert(loadColor._red == 12);
assert(loadColor._green == 13);
assert(loadColor._blue == 14);
}
Personally I find QVariantMap
and QVariantList
quite handy for these type of things.
Provide convertion functions to your class/structure:
class User {
public:
QVariantMap toVariantMap() const {
QVariantMap map;
map["name"] = m_name;
map["reputation"] = m_reputation;
map["tags"] = m_tags;
return map;
}
static User fromVariantMap(const QVariantMap& map) {
User user;
user.m_name = map["name"].toString();
user.m_reputation = map["reputation"].toInt();
user.m_tags = map["tags"].toStringList();
return user;
}
private:
QString m_name;
int m_reputation;
QStringList m_tags;
}
Save it with toVariantMap
:
settings->setValue("user", user.toVariantMap());
Fetch it with fromVariantMap
:
auto user = User::fromVariantMap(settings->value("user").toVariantMap());
To save list of items other than QString, QVariantList can be used:
QVariantList list;
for (int i = 0; i < m_list.size(); ++i)
list.append(m_list[i]);
map["list"] = list;
The QDataStream class provides serialization of binary data to a QIODevice. You should implement two operators:
QDataStream & operator<< ( QDataStream & stream, const YourClass & yourObject );
QDataStream & operator>> ( QDataStream & stream, YourClass & yourObject );
which will be responsible for serialization and de-serialization of data.
Read more about serialization in Qt
In case you are interested in textual serialization, then you should choose QTextStream as your tool. However, the most of the classes do not have operators able to handle text streams, so you will have to implement them.
精彩评论