⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 settings.cc

📁 c++的guiQt做的开发
💻 CC
字号:
/** @file Settings - class handling basic application settings, reading and writing values with keys and also storing and restoring more complex settings (window and toolbar positions), reading Paths and expanding environment variables in settings. QSettings with two files (user file in $HOME (readwrite) and system file with default settings (readonly)) is used as backend for storing the data @author Martin Petricek*/#include "settings.h"#include "util.h"#include "staticsettings.h"#include <stdlib.h>#include <QApplication>#include <QDesktopWidget>#include <QDir>#include <QList>#include <QMap>#include <QRegExp>#include <QSettings>#include <QSplitter>#include <QString>#include <QStringList>namespace gui {/** All defined aliases (variables mappings) */QMap<QString,QString> aliases;using namespace std;using namespace util;/** "Root" item of all configuration settings, which are relative to this item This is hardcoded default whouch should be always changed by calling Settings::setAppKey */QString APP_KEY = "/LibMPW/";/** Name of variable which will be expanded to full path to the executable */const QString APP_PATH_VAR = "APP_BIN";/** Name of variable which will be expanded to data directory */const QString DATA_PATH_VAR = "APP_DATA";/** Directory where all data files would be stored (icons, default config, etc ...) This is hardcoded default whouch should be always changed by calling Settings::setPaths*/QString DATA_PATH = "/usr/local/share/libmpw";/** Config directory name (will be used relative to $HOME) This is hardcoded default whouch should be always changed by calling Settings::setPaths*/QString CONFIG_DIR = ".libmpw";/** Config file name (in CONFIG_DIR) This is hardcoded default whouch should be always changed by calling Settings::setPaths*/QString CONFIG_FILE = "libmpw.cfg";/** delete settings object (and save settings) This function is called at application exit */void saveSettings(void) { delete globalSettings;//this causes settings to be saved to disk}/** One object for application, holding all global settings. Should be thread-safe. This instance is used from other files */Settings *globalSettings=NULL;/** Set name of application, used while storing the settings. This will be used as root key for storing settings. This must be called before creating first instance of Settings @param key New application key. Should not contain any slashes*/void Settings::setAppKey(const QString &key) { if (globalSettings) return; APP_KEY="/"+key+"/";}/** Add alias for a variable @param origName Original variable name @param newName New variable name*/void Settings::addAlias(const QString &origName, const QString &newName) { aliases[newName]=origName;}/** Set global paths used by settings This must be called before creating first instance of Settings @param dataPath DATA_PATH, path to application data files, usually /usr/share/local/[application name] @param configDir CONFIG_DIR, name of directory in $HOME which will hold user settings. Configuration file will be stored in it @param configFile CONFIG_FILE, name of configuration files: file in CONFIG_DIR will hold changeable settings and in DATA_PATH will hold default unchangeable settings*/void Settings::setPaths(const QString &dataPath, const QString &configDir, const QString &configFile) { if (globalSettings) return; DATA_PATH=dataPath; CONFIG_DIR=configDir; CONFIG_FILE=configFile;}/** Return DATA_PATH, path to application data files*/QString Settings::dataPath() { return DATA_PATH;}/** Return CONFIG_DIR, name of directory holding configuration*/QString Settings::configDir() { return CONFIG_DIR;}/** Return CONFIG_FILE, name of configuration file*/QString Settings::configFile() { return CONFIG_FILE;}/** Install atexit handler, that will save settings on program exit This must be called after creating instance of Settings*/void Settings::installExitHandler() { if (!globalSettings) return; atexit(saveSettings);}/** Return Instance of Settings. Ensures only one instance of Settings exists at any time (singleton) If no instance exists, it is created. @return existing Settings object*/Settings* Settings::getInstance() { if (!globalSettings) globalSettings=new Settings(); return globalSettings;}/** private initialization function */void Settings::init() { initSettings();}/** Read settings with given key from configuration file and return as QString @param key Key to read from settings @param defValue default value to use if key not found in settings. @return Value of given setting */QString Settings::read(const QString &key,const QString &defValue/*=QString::null*/) { QString x=set->value(APP_KEY+key,QVariant(QString::null)).toString(); if (x.isNull()) x=staticSet->readEntry(key,defValue); return x;}/** Read settings with given key from configuration file and return as bool @param key Key to read from settings @param defValue default value to use if key not found in settings. @return Value of given setting (true or false) */bool Settings::readBool(const QString &key,bool defValue/*=false*/) { QString k=read(key); if (k.isNull()) return defValue; //Positive integer, "T" and "True" (regardless of case) are considered "true". Everything else "false" k=k.trimmed().toLower(); int intVal=k.toInt(); if (intVal>0) return true; else if (k=="t") return true; else if (k=="true") return true; return false;}/** Read settings with given key from configuration file and return as integer @param key Key to read from settings @param defValue default value to use if key not found in settings. @return Value of given setting*/int Settings::readNum(const QString &key,int defValue/*=0*/) { QString k=read(key); bool ok; int x=k.toInt(&ok); if (!ok) return defValue; return x;}/** Read settings with given key from configuration file and return as QString Any environment variable references (in form $VARIABLE) are expanded in the string. @param key Key to read from settings @param defValue default value to use if key not found in settings. @return Value of given setting*/QString Settings::readExpand(const QString &key,const QString &defValue/*=QString::null*/) { QString x=read(key,defValue); x=expand(x); return x;}/** creates and inits new QSettings Object. Set paths to config files*/void Settings::initSettings() { QDir home=QDir::home(); home.mkdir(CONFIG_DIR); home.cd(CONFIG_DIR);// QSettings::setPath(QSettings::IniFormat,QSettings::UserScope,home.absolutePath()); //Need to specify exact filename in case of windows set=new QSettings(home.absolutePath()+'/'+CONFIG_FILE,QSettings::IniFormat);// set->setPath(QSettings::IniFormat,QSettings::UserScope,home.absolutePath()); staticSet=new StaticSettings(); //Look in data directory bool haveSettings=staticSet->tryLoad(DATA_PATH,CONFIG_FILE); //Look in directory with the binary -> lowest priority if (!haveSettings) haveSettings=staticSet->tryLoad(appPath(),CONFIG_FILE);}/** Given name of the file, finds and returns full path to the file, considering all relevant settings \see readPath @param nameOfPath Name of paths in settings for this file (e.g. "icon") @param fileName Name of file. If not specified, the path itself is the filename we want to find @param prefix Path prefix (Can be specified if desired to read from different configuration key than default) @return QString with full path to the file, or NULL if no file found in path*/QString Settings::getFullPathName(const QString &nameOfPath,QString fileName/*=QString::null*/,const QString &prefix/*=QString::null*/) { if (fileName.isNull()) {  fileName=""; } if (fileName.startsWith("/")) { //absolute path -> no change  return fileName; } QStringList path; if (prefix.isNull()) {  path=readPath(nameOfPath); } else {  path=readPath(nameOfPath,prefix); } QString absName; for(QStringList::Iterator it=path.begin();it!=path.end();++it) {  if (fileName=="") {   absName=*it;  } else {   absName=*it+"/"+fileName;  }  if (QFile::exists(absName)) return absName; } return QString::null;}/** Remove key from user settings, effectively restoring the setting to its default value @param key Key to remove*/void Settings::remove(const QString &key) { set->remove(key);}/** Remove all keys directly under specified key according to hiararchic structure @param key Key to remove*/void Settings::removeAll(const QString &key) { set->beginGroup(key); QStringList all=set->childKeys(); for(int i=0;i<all.count();i++) {  set->remove(all[i]); } set->endGroup(); //At last, try to remove the key itself set->remove(key);}/** Return path to application. Must be called after QApplication instance is created Cache the result, so further calls will return the cached value*/QString Settings::appPath() { static QString appPathCached=QString::null; //Get application path if (appPathCached.isNull()) {  appPathCached=qApp->applicationDirPath();  appPathCached=QDir(appPathCached).absolutePath(); } return appPathCached;}/** Expand single variable @param var name of the variable @return Value of the variable or empty string if the variable does not exist*/QString Settings::expandSingle(const QString &var) { if (aliases.contains(var)) return expandSingle(aliases[var]); QString envVar; /* home() is special - it is equal to regular $HOME on unixes, but might  expand to "application data" directory on windows if HOME is not set */ if (var=="HOME") envVar=QDir::home().path(); else if (var==APP_PATH_VAR) envVar=appPath(); else if (var==DATA_PATH_VAR) envVar=DATA_PATH; else envVar=getenv(var.toUtf8()); if (envVar==QString::null) { //variable not found in environment  envVar=""; } return envVar;}/** Expand environment variables in given string (like $HOME, etc ..) @param s String to expand @return QString with variables expanded*/QString Settings::expand(QString s) { QRegExp r("\\$([a-zA-Z0-9_]+|\\{[_a-zA-Z0-9]+\\})|(\\\\.)"); QString var, envVar;  int pos=0;  while((pos=r.indexIn(s,pos))!=-1) { //while found some variable   if (r.cap(2).length()>0) {// Found \something -> skip    envVar=r.cap(2).mid(1);   } else { //Found $VARIABLE    var=r.cap(1);    if (var[0]=='{') var=var.mid(1,var.length()-2);    envVar=expandSingle(var);   }   s=s.replace(pos,r.matchedLength(),envVar);   pos+=envVar.length();//Move to end of expanded string  } return s;}/** Read path list element from config file. Expands variables ($HOME, etc ...) and return as string list Path elements are expected to be separated by semicolon Trailing slashes are removed from path elements @param name Identifier of path in config file @param prefix Path prefix (Can be specified if desired to read from different configuration key than default "path"/) @return QStringList containing expanded path directories */QStringList Settings::readPath(const QString &name,const QString &prefix/*="path/"*/) { QString path=read(prefix+name,"."); QStringList s=path.split(";"); QRegExp stripTrail("(.)/+$"); for(QStringList::Iterator it=s.begin();it!=s.end();++it) {  //Trim starting and ending whitespace  *it=(*it).trimmed();  //Expand environment variables in path component  *it=expand(*it);  //Trim trailing slashes  *it=(*it).replace(stripTrail,"\\1");  *it=QDir::convertSeparators(*it); } return s;}/** read list of values from config file and return as string list List elements are expected to be separated by defined separator (default is comma) @param name Identifier of list in config file @param separator String separating items in the list @return QStringList containing items from list */QStringList Settings::readList(const QString &name,const QString &separator/*=","*/) { QString lst=read(name,""); QStringList s=lst.split(separator); return s;}/** Default constructor */Settings::Settings() { init();}/** flushes settings, saving all changes to disk */void Settings::flush() { delete set; delete staticSet; initSettings();}/** Default destructor */Settings::~Settings() { delete set; delete staticSet;}/** Save window/widget size and position to settings. @param win Widget that will have it's size and position stored @param name Name of key to be used in configuration*/void Settings::saveWindow(QWidget *win,const QString &name) { QString line; line+=QString::number(win->width()); line+=","; line+=QString::number(win->height()); line+=","; line+=QString::number(win->x()); line+=","; line+=QString::number(win->y()); write("gui/windowstate/"+name,line);}/** Write settings with given key and value to configuration @param key Key to write to settings @param value Value to write to settings */void Settings::write(const QString &key,const QString &value) { set->setValue(APP_KEY+key,value); emit settingChanged(key);}/** Write settings with given key and value to configuration @param key Key to write to settings @param value Value to write to settings */void Settings::write(const QString &key, int value) { set->setValue(APP_KEY+key,value); emit settingChanged(key);}/** Restore window/widget size and position from setting. @param win Widget that will be resized and moved @param name Name of key to be used in configuration*/void Settings::restoreWindow(QWidget *win,const QString &name) { QDesktopWidget *desk = QApplication::desktop(); QString line=read("gui/windowstate/"+name); QStringList pos=explode(',',line); if (pos.count()!=4) return;//No previous window state information available, or it is invalid int x,y,w,h; w=pos[0].toInt(); h=pos[1].toInt(); x=pos[2].toInt(); y=pos[3].toInt(); if (w<=0 || h<=0) return;//Negative/null size is invalid int dw=desk->width(); int dh=desk->height(); //if window is offscreen, move it to screen if (x<-w+1) x=-w+1; //Offscreen -> Onscreen if (y<-h+1) y=-h+1; //Offscreen -> Onscreen if (x>dw-1) x=dw-1; //Offscreen -> Onscreen if (y>dh-1) x=dh-1; //Offscreen -> Onscreen win->resize(w,h); win->move(x,y);}/** Save splitter positions to settings. @param spl Splitter to save positions @param name Name of key to be used in configuration*/void Settings::saveSplitter(QSplitter *spl,const QString &name) { QList<int> siz=spl->sizes(); QString line; int cnt=siz.size(); for (int i=0;i<cnt;i++) {  line+=QString::number(siz[i]);  if (i<cnt-1) line+=","; } write("gui/windowstate/"+name,line);}/** Restore splitter positions from setting. @param spl Splitter to be resized @param name Name of key to be used in configuration*/void Settings::restoreSplitter(QSplitter *spl,const QString &name) { QString line=read("gui/windowstate/"+name); QStringList pos=explode(',',line); int cnt=pos.count(); QList<int> splSize; if (cnt<2) return;//No previous window state information available, or it is invalid for(int i=0;i<cnt;i++) {  int v=pos[i].toInt();  if (v<=0) return;//Negative/null size is invalid  splSize.append(v); } spl->setSizes(splSize);}} // namespace gui

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -