Skip to content

Instantly share code, notes, and snippets.

@afreerunner
Forked from micjabbour/main.cpp
Created January 9, 2019 02:20
Show Gist options
  • Save afreerunner/67673f93322c4dd5a79785916cbe4f0a to your computer and use it in GitHub Desktop.
Save afreerunner/67673f93322c4dd5a79785916cbe4f0a to your computer and use it in GitHub Desktop.

Revisions

  1. @micjabbour micjabbour created this gist Jan 7, 2017.
    100 changes: 100 additions & 0 deletions main.cpp
    Original file line number Diff line number Diff line change
    @@ -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();
    }