Qt软件开发文档18---QSettings类的封装与调用,文件路径判断

简述

软件开发时候,往往需要利用QSettings写入ini配置文件
多次调用QSettings的读写加大代码量,同时,修改时也会加大难度。
为此封装一个ConFRouter类,利用QSettings统一管理配置文件里的内容。


类的声明与定义

1. ConFRouter.h

class DLL_API ConFRouter
{
public:
    static ConFRouter* create_confrouter(const QString& path = QString(""));
    void save_file();
    void read_file();
    QString& operator[](const QString& key);
private:
    ConFRouter(const QString& path);
    QString _root;
    QHash _find;

    QString _case_path;
    QString _screen_shot_path;
    QString _video_path;
    QString _display_value;

    std::vector _groups = { 
        "CaseGroup", 
        "PathGroup" 
    };
    std::vector<vector> _keynames = {
        { "case_path" },
        { "video_path", "screen_shot_path", "display_value" }
    };
};

2. ConFRouter.cpp

ConFRouter* ConFRouter::create_confrouter(const QString& path)
{
    static ConFRouter* con_pointer = nullptr;
    if (con_pointer == nullptr)
    {
        assert(path.size() != 0);
        con_pointer = new ConFRouter(path);
    }
    return con_pointer;
}

ConFRouter::ConFRouter(const QString& path)
{
    auto make_hashs = [](const std::vector<vector>& keynames, 
        const std::vector<vector>& pointers) {
        QHash hashs;
        assert(keynames.size() == pointers.size());
        for (size_t i = 0; i < keynames.size(); i++)
        {
            assert(keynames[i].size() == pointers[i].size());
            for (size_t j = 0; j < keynames[i].size(); j++)
                hashs.insert(keynames[i][j], pointers[i][j]);
        }
        return hashs;
    };

    auto set_defult = [=](const std::vector<vector>& pointers, 
        const std::vector<vector> defaults) {
        assert(defaults.size() == pointers.size());
        for (size_t i = 0; i < pointers.size(); i++)
        {
            assert(defaults[i].size() == pointers[i].size());
            for (size_t j = 0; j < pointers[i].size(); j++)
                 *(pointers[i][j]) = defaults[i][j];
        }
    };

    std::vector<vector> defaults = {
        { path + "/vinci_case" },
        { path + "/avi", path + "/screenshot", "0.03" }
    };

    std::vector<vector> pointers = {
        { &_case_path },
        { &_video_path, &_screen_shot_path, &_display_value }
    };

    _root = path;
    _find = make_hashs(_keynames, pointers);
    set_defult(pointers, defaults);
    this->read_file();
}

void ConFRouter::save_file()
{
    std::shared_ptr con = std::shared_ptr(
        new QSettings(_root + "/settings.ini", QSettings::IniFormat),
        [](QSettings *setting) {  delete setting;  }
    );

    for (size_t i = 0; i < _groups.size(); i++)
    {
        con->beginGroup(_groups[i]);
        for (size_t j = 0; j < _keynames[i].size(); j++)
            con->setValue(_keynames[i][j], (*this)[_keynames[i][j]]);
        con->endGroup();
    }

    con->sync();
}

void ConFRouter::read_file()
{
    std::shared_ptr con = std::shared_ptr(
        new QSettings(_root + "/settings.ini", QSettings::IniFormat), 
        [](QSettings *setting) {  delete setting;  }
    );

    for (size_t i = 0; i < _groups.size(); i++)
    {
        con->beginGroup(_groups[i]);
        for (size_t j = 0; j < _keynames[i].size(); j++)
        {
            QString value = con->value(_keynames[i][j]).toString();
            if (value.size() != 0)
                (*this)[_keynames[i][j]] = value;
        }
        con->endGroup();
    }
}

QString & ConFRouter::operator[](const QString & key)
{
    auto pointer = this->_find.find(key);
    assert(pointer != this->_find.end());
    return *(pointer.value());
}

类的调用

1.mainWnd中声明Path

在创建mainWnd时候,在对应得appPath下创建setting.ini

#include "ConFRouter.h"
...
ConFRouter::create_confrouter(QApplication::applicationDirPath());

2.读取setting.ini
读取的信息为QString类型,需要我们自己对类型转换。

void CSettingDlg::read_iniFile()
{
    auto con = ConFRouter::create_confrouter();
    QString screenShotPath = (*con)["screen_shot_path"];
    QString videoPath = (*con)["video_path"];
    QString displayValue = (*con)["display_value"];
    if ((checkFloderPath(screenShotPath) == FloderPath::INVALID)) {
        (*con)["screen_shot_path"] = this->_appPath;
        screenShotPath = this->_appPath;
    }
    if ((checkFloderPath(videoPath) == FloderPath::INVALID)) {
        (*con)["video_path"] = this->_appPath;
        videoPath = this->_appPath;
    }
    bool ok;
    displayValue.toDouble(&ok);
    if (ok == false) {
        (*con)["display_value"] = 0.3;
        displayValue = 0.3;
    }
    con->save_file();
    this->_screen_shot_edit->setText(screenShotPath);
    this->_video_edit->setText(videoPath);
    this->_display_box->setValue(displayValue.toDouble());
}

3.修改setting.ini的内容

void CSettingDlg::write_iniFile()
{
    auto con = ConFRouter::create_confrouter();
    QString screenShotPath = this->_screen_shot_edit->text();
    QString videoPath = this->_video_edit->text();
    double displayValue = this->_display_box->value();
    (*con)["screen_shot_path"] = screenShotPath;
    (*con)["video_path"] = videoPath;
    (*con)["display_value"] = QString("%1").arg(displayValue);
    con->save_file();
}

对路径的判断

读取到的路径,需要写入一个func判断路径是否合理。

int CSettingDlg::checkFloderPath(const QString path)
{
    if (0 == path.size())
        return FloderPath::INVALID;
    QStringList allDirs;
    if (path.contains("/")) 
        allDirs = path.split("/", QString::SkipEmptyParts);
    else
        allDirs = path.split("\\", QString::SkipEmptyParts);
    QString dirPath = allDirs.at(0);
    QFileInfo rootPath(dirPath + "/");
    if (false == rootPath.isRoot())
        return FloderPath::INVALID;
    QDir dir;
    for (size_t i = 1; i < allDirs.size(); i++)
    {
        dirPath = dirPath + "/" + allDirs.at(i);
        if (false == dir.exists(dirPath)) {
            if (false == dir.mkdir(dirPath))
                return FloderPath::INVALID;
        }
    }
    return FloderPath::VALID;
}

你可能感兴趣的:(Qt,软件开发)