QSettings, custom format and class methods as read/write functions.
Hello everybody,
I've run into one problem, but first of all I'll describe what I tried to achieve. I'm writing a multiuser client app with server-side authentication. This app has to store some user's settings on his computer. This settings need to be encrypted with a key, which is stored on the server-side and is sent after user's authentication. Every user has its own unique key.
I came up with the following solution: I've created a wrapper class that contains a QSettings object, an encryption key, setValue(), value(), sync(), writeFile() and readFile() methods. The methods setValue(), value() and sync() are calling the corresponding QSettings's methods. writeFile() and readFile() are declared according to QSettings::WriteFunc and QSettings::ReadFunc and do writing/reading settings to/from the file. They also encrypt/decrypt the file if the encryption key is not NULL.
The class is inside a namespace as all other app stuff.
Now the stripped down header file:
Code:
namespace CLIENT {
{
Q_OBJECT
public:
void sync();
~Settings();
private:
Key key;
};
}
And source file:
Code:
namespace CLIENT {
Settings
::Settings(const QString &user,
const Key
&k,
QObject *parent
){
if (!user.isEmpty())
appname.append(".").append(user);
}
{
s->setValue(key, value);
}
void Settings::sync()
{
s->sync();
}
{
return s->value(key, defaultValue);
}
Settings::~Settings()
{
delete s;
}
{
// Reads data from device, decrypts it with the key and saves to map
}
{
#ifdef DEBUG
qDebug() << Q_FUNC_INFO << endl << "Writing map:" << map;
#endif // DEBUG
// Saves map to QByteArray, encrypts it with the key and writes to device
}
}
Now about the problem:
I get a segfault at line 350 in qmap.h:
Code:
inline const_iterator constBegin() const { return const_iterator(e->forward[0]); }
which traces back to the line 43 of my code (the first access to map).
The debugger tells me that the map is <not in scope>, the device seems to be <not in scope> too.
Am I doing something wrong?
Is there any way I can get my class working with QSettings or do I have to write it from scratch?
I'm using Qt 4.6.2 (minGW).
Re: QSettings, custom format and class methods as read/write functions.
Forgot to mention. If I move writeFile() and readFile() out of the class, i.e., make them regular functions like this:
and change line 6 of source file to
Code:
f
= QSettings::registerFormat("settings", readFile, writeFile
);
everything starts working as expected. But then I'm unable to use per-instance encryption key as there is no way to determine an instance of QSettings that calls writeFile() and readFile() in this case.
PS: It would be much easier if QSettings class provided oveloadable reading and writing methods.
Re: QSettings, custom format and class methods as read/write functions.
Code:
Settings
::Settings(const QString &user,
const Key
&k,
QObject *parent
){
if (!user.isEmpty())
appname.append(".").append(user);
}
I can image that you will have problems with object not being created if you use it in the constructor.
I think this should work:
Code:
f
= QSettings::registerFormat("settings", readFile, writeFile
);
But than you can not call the QSetting constructor unless your Settings object is created:
Thus try putting the last code segment in an initialize function instead of the constructor. readFile and writeFile might not exists.
Re: QSettings, custom format and class methods as read/write functions.
Why are you using this at all like that? (function pointers??)
Why not just define and implement your methods normally?
But if you do, you probably mean to do:
Code:
pReadFunc = &Settings::writeFile;
//Same for pWriteFunc;
f
= QSettings::registerFormat("settings",pReadFunc,pWriteFunc
);
I didn't test my code here for compilation, it should be regarded as pseudo code.
The idea is that you didn't fully described your function signature.
EDIT:
Actually much more is missing - object initialization, and then assigning the function pointer from that object.
Again, this is complicating things WAAAAY more than needed.
Re: QSettings, custom format and class methods as read/write functions.
You don't need a typedef or variable assignment to pass a function pointer. His prototype is already available to the compiler from his class header. Also, how else do you use a callback in c++ without passing a functor?
Re: QSettings, custom format and class methods as read/write functions.
Quote:
You don't need a typedef or variable assignment to pass a function pointer.
No one said you did.
Its just more readable this way, when you don't put the whole definition as parameter - that was not the point I was making.
Quote:
His prototype is already available to the compiler from his class header.
true.
Was to quick to write, before thought through.
Quote:
Also, how else do you use a callback in c++ without passing a functor?
I was on the wrong path.
I thought he was trying to do something else than what I see now he does, and thought the whole approach was complicating things.
But I think I understand the problem now.
Will have to think to see if I can see what can be wrong.
Re: QSettings, custom format and class methods as read/write functions.
Quote:
No one said you did.
Its just more readable this way, when you don't put the whole definition as parameter - that was not the point I was making.
You don't have to define anything, you are simply passing the address of the function. The "definition" aka prototype is already supplied for his function in his class header, and the receiver has a specification for it in the parameter of the function he is calling. Do you seriously think that
Code:
passFuncPointer(someFunc);
must look like
Code:
/*seriously?*/
passFuncPointer(someFunc(int,int,float));
without a typedef?
Here's some code to show you what I mean.
Code:
#include <QDebug>
void someFunc(int p)
{
qDebug() << p;
}
void call_ftor(void(*func)(int))
{
func(13);
}
int main(int argc, char* argv[])
{
/*passing the function pointer*/
call_ftor(someFunc);
}