00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 #include <qcolor.h>
00020 #include <qregexp.h>
00021 #include <qdict.h>
00022 #include <qdir.h>
00023 #include <qvaluelist.h>
00024 #include <iostream>
00025 #include <qregexp.h>
00026 #include <fun/SerialTree.h>
00027 #include <fun/Serializer.h>
00028 #include <fun/Deserializer.h>
00029 #include <fun/ConfigFile.h>
00030
00031
00032
00033
00034 namespace fun {
00035 INSTANTIATOR(ConfigFile)
00036
00037
00038 ConfigFile ConfigFile::funconfig;
00039
00040 ConfigFile::ConfigFile( const QString &filename ) : PropertyList()
00041 {
00042 setFilename( filename );
00043
00044
00045 }
00046
00047 ConfigFile::~ConfigFile()
00048 {
00049
00050 saveToXML();
00051 }
00052
00053 bool
00054 ConfigFile::saveToText( std::ostream &os) const
00055 {
00056 NOT_DONE("saveToText() should be better about wrapping long lines... what it does is unsafe!");
00057 QString ts;
00058 QRegExp trailingNewline("\\n$");
00059 QRegExp newline("\\n");
00060 QRegExp tab("\\t");
00061 for(QValueList<QString>::ConstIterator it = order.begin(); it != order.end(); ++it)
00062 {
00063 Entry *e = data.find(*it);
00064
00065 if(!e->cmnt.isEmpty())
00066 {
00067 ts = e->cmnt;
00068 ts.replace(trailingNewline, "");
00069 ts.replace(newline, "\n# ");
00070 os << "# " << ts << endl;
00071 }
00072 ts = e->val;
00073
00074
00075 ts.replace(newline, "\\n\\\n");
00076
00077 ts.replace(tab, "\\t");
00078
00079 os << *it << " = " << ts << endl;
00080 }
00081 return true;
00082 }
00083
00084 bool
00085 ConfigFile::loadFromText( std::istream &is)
00086 {
00087
00088
00089 data.clear();
00090 order.clear();
00091 setNeedsSave( false );
00092
00093 char line[1000];
00094
00095 QRegExp continuedLine("\\\\$");
00096 QRegExp trailingSlash("\\\\$");
00097 QRegExp noNonSpace("^\\s*$");
00098 QRegExp leadingComment("^# ? ?");
00099 QRegExp nonFirstLineComment("\\n# ? ?");
00100 QRegExp slashT("\\\\t");
00101 QRegExp slashN("\\\\n");
00102 QString buf;
00103 QString cbuf;
00104 QString key, val;
00105 int len;
00106 int lno = 0;
00107 bool inval = false;
00108 while(++lno)
00109 {
00110 if(!is.getline(line, sizeof(line)).good()) break;
00111
00112 if(line[0] == '#')
00113 {
00114 if(buf.isEmpty())
00115 {
00116 cbuf += line;
00117 cbuf += "\n";
00118 }
00119
00120
00121 continue;
00122 }
00123 len = strlen(line);
00124 buf += line;
00125
00126 if(buf.contains(continuedLine))
00127 {
00128 buf.replace(trailingSlash, "");
00129
00130 continue;
00131 }
00132 if(buf.isEmpty() || buf.contains(noNonSpace))
00133 {
00134 buf = cbuf = "";
00135 continue;
00136 }
00137
00138
00139
00140 int epos = buf.find("=");
00141 if(epos == -1)
00142 {
00143 NOT_DONE("loadFromText doesn't handle missing \"=\" in entry ending on line " << dec << lno);
00144 return false;
00145 }
00146 key = buf.left(epos).stripWhiteSpace();
00147 val = buf.right(buf.length() - epos - 1).stripWhiteSpace();
00148
00149 if(key.isEmpty())
00150 {
00151 NOT_DONE("loadFromText doesn't handle null key in entry ending on line " << dec << lno);
00152 return false;
00153 }
00154 val.replace(slashT, "\t");
00155 val.replace(slashN, "\n");
00156
00157 set(key, val);
00158 if(!cbuf.isEmpty())
00159 {
00160 cbuf.replace(leadingComment, "");
00161 cbuf.replace(nonFirstLineComment, "\n");
00162 setComment(key, cbuf);
00163 }
00164 buf = cbuf = "";
00165 }
00166
00167 return true;
00168 }
00169
00170
00171
00172
00173 bool
00174 ConfigFile::loadFromXML(const QString &fn )
00175 {
00176 if( !fn.isEmpty() ) setFilename( fn );
00177 SerialTree *tree = SerialTree::loadFromXMLFile(filename);
00178 if(tree == NULL)
00179 {
00180
00181 return false;
00182 }
00183 ConfigFile *cf = 0;
00184 cf = dynamic_cast<ConfigFile *>( tree->getSerializable("configfile") );
00185 if ( ! cf )
00186 {
00187
00188 return false;
00189 }
00190
00191 mergeIn( cf );
00192 delete( cf );
00193
00194 return true;
00195 }
00196
00197 void ConfigFile::deserialize(const Deserializer &ser)
00198 {
00199 PropertyList::deserialize(ser);
00200 }
00201
00202 bool
00203 ConfigFile::saveToXML(const QString &fn) const
00204 {
00205 if( ! fn.isEmpty() ) this->filename = fn;
00206 if( filename.isEmpty() ) return false;
00207
00208 SerialTree tree;
00209 tree.putSerializable( "configfile", *this );
00210 return tree.saveToXMLFile( filename );
00211 }
00212
00213 void ConfigFile::serialize(Serializer &ser) const
00214 {
00215 PropertyList::serialize(ser);
00216 ser.setSerializableClass("ConfigFile");
00217 }
00218
00219
00220 void
00221 ConfigFile::setFilename( const QString &fn )
00222 {
00223
00224 this->filename = fn;
00225 }
00226
00227 QString
00228 ConfigFile::getFilename()
00229 {
00230 return this->filename;
00231 }
00232
00233
00234 ConfigFile &
00235 ConfigFile::funConfig()
00236 {
00237 if( funconfig.getFilename().isEmpty() )
00238 {
00239
00240 funconfig.loadFromXML( QDir::homeDirPath() + QDir::separator() + ".libfun.conf" );
00241 }
00242 return funconfig;
00243 }
00244
00245 bool
00246 ConfigFile::save()
00247 {
00248 return this->saveToXML();
00249 }
00250
00251 bool
00252 ConfigFile::load()
00253 {
00254 return this->loadFromXML();
00255 }
00256
00257 };