Created
January 7, 2017 21:51
-
-
Save micjabbour/2bb5b62a239a8d70b210641e59e8655d to your computer and use it in GitHub Desktop.
QSettings sqlite format
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#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(); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment