|
|
@@ -0,0 +1,100 @@ |
|
|
#include <QtWidgets> |
|
|
#include <QtSql> |
|
|
|
|
|
//to ensure the database connection is closed and removed at the end |
|
|
//of the write/read func call |
|
|
class SQLConnectionRAIIWrapper{ |
|
|
public: |
|
|
SQLConnectionRAIIWrapper(QString fileName){ |
|
|
//use a unique connection name, to ensure thread safety |
|
|
connectionName = QString("SQLSETTINGS%1").arg((int)QThread::currentThreadId()); |
|
|
QSqlDatabase db = QSqlDatabase::addDatabase("QSQLITE", connectionName); |
|
|
db.setDatabaseName(fileName); |
|
|
db.open(); |
|
|
} |
|
|
~SQLConnectionRAIIWrapper(){ |
|
|
getDb().close(); |
|
|
QSqlDatabase::removeDatabase(connectionName); |
|
|
} |
|
|
QSqlDatabase getDb(){ return QSqlDatabase::database(connectionName); } |
|
|
private: |
|
|
QString connectionName; |
|
|
}; |
|
|
|
|
|
//write function creates a temporary file, stores |
|
|
//map in it (using sqlite), writes data from the temp file into the device |
|
|
bool writeSqliteFunc(QIODevice& device, const QSettings::SettingsMap& map){ |
|
|
QTemporaryFile tempFile; |
|
|
if(!tempFile.open()) return false; |
|
|
QString tempFileName = tempFile.fileName(); |
|
|
tempFile.close(); |
|
|
{ |
|
|
SQLConnectionRAIIWrapper connectionWrapper(tempFileName); |
|
|
QSqlDatabase db = connectionWrapper.getDb(); |
|
|
if(!db.isOpen()) return false; |
|
|
QSqlQuery query(db); |
|
|
if(!query.exec("CREATE TABLE IF NOT EXISTS settings(key TEXT PRIMARY KEY, value TEXT);")) |
|
|
return false; |
|
|
query.prepare("REPLACE INTO settings(key, value) VALUES(?, ?)"); |
|
|
QVariantList keys; |
|
|
for(QVariant key: map.keys()) keys.append(key); |
|
|
query.addBindValue(keys); |
|
|
query.addBindValue(map.values()); |
|
|
if(!query.execBatch()) return false; |
|
|
} |
|
|
if(!tempFile.open()) return false; |
|
|
auto bytesWritten = device.write(tempFile.readAll()); |
|
|
tempFile.close(); |
|
|
return bytesWritten > 0; |
|
|
} |
|
|
|
|
|
//uses a similar strategy to read the data from a temporary file into the map |
|
|
bool readSqliteFunc(QIODevice& device, QSettings::SettingsMap& map){ |
|
|
QTemporaryFile tempFile; |
|
|
if(!tempFile.open()) return false; |
|
|
QString tempFileName = tempFile.fileName(); |
|
|
tempFile.write(device.readAll()); |
|
|
tempFile.close(); |
|
|
|
|
|
SQLConnectionRAIIWrapper connectionWrapper(tempFileName); |
|
|
QSqlDatabase db = connectionWrapper.getDb(); |
|
|
if(!db.isOpen()) return false; |
|
|
QSqlQuery query(db); |
|
|
if(!query.exec("SELECT key, value FROM settings;")) |
|
|
return false; |
|
|
while(query.next()){ |
|
|
QString key = query.record().value("key").toString(); |
|
|
QVariant value = query.record().value("value"); |
|
|
map[key]= value; |
|
|
} |
|
|
return true; |
|
|
} |
|
|
|
|
|
int main(int argc, char* argv[]){ |
|
|
QApplication a(argc, argv); |
|
|
|
|
|
const QSettings::Format sqliteFormat = QSettings::registerFormat("sqlite", &readSqliteFunc, &writeSqliteFunc); |
|
|
|
|
|
QWidget w; |
|
|
QFormLayout layout(&w); |
|
|
QLineEdit lineEditA; |
|
|
QLineEdit lineEditB; |
|
|
QPushButton buttonSave("Save"); |
|
|
layout.addRow("KeyA:", &lineEditA); |
|
|
layout.addRow("KeyB:", &lineEditB); |
|
|
layout.addRow(&buttonSave); |
|
|
|
|
|
//read settings |
|
|
QSettings settings("settings.sqlite", sqliteFormat); |
|
|
lineEditA.setText(settings.value("KeyA").toString()); |
|
|
lineEditB.setText(settings.value("KeyB").toString()); |
|
|
QObject::connect(&buttonSave, &QPushButton::clicked, [&]{ |
|
|
//save settings |
|
|
QSettings settings("settings.sqlite", sqliteFormat); |
|
|
settings.setValue("KeyA", lineEditA.text()); |
|
|
settings.setValue("KeyB", lineEditB.text()); |
|
|
}); |
|
|
w.show(); |
|
|
|
|
|
return a.exec(); |
|
|
} |