Skip to content

Instantly share code, notes, and snippets.

@micjabbour
Created January 7, 2017 21:51
Show Gist options
  • Save micjabbour/2bb5b62a239a8d70b210641e59e8655d to your computer and use it in GitHub Desktop.
Save micjabbour/2bb5b62a239a8d70b210641e59e8655d to your computer and use it in GitHub Desktop.
QSettings sqlite format
#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