You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
2548 lines
74 KiB
2548 lines
74 KiB
/* the Configuration Database library, Version II
|
|
|
|
the TDE addressbook
|
|
|
|
$ Author: Mirko Boehm $
|
|
$ Copyright: (C) 1996-2001, Mirko Boehm $
|
|
$ Contact: mirko@kde.org
|
|
http://www.kde.org $
|
|
$ License: GPL with the following explicit clarification:
|
|
This code may be linked against any version of the Qt toolkit
|
|
from Troll Tech, Norway. $
|
|
|
|
$Id$
|
|
*/
|
|
|
|
#include "qconfigDB.h"
|
|
// #include "debug.h"
|
|
|
|
extern "C" {
|
|
#include <sys/types.h>
|
|
#include <sys/stat.h>
|
|
#include <signal.h>
|
|
#include <unistd.h>
|
|
#include <ctype.h>
|
|
}
|
|
|
|
// #include <tqstring.h>
|
|
#include <tqtextstream.h>
|
|
#include <tqfile.h>
|
|
#include <tqtimer.h>
|
|
#include <tqdatetime.h>
|
|
#include <tqfileinfo.h>
|
|
|
|
#include "qconfigDB.moc"
|
|
#include <kdebug.h>
|
|
|
|
#ifdef KAB_KDEBUG_AREA
|
|
#undef KAB_KDEBUG_AREA
|
|
#endif
|
|
|
|
#define KAB_KDEBUG_AREA 800
|
|
|
|
static bool isComment(TQCString line)
|
|
{
|
|
// ############################################################################
|
|
line=line.stripWhiteSpace();
|
|
if(line.isEmpty())
|
|
{
|
|
return false; // line is empty but not a comment
|
|
} else {
|
|
return(line[0]=='#');
|
|
}
|
|
// ############################################################################
|
|
}
|
|
|
|
static void tokenize(list<TQCString>& res, const TQCString& text, char tr, bool strict=false)
|
|
{
|
|
register bool GUARD; GUARD=false;
|
|
// ############################################################################
|
|
kdDebug(GUARD, KAB_KDEBUG_AREA) << "tokenize: called." << endl;
|
|
int eins=0, zwei=0;
|
|
TQCString teil;
|
|
// -----
|
|
kdDebug(GUARD, KAB_KDEBUG_AREA) << "tokenize: partening -->%" << text.data() << "<--." << endl;
|
|
res.erase(res.begin(), res.end());
|
|
// -----
|
|
if(text.isEmpty())
|
|
{
|
|
kdDebug(GUARD, KAB_KDEBUG_AREA) <<
|
|
"tokenize: text is an empty string, done." << endl;
|
|
return;
|
|
}
|
|
while(zwei!=-1)
|
|
{
|
|
teil="";
|
|
zwei=text.find(tr, eins);
|
|
if(zwei!=-1)
|
|
{
|
|
teil=text.mid(eins, zwei-eins);
|
|
res.push_back(teil);
|
|
} else { // last element
|
|
if(!strict) // nur wenn dazwischen Zeichen sind
|
|
{
|
|
teil=text.mid(eins, text.length()-eins);
|
|
res.push_back(teil);
|
|
}
|
|
}
|
|
eins=zwei+1;
|
|
// if((unsigned)eins>=text.length()) break;
|
|
}
|
|
kdDebug(GUARD, KAB_KDEBUG_AREA) << "tokenize: partened in "
|
|
<< res.size() << " parts.\n";
|
|
// -----
|
|
kdDebug(GUARD, KAB_KDEBUG_AREA) << "tokenize: done." << endl;
|
|
// ############################################################################
|
|
}
|
|
|
|
// TQCString AuthorEmailAddress; // assign your email address to this string
|
|
|
|
static TQCString ReadLineFromStream(TQTextStream& stream)
|
|
{
|
|
register bool GUARD; GUARD=false;
|
|
// ############################################################################
|
|
kdDebug(GUARD, KAB_KDEBUG_AREA) << "ReadLineFromStream:: reading line." << endl;
|
|
TQCString line;
|
|
// -----
|
|
while(!stream.eof())
|
|
{
|
|
line=stream.readLine().ascii();
|
|
if(!line.isEmpty())
|
|
{
|
|
if(isComment(line))
|
|
{
|
|
line="";
|
|
continue;
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
// -----
|
|
kdDebug(GUARD, KAB_KDEBUG_AREA) << "ReadLineFromStream:: line \"" << line.data() << "\" read.\n";
|
|
return line;
|
|
// ############################################################################
|
|
}
|
|
|
|
// class implementations:
|
|
|
|
list<TQString> QConfigDB::LockFiles; // the lockfiles created by this session
|
|
|
|
KeyValueMap::KeyValueMap()
|
|
: data(new StringStringMap)
|
|
{
|
|
// ###########################################################################
|
|
// ###########################################################################
|
|
}
|
|
|
|
KeyValueMap::KeyValueMap(const KeyValueMap& orig)
|
|
: data(new StringStringMap(*orig.data))
|
|
{
|
|
// ###########################################################################
|
|
// ###########################################################################
|
|
}
|
|
|
|
KeyValueMap::~KeyValueMap()
|
|
{
|
|
// ###########################################################################
|
|
delete data;
|
|
// ###########################################################################
|
|
}
|
|
|
|
bool KeyValueMap::invariant()
|
|
{
|
|
return true;
|
|
}
|
|
|
|
StringStringMap::iterator KeyValueMap::begin()
|
|
{
|
|
return data->begin();
|
|
}
|
|
|
|
StringStringMap::iterator KeyValueMap::end()
|
|
{
|
|
return data->end();
|
|
}
|
|
|
|
unsigned int
|
|
KeyValueMap::size() const
|
|
{
|
|
// ###########################################################################
|
|
return data->size();
|
|
// ###########################################################################
|
|
}
|
|
|
|
void
|
|
KeyValueMap::clear()
|
|
{
|
|
register bool GUARD; GUARD=false;
|
|
// ###########################################################################
|
|
kdDebug(GUARD, KAB_KDEBUG_AREA) <<
|
|
"KeyValueMap::clear: erasing map contents ... " << endl;
|
|
// -----
|
|
if(!data->empty()) // erase fails on empty containers!
|
|
{
|
|
data->erase(data->begin(), data->end());
|
|
}
|
|
// -----
|
|
kdDebug(GUARD, KAB_KDEBUG_AREA) << "done." << endl;
|
|
// ###########################################################################
|
|
}
|
|
|
|
bool
|
|
KeyValueMap::fill(const TQString& filename, bool force, bool relax)
|
|
{
|
|
register bool GUARD; GUARD=false;
|
|
// ###########################################################################
|
|
TQFile file(filename);
|
|
TQCString line;
|
|
// -----
|
|
if(file.open(IO_ReadOnly))
|
|
{
|
|
TQTextStream stream(&file);
|
|
// We read/write utf8 strings, so we don't want that TQTextStream uses local8bit
|
|
// Latin1 means : no conversion, when giving char*s to a TQTextStream. (DF)
|
|
stream.setEncoding(TQTextStream::Latin1);
|
|
// -----
|
|
while(!stream.eof())
|
|
{
|
|
line=stream.readLine().ascii();
|
|
if(!line.isEmpty() /* && !stream.eof() */ && !isComment(line))
|
|
{
|
|
if(!insertLine(line, force, relax, false))
|
|
{
|
|
kdDebug(GUARD, KAB_KDEBUG_AREA) <<
|
|
"KeyValueMap::fill: could not insert line "
|
|
<< line << ".\n"; // ignore this case further
|
|
}
|
|
}
|
|
}
|
|
file.close();
|
|
// -----
|
|
return true;
|
|
} else {
|
|
kdDebug(GUARD, KAB_KDEBUG_AREA) <<
|
|
"KeyValueMap::fill: cannot open file " <<
|
|
filename << endl;
|
|
return false;
|
|
}
|
|
// ###########################################################################
|
|
}
|
|
|
|
bool
|
|
KeyValueMap::save(const TQString& filename, bool force)
|
|
{
|
|
register bool GUARD; GUARD=false;
|
|
// ###########################################################################
|
|
kdDebug(GUARD, KAB_KDEBUG_AREA) <<
|
|
"KeyValueMap::save: saving data to -->" <<
|
|
filename << "<--.\n";
|
|
StringStringMap::iterator pos;
|
|
TQFile file(filename);
|
|
// ----- open file, regarding existence:
|
|
if(!force)
|
|
{
|
|
if(file.exists())
|
|
{
|
|
kdDebug(GUARD, KAB_KDEBUG_AREA) <<
|
|
"KeyValueMap::save: file exists but may not." << endl;
|
|
return false;
|
|
}
|
|
}
|
|
if(file.open(IO_WriteOnly))
|
|
{
|
|
TQTextStream stream(&file);
|
|
stream.setEncoding(TQTextStream::Latin1); // no conversion
|
|
stream << "# saved by KeyValueMap object ($Revision$)" << endl;
|
|
for(pos=data->begin(); pos!=data->end(); ++pos)
|
|
{ // values do not get coded here
|
|
stream << (*pos).first << '=' << (*pos).second << endl;
|
|
}
|
|
file.close();
|
|
} else {
|
|
kdDebug(GUARD, KAB_KDEBUG_AREA) <<
|
|
"KeyValueMap::save: could not open file -->%s<-- for saving." <<
|
|
filename.utf8() << endl;
|
|
return false;
|
|
}
|
|
// ###########################################################################
|
|
return true;
|
|
}
|
|
|
|
bool
|
|
KeyValueMap::save(TQTextStream& file, int count)
|
|
{
|
|
register bool GUARD; GUARD=false;
|
|
// ###########################################################################
|
|
kdDebug(GUARD, KAB_KDEBUG_AREA) <<
|
|
"KeyValueMap::save: saving data to given output stream." << endl;
|
|
StringStringMap::iterator pos;
|
|
bool ret=true;
|
|
char* prefix=new char[count+1];
|
|
memset(prefix, ' ', count);
|
|
prefix[count]=0;
|
|
// -----
|
|
for(pos=data->begin(); pos!=data->end(); ++pos)
|
|
{
|
|
file << prefix << (*pos).first << '=' << (*pos).second << endl;
|
|
}
|
|
delete [] prefix;
|
|
// -----
|
|
return ret;
|
|
// ###########################################################################
|
|
}
|
|
|
|
|
|
bool
|
|
KeyValueMap::erase(const TQCString& key)
|
|
{
|
|
// ###########################################################################
|
|
bool rc=(data->erase(key)>0);
|
|
return rc;
|
|
// ###########################################################################
|
|
}
|
|
|
|
|
|
bool
|
|
KeyValueMap::empty()
|
|
{
|
|
// ###########################################################################
|
|
return data->empty();
|
|
// ###########################################################################
|
|
}
|
|
|
|
bool
|
|
KeyValueMap::parseComplexString
|
|
(const TQCString& orig,
|
|
int index, // first char to parse
|
|
TQCString& result, // string without leading and trailing ".."
|
|
int& noOfChars) // no of chars that represented the
|
|
const // complex string in the original
|
|
{
|
|
register bool GUARD; GUARD=false;
|
|
// ###########################################################################
|
|
int first;
|
|
TQCString temp(2*orig.length());
|
|
TQCString mod;
|
|
int count=1;
|
|
kdDebug(GUARD, KAB_KDEBUG_AREA) <<
|
|
"KeyValueMap::parseComplexString: parsing the string -->"
|
|
<< orig << "<--.\n";
|
|
// -----
|
|
if(orig.isEmpty())
|
|
{
|
|
kdDebug(GUARD, KAB_KDEBUG_AREA) <<
|
|
"KeyValueMap::parseComplexString: string is empty.\n"
|
|
" "
|
|
"This is no valid complex string." << endl;
|
|
return false;
|
|
}
|
|
// ----- prepare the string:
|
|
temp=orig.mid(index, orig.length()-index); // remove everything before index
|
|
mod=temp.stripWhiteSpace(); // remove leading and trailing white spaces
|
|
// ----- test some conditions:
|
|
if(mod.length()<2)
|
|
{
|
|
kdDebug() << "KeyValueMap::parseComplexString: no pair of brackets " << endl;
|
|
return false;
|
|
}
|
|
if(mod[0]!='"')
|
|
{
|
|
kdDebug() << "KeyValueMap::parseComplexString: no opening bracket." << endl;
|
|
return false;
|
|
}
|
|
// ----- now parse it:
|
|
first=1; // first character after opening bracket
|
|
temp="";
|
|
for(;;)
|
|
{
|
|
if(mod[first]=='\\')
|
|
{ // handle special characters
|
|
++first;
|
|
kdDebug(GUARD, KAB_KDEBUG_AREA).form("KeyValueMap::parseComplexString: found "
|
|
"a special character \"%c\".", mod[first]) << endl;
|
|
if((unsigned)first==mod.length())
|
|
{
|
|
kdDebug(GUARD, KAB_KDEBUG_AREA) <<
|
|
"KeyValueMap::parseComplexString: "
|
|
"string lacks the closing \".\n "
|
|
" This is no valid "
|
|
"complex string." << endl;
|
|
return false;
|
|
}
|
|
switch(mod[first])
|
|
{
|
|
case 't': temp+='\t'; break;
|
|
case 'n': temp+='\n'; break;
|
|
case '"': temp+='"'; break;
|
|
case 'e': temp+="\\e"; break;
|
|
case '\\': temp+='\\'; break;
|
|
default:
|
|
// WORK_TO_DO: implement octal coding here!
|
|
kdDebug(GUARD, KAB_KDEBUG_AREA) << "KeyValueMap::parseComplexString: "
|
|
"invalid control character.\n "
|
|
" This is no valid complex string." << endl;
|
|
return false;
|
|
}
|
|
count+=2; // this took 2 characters
|
|
++first;
|
|
} else { // it is a character
|
|
++count;
|
|
if(mod[first]=='"') // end of coded string?
|
|
{
|
|
break;
|
|
}
|
|
temp+=mod[first];
|
|
++first;
|
|
}
|
|
if((unsigned)first>=mod.length())
|
|
{
|
|
kdDebug(GUARD, KAB_KDEBUG_AREA) << "KeyValueMap::parseComplexString: "
|
|
"string lacks the closing \".\n "
|
|
" This is no valid complex string.\n";
|
|
return false;
|
|
}
|
|
}
|
|
// -----
|
|
kdDebug(GUARD, KAB_KDEBUG_AREA).form(
|
|
"KeyValueMap::parseComplexString: finished parsing, no errors, "
|
|
"%i characters, %i in string.", count, temp.length()) << endl;
|
|
noOfChars=count;
|
|
result=temp;
|
|
// ###########################################################################
|
|
return true;
|
|
}
|
|
|
|
TQCString
|
|
KeyValueMap::makeComplexString(const TQCString& orig)
|
|
{
|
|
register bool GUARD; GUARD=false;
|
|
// ###########################################################################
|
|
kdDebug(GUARD, KAB_KDEBUG_AREA) <<
|
|
"KeyValueMap::makeComplexString: coding the string\n -->"
|
|
<< orig <<
|
|
"<--\n into a complex string.\n";
|
|
TQCString temp(2*orig.length());
|
|
unsigned int count;
|
|
// -----
|
|
temp+='"'; // opening bracket
|
|
for(count=0; count<orig.length(); count++)
|
|
{
|
|
switch(orig[count])
|
|
{ // catch all special characters:
|
|
case '"':
|
|
kdDebug(GUARD, KAB_KDEBUG_AREA).form("KeyValueMap::makeComplexString: "
|
|
"found the special char \"%c\".", orig[count]) << endl;
|
|
temp+='\\';
|
|
temp+='"';
|
|
break;
|
|
case '\n':
|
|
kdDebug(GUARD, KAB_KDEBUG_AREA).form("KeyValueMap::makeComplexString: "
|
|
"found the special char \"%c\".", orig[count]) << endl;
|
|
temp+='\\';
|
|
temp+='n';
|
|
break;
|
|
case '\t':
|
|
kdDebug(GUARD, KAB_KDEBUG_AREA).form("KeyValueMap::makeComplexString: "
|
|
"found the special char \"%c\".", orig[count]) << endl;
|
|
temp+='\\';
|
|
temp+='t';
|
|
break;
|
|
case '\\':
|
|
kdDebug(GUARD, KAB_KDEBUG_AREA).form("KeyValueMap::makeComplexString: "
|
|
"found the special char \"%c\".", orig[count]) << endl;
|
|
temp+='\\';
|
|
temp+='\\';
|
|
break;
|
|
default: temp+=orig[count];
|
|
}
|
|
}
|
|
temp+='"'; // closing bracket
|
|
// -----
|
|
kdDebug(GUARD, KAB_KDEBUG_AREA) <<
|
|
"KeyValueMap::makeComplexString: result is\n -->"
|
|
<<temp<<"<--.\n";
|
|
return temp;
|
|
// ###########################################################################
|
|
}
|
|
|
|
bool
|
|
KeyValueMap::getRaw(const TQCString& key, TQCString& value) const
|
|
{
|
|
register bool GUARD; GUARD=false;
|
|
// ###########################################################################
|
|
kdDebug(GUARD, KAB_KDEBUG_AREA) <<
|
|
"KeyValueMap::getRaw: trying to get raw value for key \"" << key << "\" ...\n";
|
|
StringStringMap::iterator pos=data->find(key);
|
|
// -----
|
|
if(pos==data->end())
|
|
{
|
|
kdDebug(GUARD, KAB_KDEBUG_AREA) << "not in KeyValueMap." << endl;
|
|
return false;
|
|
} else {
|
|
value=(*pos).second;
|
|
kdDebug(GUARD, KAB_KDEBUG_AREA) << "in KeyValueMap, value is "
|
|
<< value << endl;
|
|
return true;
|
|
}
|
|
// ###########################################################################
|
|
}
|
|
|
|
bool
|
|
KeyValueMap::insertRaw(const TQCString& key, const TQCString& value, bool force)
|
|
{
|
|
register bool GUARD; GUARD=false;
|
|
// ###########################################################################
|
|
kdDebug(GUARD, KAB_KDEBUG_AREA) <<
|
|
"KeyValueMap::insertRaw: inserting uncoded value "
|
|
<< value <<
|
|
" for key " << key << endl;
|
|
int n=0;
|
|
// -----
|
|
if(key.isEmpty()) // empty KEYS are errors:
|
|
{
|
|
kdDebug() << "KeyValueMap::insertRaw: tried to insert empty key." << endl;
|
|
return false;
|
|
}
|
|
if(force) // entry will be replaced
|
|
{
|
|
n=data->erase(key);
|
|
}
|
|
if(data->insert(StringStringMap::value_type(key, value)).second)
|
|
{
|
|
kdDebug(GUARD, KAB_KDEBUG_AREA) << "KeyValueMap::insertRaw: success"
|
|
<< (n==0 ? "" : " (forced)") << endl;
|
|
return true;
|
|
} else {
|
|
kdDebug(GUARD, KAB_KDEBUG_AREA) << "KeyValueMap::insertRaw: failed, "
|
|
"key already in KeyValueMap." << endl;
|
|
return false;
|
|
}
|
|
// ###########################################################################
|
|
}
|
|
|
|
|
|
// -----------------------------------------------------------------------------
|
|
// HUGE SEPARATOR BETWEEN INTERNAL LOGIC AND EXTENDABLE PAIRS OF GET- AND INSERT
|
|
// -METHODS.
|
|
// EXTENDABLE MEANS: OTHER DATATYPES CAN BE ADDED HERE.
|
|
// -----------------------------------------------------------------------------
|
|
|
|
/* The following functions are the pairs of insert-get-methods for different
|
|
* data types. See keyvaluemap.h for the declarations. */
|
|
|
|
// ascii strings:
|
|
|
|
bool
|
|
KeyValueMap::insert(const TQCString& key, const TQCString& value, bool force)
|
|
{
|
|
register bool GUARD; GUARD=false;
|
|
// ###########################################################################
|
|
kdDebug(GUARD, KAB_KDEBUG_AREA) <<
|
|
"KeyValueMap::insert: inserting value\n -->"
|
|
<< value <<
|
|
"<-- \""
|
|
" for key\n -->"
|
|
<< key <<
|
|
"<--.\n";
|
|
return insertRaw(key, makeComplexString(value), force);
|
|
// ###########################################################################
|
|
}
|
|
|
|
/* Attention:
|
|
* This is another insert function that partens lines like "key=value"!
|
|
* It is used for reading files and command line parameters easily.
|
|
*/
|
|
|
|
bool
|
|
KeyValueMap::insertLine(TQCString line, bool force, bool relax, bool encode)
|
|
{
|
|
register bool GUARD; GUARD=false;
|
|
// ###########################################################################
|
|
kdDebug(GUARD, KAB_KDEBUG_AREA) <<
|
|
"KeyValueMap::insertLine: inserting line -->"<<line<<"<--.\n";
|
|
int index;
|
|
TQCString key;
|
|
TQCString value;
|
|
// ----- is the line empty or does it contain only whitespaces?
|
|
uint len = line.length();
|
|
for(index=0; isspace(line[index]) && (unsigned)index<len; ++index);
|
|
if(line.isEmpty() || (unsigned)index==len)
|
|
{
|
|
kdDebug(GUARD, KAB_KDEBUG_AREA) <<
|
|
"KeyValueMap::insertLine: line is empty." << endl;
|
|
return false;
|
|
}
|
|
// -----
|
|
index=line.find('=');
|
|
if(index==-1) // not found
|
|
{
|
|
kdDebug() << "KeyValueMap::insertLine: no \"=\" found in \""<<line<<"\".\n";
|
|
return false;
|
|
}
|
|
// -----
|
|
key=line.mid(0, index); // copy from start to '='
|
|
value=line.mid(index+1, line.length()-1-index); // copy the rest
|
|
// ----- only alphanumerical characters are allowed in the keys:
|
|
for(index=key.length()-1; index>-1; /* nothing */)
|
|
{
|
|
if(!(isalnum(key[index]) || ispunct(key[index])))
|
|
{
|
|
key=key.remove(index, 1); // WORK_TO_DO: optimize this (very slow)!
|
|
}
|
|
--index;
|
|
}
|
|
// ----- now insert it if key is still valid:
|
|
if(!key.isEmpty() && (relax==true ? 1 : !value.isEmpty() ) )
|
|
{
|
|
kdDebug(GUARD, KAB_KDEBUG_AREA) << "KeyValueMap::insertLine: done." << endl;
|
|
if(encode)
|
|
{ // the usual way:
|
|
return insert(key, value, force);
|
|
} else { // while loading from a already coded file:
|
|
return insertRaw(key, value, force);
|
|
}
|
|
} else {
|
|
kdDebug() << "KeyValueMap::insertLine: key " << (relax ? "" : "or value ") << " is empty." << endl;
|
|
return false;
|
|
}
|
|
// ###########################################################################
|
|
}
|
|
|
|
bool
|
|
KeyValueMap::get(const TQCString& key, TQCString& value) const
|
|
{
|
|
register bool GUARD; GUARD=false;
|
|
// ###########################################################################
|
|
kdDebug(GUARD, KAB_KDEBUG_AREA) << "KeyValueMap::get[string]: "
|
|
"trying to get value for key \"" << key << "\" ... " << endl;
|
|
TQCString raw;
|
|
TQCString temp;
|
|
// -----
|
|
if(!getRaw(key, raw))
|
|
{
|
|
return false; // key does not exist
|
|
} else {
|
|
kdDebug(GUARD, KAB_KDEBUG_AREA) << "KeyValueMap::get[string]: checking "
|
|
"wether this is a complex string." << endl;
|
|
{
|
|
int count;
|
|
if(parseComplexString(raw, 0, temp, count))
|
|
{
|
|
kdDebug(GUARD, KAB_KDEBUG_AREA) <<
|
|
"KeyValueMap::get[string]: complex string found." << endl;
|
|
value=temp;
|
|
} else {
|
|
kdDebug(GUARD, KAB_KDEBUG_AREA) <<
|
|
"KeyValueMap::get[string]: this is no complex string." << endl;
|
|
// disabled this strong check:
|
|
// CHECK(false); // kill debug version
|
|
return false;
|
|
}
|
|
}
|
|
// ^^^^^^
|
|
return true;
|
|
}
|
|
// ###########################################################################
|
|
}
|
|
|
|
// (^^^ ascii strings)
|
|
// UNICODE strings:
|
|
|
|
bool
|
|
KeyValueMap::insert(const TQCString& key, const TQString& value, bool force)
|
|
{
|
|
register bool GUARD; GUARD=false;
|
|
// ###########################################################################
|
|
TQCString v;
|
|
// -----
|
|
v=value.utf8();
|
|
kdDebug(GUARD, KAB_KDEBUG_AREA) << "KeyValueMap::insert[QString]: trying to "
|
|
"insert \"" << (!value.isNull() ? "true" : "false")
|
|
<< "\" for key\n -->"
|
|
<< v
|
|
<< "<--.\n";
|
|
return insert(key, v, force);
|
|
// ###########################################################################
|
|
}
|
|
|
|
bool
|
|
KeyValueMap::get(const TQCString& key, TQString& value) const
|
|
{
|
|
register bool GUARD; GUARD=false;
|
|
// ###########################################################################
|
|
kdDebug(GUARD, KAB_KDEBUG_AREA) << "KeyValueMap::get[QString]: trying to get "
|
|
"a TQString value for key " << key << endl;
|
|
TQCString v;
|
|
// ----- get string representation:
|
|
if(!get(key, v))
|
|
{
|
|
kdDebug(GUARD, KAB_KDEBUG_AREA) << "KeyValueMap::get[QString]: key "
|
|
<< key << " not in KeyValueMap.\n";
|
|
return false;
|
|
}
|
|
// ----- find its state:
|
|
value=TQString::fromUtf8(v); // is there a better way?
|
|
kdDebug(GUARD, KAB_KDEBUG_AREA) << "KeyValueMap::get[QString]: success, value"
|
|
" (in UTF8) is " << v << endl;
|
|
return true;
|
|
// ###########################################################################
|
|
}
|
|
|
|
// (^^^ UNICODE strings)
|
|
// bool:
|
|
|
|
bool
|
|
KeyValueMap::insert(const TQCString& key, const bool& value, bool force)
|
|
{
|
|
register bool GUARD; GUARD=false;
|
|
// ###########################################################################
|
|
kdDebug(GUARD, KAB_KDEBUG_AREA) << "KeyValueMap::insert[bool]: trying to "
|
|
"insert \""
|
|
<< (value==true ? "true" : "false")
|
|
<<"\" for key\n -->"
|
|
<< key << "<--.\n";
|
|
return insert(key, value==true ? "true" : "false", force);
|
|
// ###########################################################################
|
|
}
|
|
|
|
|
|
bool
|
|
KeyValueMap::get(const TQCString& key, bool& value) const
|
|
{
|
|
register bool GUARD; GUARD=false;
|
|
// ###########################################################################
|
|
kdDebug(GUARD, KAB_KDEBUG_AREA) << "KeyValueMap::get[bool]: trying to get "
|
|
"BOOL value for key " << key << endl;
|
|
TQCString v;
|
|
// ----- get string representation:
|
|
if(!get(key, v))
|
|
{
|
|
kdDebug(GUARD, KAB_KDEBUG_AREA) << "KeyValueMap::get[bool]: key "
|
|
<< key << " not in KeyValueMap.";
|
|
return false;
|
|
}
|
|
// ----- find its state:
|
|
v=v.stripWhiteSpace();
|
|
if(v=="true")
|
|
{
|
|
kdDebug(GUARD, KAB_KDEBUG_AREA) << "KeyValueMap::get[bool]: success, "
|
|
"value is true." << endl;
|
|
value=true;
|
|
return true;
|
|
}
|
|
if(v=="false")
|
|
{
|
|
kdDebug(GUARD, KAB_KDEBUG_AREA) << "KeyValueMap::get[bool]: success, "
|
|
"value is false." << endl;
|
|
value=false;
|
|
return true;
|
|
}
|
|
kdDebug(GUARD, KAB_KDEBUG_AREA) <<
|
|
"KeyValueMap::get[bool]: failure, unknown value." << endl;
|
|
// -----
|
|
return false;
|
|
// ###########################################################################
|
|
}
|
|
|
|
// (^^^ bool)
|
|
// long:
|
|
|
|
bool
|
|
KeyValueMap::insert(const TQCString& key, const long& value, bool force)
|
|
{
|
|
register bool GUARD; GUARD=false;
|
|
// ###########################################################################
|
|
kdDebug(GUARD, KAB_KDEBUG_AREA) << "KeyValueMap::insert[int]: trying to "
|
|
"insert value \""<<value << "\" for key\n -->"<<key<<"<--.\n";
|
|
TQCString temp;
|
|
// -----
|
|
temp.setNum(value);
|
|
return insert(key, temp, force);
|
|
// ###########################################################################
|
|
}
|
|
|
|
bool
|
|
KeyValueMap::get(const TQCString& key, long& value) const
|
|
{
|
|
register bool GUARD; GUARD=false;
|
|
// ###########################################################################
|
|
kdDebug(GUARD, KAB_KDEBUG_AREA) << "KeyValueMap::get[int]: trying to get "
|
|
"INTEGER value for key " << key << endl;
|
|
TQCString v;
|
|
bool ok;
|
|
long temp;
|
|
// -----
|
|
if(!get(key, v))
|
|
{
|
|
kdDebug(GUARD, KAB_KDEBUG_AREA) << "KeyValueMap::get[int]: key "
|
|
<< key <<" not in KeyValueMap.\n";
|
|
return false;
|
|
}
|
|
// -----
|
|
temp=v.toLong(&ok);
|
|
if(ok)
|
|
{
|
|
value=temp;
|
|
return true;
|
|
} else {
|
|
return false;
|
|
}
|
|
// ###########################################################################
|
|
}
|
|
|
|
// (^^^ long)
|
|
// long int lists:
|
|
|
|
bool
|
|
KeyValueMap::insert(const TQCString& key, const list<long>& values, bool force)
|
|
{
|
|
register bool GUARD; GUARD=false;
|
|
// ###########################################################################
|
|
kdDebug(GUARD, KAB_KDEBUG_AREA) << "KeyValueMap::insert[long int list]: "
|
|
"trying to insert long int list into map." << endl;
|
|
TQCString temp;
|
|
TQCString value;
|
|
list<long>::const_iterator pos;
|
|
// -----
|
|
for(pos=values.begin(); pos!=values.end(); ++pos)
|
|
{
|
|
temp.setNum(*pos);
|
|
value=value+temp+", ";
|
|
}
|
|
if(!value.isEmpty())
|
|
{ // remove last comma and space:
|
|
value.remove(value.length()-2, 2);
|
|
}
|
|
// -----
|
|
kdDebug(GUARD, KAB_KDEBUG_AREA) << "KeyValueMap::insert[long int list]: "
|
|
"constructed string value is " << value << endl;
|
|
return insert(key, value, force);
|
|
// ###########################################################################
|
|
}
|
|
|
|
bool
|
|
KeyValueMap::get(const TQCString& key, list<long>& values) const
|
|
{
|
|
register bool GUARD; GUARD=false;
|
|
// ###########################################################################
|
|
kdDebug(GUARD, KAB_KDEBUG_AREA) << "KeyValueMap::get[long int list]: trying "
|
|
"to decode int list for key " << key << endl;
|
|
kdDebug(!values.empty(), KAB_KDEBUG_AREA) << "KeyValueMap::get[long int list]"
|
|
": attention - list should be empty but is not.\n";
|
|
TQCString value;
|
|
list<TQCString> tokens;
|
|
list<TQCString>::iterator pos;
|
|
long temp;
|
|
bool ok;
|
|
// -----
|
|
if(!get(key, value))
|
|
{
|
|
kdDebug(GUARD, KAB_KDEBUG_AREA) <<
|
|
"KeyValueMap::get[long int list]: no such key." << endl;
|
|
return false;
|
|
}
|
|
tokenize(tokens, value, ',');
|
|
if(tokens.empty())
|
|
{
|
|
kdDebug(GUARD, KAB_KDEBUG_AREA) <<
|
|
"KeyValueMap::get[long int list]: no tokens." << endl;
|
|
return false;
|
|
}
|
|
// -----
|
|
for(pos=tokens.begin(); pos!=tokens.end(); ++pos)
|
|
{
|
|
temp=(*pos).toLong(&ok);
|
|
if(ok)
|
|
{
|
|
values.push_back(temp);
|
|
} else {
|
|
kdDebug() << "KeyValueMap::get[long int list]: conversion error for " << endl;
|
|
}
|
|
}
|
|
// -----
|
|
kdDebug(GUARD, KAB_KDEBUG_AREA) << "KeyValueMap::get[long int list]: done." << endl;
|
|
// ###########################################################################
|
|
return true;
|
|
}
|
|
|
|
// (^^^ long int lists)
|
|
// int lists:
|
|
|
|
bool
|
|
KeyValueMap::insert(const TQCString& key, const list<int>& values, bool force)
|
|
{
|
|
register bool GUARD; GUARD=false;
|
|
// ###########################################################################
|
|
kdDebug(GUARD, KAB_KDEBUG_AREA) << "KeyValueMap::insert[int list]: trying to "
|
|
"insert int list into map." << endl;
|
|
TQCString temp;
|
|
TQCString value;
|
|
list<int>::const_iterator pos;
|
|
// -----
|
|
for(pos=values.begin(); pos!=values.end(); ++pos)
|
|
{
|
|
temp.setNum(*pos);
|
|
value=value+temp+", ";
|
|
}
|
|
if(!value.isEmpty())
|
|
{ // remove last comma and space:
|
|
value.remove(value.length()-2, 2);
|
|
}
|
|
// -----
|
|
kdDebug(GUARD, KAB_KDEBUG_AREA) << "KeyValueMap::insert[int list]: "
|
|
"constructed string value is " << value << endl;
|
|
return insert(key, value, force);
|
|
// ###########################################################################
|
|
}
|
|
|
|
bool
|
|
KeyValueMap::get(const TQCString& key, list<int>& values) const
|
|
{
|
|
register bool GUARD; GUARD=false;
|
|
// ###########################################################################
|
|
kdDebug(GUARD, KAB_KDEBUG_AREA) << "KeyValueMap::get[int list]: trying to "
|
|
"decode int list for key " << key << endl;
|
|
kdDebug(!values.empty(), KAB_KDEBUG_AREA) << "KeyValueMap::get[int list]: "
|
|
"attention - list should be empty but is not.\n";
|
|
TQCString value;
|
|
list<TQCString> tokens;
|
|
list<TQCString>::iterator pos;
|
|
int temp;
|
|
bool ok;
|
|
// -----
|
|
if(!get(key, value))
|
|
{
|
|
kdDebug(GUARD, KAB_KDEBUG_AREA) <<
|
|
"KeyValueMap::get[int list]: no such key." << endl;
|
|
return false;
|
|
}
|
|
tokenize(tokens, value, ',');
|
|
if(tokens.empty())
|
|
{
|
|
kdDebug(GUARD, KAB_KDEBUG_AREA) <<
|
|
"KeyValueMap::get[int list]: no tokens." << endl;
|
|
return false;
|
|
}
|
|
// -----
|
|
for(pos=tokens.begin(); pos!=tokens.end(); ++pos)
|
|
{
|
|
temp=(*pos).toInt(&ok);
|
|
if(ok)
|
|
{
|
|
values.push_back(temp);
|
|
} else {
|
|
kdDebug() << "KeyValueMap::get[int list]: conversion error for " << *pos << endl;
|
|
}
|
|
}
|
|
// -----
|
|
kdDebug(GUARD, KAB_KDEBUG_AREA) << "KeyValueMap::get[long int list]: done." << endl;
|
|
// ###########################################################################
|
|
return true;
|
|
}
|
|
|
|
// (^^^ int lists)
|
|
// doubles:
|
|
|
|
bool
|
|
KeyValueMap::insert(const TQCString& key, const double& value, bool force)
|
|
{
|
|
register bool GUARD; GUARD=false;
|
|
// ###########################################################################
|
|
kdDebug(GUARD, KAB_KDEBUG_AREA).form("KeyValueMap::insert[double]: trying to "
|
|
"insert value \"%f\" for key\n -->", value) << key << "<--.\n";
|
|
TQCString temp;
|
|
// -----
|
|
temp.setNum(value);
|
|
return insert(key, temp, force);
|
|
// ###########################################################################
|
|
}
|
|
|
|
bool
|
|
KeyValueMap::get(const TQCString& key, double& value) const
|
|
{
|
|
register bool GUARD; GUARD=false;
|
|
// ###########################################################################
|
|
kdDebug(GUARD, KAB_KDEBUG_AREA) << "KeyValueMap::get[double]: trying to get "
|
|
"FLOAT value for key " << key << endl;
|
|
TQCString v;
|
|
bool ok;
|
|
double temp;
|
|
// -----
|
|
if(!get(key, v))
|
|
{
|
|
kdDebug(GUARD, KAB_KDEBUG_AREA) << "KeyValueMap::get[int]: key "
|
|
<<key<<" not in "
|
|
"KeyValueMap." << endl;
|
|
return false;
|
|
}
|
|
// -----
|
|
temp=v.toDouble(&ok);
|
|
if(ok)
|
|
{
|
|
value=temp;
|
|
return true;
|
|
} else {
|
|
return false;
|
|
}
|
|
// ###########################################################################
|
|
}
|
|
|
|
// (^^^ doubles)
|
|
// lists of strings:
|
|
|
|
bool
|
|
KeyValueMap::get(const TQCString& key, list<TQCString>& values) const
|
|
{
|
|
register bool GUARD; GUARD=false;
|
|
kdDebug(!values.empty(), KAB_KDEBUG_AREA) << "KeyValueMap::get[string list]: "
|
|
"attention!\n \"values\" list reference is not "
|
|
"empty!" << endl;
|
|
// ###########################################################################
|
|
kdDebug(GUARD, KAB_KDEBUG_AREA) << "KeyValueMap::get[string list]: trying to "
|
|
"decode string list for key " << key << endl;
|
|
TQCString raw, part, value;
|
|
int first=1, second=1, i;
|
|
// ----- get the string value as a whole:
|
|
if(!getRaw(key, raw))
|
|
{
|
|
kdDebug(GUARD, KAB_KDEBUG_AREA) << "KeyValueMap::get[list<string>]: key "
|
|
<< key << " not in KeyValueMap." << endl;
|
|
return false;
|
|
}
|
|
// -----
|
|
for(;;)
|
|
{ // ----- parten the string down into a list, find special characters:
|
|
second=first;
|
|
for(;;)
|
|
{
|
|
second=raw.find('\\', second);
|
|
// ----- this may never be the last and also not the second last
|
|
// character in a complex string:
|
|
if(second!=-1)
|
|
{ // ----- check for string end:
|
|
// we use "\e" as token for the string-delimiter
|
|
if(raw[second+1]=='e' // the right character
|
|
&& raw[second-1]!='\\') // not escaped
|
|
{
|
|
kdDebug(GUARD, KAB_KDEBUG_AREA) << "KeyValueMap::get"
|
|
"[list<string>]: found string end at pos " <<
|
|
second << endl;
|
|
break;
|
|
} else {
|
|
++second;
|
|
}
|
|
} else {
|
|
break;
|
|
}
|
|
}
|
|
if(second!=-1)
|
|
{
|
|
// ----- now second points to the end of the substring:
|
|
part="\""+raw.mid(first, second-first)+"\"";
|
|
// ----- insert decoded value into the list:
|
|
if(parseComplexString(part, 0, value, i))
|
|
{
|
|
kdDebug(GUARD, KAB_KDEBUG_AREA) << "KeyValueMap::get"
|
|
"[list<string>]: found item " << value << endl;
|
|
values.push_back(value);
|
|
} else {
|
|
kdDebug() << "KeyValueMap::get[list<string>]: parse error." << endl;
|
|
return false;
|
|
}
|
|
if((unsigned)second<raw.length()-3)
|
|
{ // ----- there may be another string
|
|
first=second+2;
|
|
} else { // ----- we are completely finished
|
|
kdDebug(GUARD, KAB_KDEBUG_AREA) <<
|
|
"KeyValueMap::get[list<string>]: list end found." << endl;
|
|
break;
|
|
}
|
|
} else { // ----- finished:
|
|
break;
|
|
}
|
|
}
|
|
// -----
|
|
kdDebug(GUARD, KAB_KDEBUG_AREA) << "KeyValueMap::get[list<string>]: done." << endl;
|
|
return true;
|
|
// ###########################################################################
|
|
}
|
|
|
|
bool
|
|
KeyValueMap::insert(const TQCString& key, const list<TQCString>& values, bool force)
|
|
{
|
|
register bool GUARD; GUARD=false;
|
|
// ###########################################################################
|
|
kdDebug(GUARD, KAB_KDEBUG_AREA) << "KeyValueMap::insert[string list]: "
|
|
"coding string list." << endl;
|
|
TQCString value="\"";
|
|
TQCString temp;
|
|
list<TQCString>::const_iterator pos;
|
|
// ----- create coded string list:
|
|
for(pos=values.begin();
|
|
pos!=values.end();
|
|
pos++)
|
|
{ // create strings like "abc\efgh\eijk":
|
|
temp=makeComplexString(*pos);
|
|
temp.remove(0, 1); // remove the leading "\""
|
|
temp.remove(temp.length()-1, 1); // the trailing "\""
|
|
value+=temp;
|
|
value+="\\e";
|
|
}
|
|
value+="\""; // finish the string
|
|
kdDebug(GUARD, KAB_KDEBUG_AREA) << "KeyValueMap::insert[string list]: result "
|
|
"of coding is " << value << endl;
|
|
// ----- insert it without coding:
|
|
return insertRaw(key, value, force);
|
|
// ###########################################################################
|
|
}
|
|
|
|
// (^^^ lists of strings)
|
|
// QStrList-s:
|
|
|
|
bool
|
|
KeyValueMap::get(const TQCString& key, TQStrList& values) const
|
|
{
|
|
register bool GUARD; GUARD=false;
|
|
kdDebug(!values.isEmpty(), KAB_KDEBUG_AREA) << "KeyValueMap::get[QStrList]: "
|
|
"attention!\n \"values\" list reference is not "
|
|
"empty!" << endl;
|
|
// ###########################################################################
|
|
kdDebug(GUARD, KAB_KDEBUG_AREA) << "KeyValueMap::get[QStrList]: trying to "
|
|
"decode string list for key " << key << endl;
|
|
TQCString raw, part, value;
|
|
int first=1, second=1, i;
|
|
// ----- get the string value as a whole:
|
|
if(!getRaw(key, raw))
|
|
{
|
|
kdDebug(GUARD, KAB_KDEBUG_AREA) << "KeyValueMap::get[QStrList]: key "
|
|
<< key <<" not in KeyValueMap." << endl;
|
|
return false;
|
|
}
|
|
// -----
|
|
for(;;)
|
|
{ // ----- parten the string down into a list, find special characters:
|
|
second=first;
|
|
for(;;)
|
|
{
|
|
second=raw.find('\\', second);
|
|
// ----- this may never be the last and also not the second last
|
|
// character in a complex string:
|
|
if(second!=-1)
|
|
{ // ----- check for string end:
|
|
// we use "\e" as token for the string-delimiter
|
|
if(raw[second+1]=='e' // the right character
|
|
&& raw[second-1]!='\\') // not escaped
|
|
{
|
|
kdDebug(GUARD, KAB_KDEBUG_AREA) << "KeyValueMap::get[QStrList]:"
|
|
" found string end at pos %i." << second << endl;
|
|
break;
|
|
} else {
|
|
++second;
|
|
}
|
|
} else {
|
|
break;
|
|
}
|
|
}
|
|
if(second!=-1)
|
|
{
|
|
// ----- now second points to the end of the substring:
|
|
part="\""+raw.mid(first, second-first)+"\"";
|
|
// ----- insert decoded value into the list:
|
|
if(parseComplexString(part, 0, value, i))
|
|
{
|
|
kdDebug(GUARD, KAB_KDEBUG_AREA) << "KeyValueMap::get[QStrList]: "
|
|
"found item " << value << endl;
|
|
values.append(value);
|
|
} else {
|
|
kdDebug() << "KeyValueMap::get[QStrList]: parse error." << endl;
|
|
return false;
|
|
}
|
|
if((unsigned)second<raw.length()-3)
|
|
{ // ----- there may be another string
|
|
first=second+2;
|
|
} else { // ----- we are completely finished
|
|
kdDebug(GUARD, KAB_KDEBUG_AREA) << "KeyValueMap::get[QStrList]: "
|
|
"list end found." << endl;
|
|
break;
|
|
}
|
|
} else { // ----- finished:
|
|
break;
|
|
}
|
|
}
|
|
// -----
|
|
kdDebug(GUARD, KAB_KDEBUG_AREA) << "KeyValueMap::get[QStrList]: done." << endl;
|
|
return true;
|
|
// ###########################################################################
|
|
}
|
|
|
|
bool
|
|
KeyValueMap::insert(const TQCString& key, const TQStrList& values, bool force)
|
|
{
|
|
register bool GUARD; GUARD=false;
|
|
// ###########################################################################
|
|
kdDebug(GUARD, KAB_KDEBUG_AREA) <<
|
|
"KeyValueMap::insert[QStrList]: coding string list." << endl;
|
|
TQCString value="\"";
|
|
TQCString temp;
|
|
unsigned int count;
|
|
// ----- create coded string list:
|
|
for(count=0; count<values.count(); ++count)
|
|
{ // create strings like "abc\efgh\eijk":
|
|
temp=makeComplexString(((TQStrList)values).at(count));
|
|
temp.remove(0, 1); // remove the leading "\""
|
|
temp.remove(temp.length()-1, 1); // the trailing "\""
|
|
value+=temp;
|
|
value+="\\e";
|
|
}
|
|
value+="\""; // finish the string
|
|
kdDebug(GUARD, KAB_KDEBUG_AREA) <<
|
|
"KeyValueMap::insert[QStrList]: result of coding is %s." <<
|
|
value << endl;
|
|
// ----- insert it without coding:
|
|
return insertRaw(key, value, force);
|
|
// ###########################################################################
|
|
}
|
|
|
|
// (^^^ QStrList-s)
|
|
// QStringList-s:
|
|
|
|
bool
|
|
KeyValueMap::get(const TQCString& key, TQStringList& values) const
|
|
{
|
|
register bool GUARD; GUARD=false;
|
|
kdDebug(!values.isEmpty(), KAB_KDEBUG_AREA) << "KeyValueMap::get"
|
|
"[QStringList]: attention!\n \"values\" list reference"
|
|
" is not empty!" << endl;
|
|
// ###########################################################################
|
|
/* The values are stored in a utf8-coded set of QCStrings.
|
|
This list is retrieved and converted back to Unicode strings. */
|
|
kdDebug(GUARD, KAB_KDEBUG_AREA) << "KeyValueMap::get[QStringList]: trying to "
|
|
"decode TQStringList for key " << key << endl;
|
|
TQStrList temp;
|
|
unsigned int count;
|
|
// ----- get the plain C strings:
|
|
if(!get(key, temp))
|
|
{
|
|
kdDebug(GUARD, KAB_KDEBUG_AREA) << "KeyValueMap::get[QStringList]: key "
|
|
<< key <<
|
|
" not in KeyValueMap." << endl;
|
|
return false;
|
|
}
|
|
// ----- do the conversion:
|
|
for(count=0; count<temp.count(); ++count)
|
|
{
|
|
values.append(TQString::fromUtf8(temp.at(count)));
|
|
}
|
|
// -----
|
|
kdDebug(GUARD, KAB_KDEBUG_AREA) << "KeyValueMap::get[QStringList]: done." << endl;
|
|
return true;
|
|
// ###########################################################################
|
|
}
|
|
|
|
bool
|
|
KeyValueMap::insert(const TQCString& key, const TQStringList& values, bool force)
|
|
{
|
|
register bool GUARD; GUARD=false;
|
|
// ###########################################################################
|
|
kdDebug(GUARD, KAB_KDEBUG_AREA) <<
|
|
"KeyValueMap::insert[QStringList]: coding TQStringList." << endl;
|
|
// The method simply creates a list of utf8-coded strings and inserts it.
|
|
TQStrList utf8strings;
|
|
unsigned int count;
|
|
// ----- create TQCString list:
|
|
for(count=0; count<values.count(); ++count)
|
|
{
|
|
utf8strings.append((*values.at(count)).utf8());
|
|
}
|
|
kdDebug(GUARD, KAB_KDEBUG_AREA) << "KeyValueMap::insert[QStringList]: done." << endl;
|
|
return insert(key, utf8strings, force);
|
|
// ###########################################################################
|
|
}
|
|
|
|
// (^^^ QStringList-s)
|
|
// lists of doubles:
|
|
|
|
bool
|
|
KeyValueMap::insert(const TQCString& key, const list<double>& values, bool force)
|
|
{
|
|
register bool GUARD; GUARD=false;
|
|
// ###########################################################################
|
|
kdDebug(GUARD, KAB_KDEBUG_AREA) << "KeyValueMap::insert[double list]: trying "
|
|
"to insert double list into map." << endl;
|
|
TQCString buffer;
|
|
// TQCString value(30*values.size()); // not usable with Qt 2
|
|
TQCString value; // WORK_TO_DO: how to reserve enough space to avoid growing?
|
|
list<double>::const_iterator pos;
|
|
// -----
|
|
for(pos=values.begin(); pos!=values.end(); ++pos)
|
|
{
|
|
buffer.setNum(*pos);
|
|
value=value+buffer+", ";
|
|
}
|
|
if(!value.isEmpty())
|
|
{ // remove last comma and space:
|
|
value.remove(value.length()-2, 2);
|
|
}
|
|
// -----
|
|
kdDebug(GUARD, KAB_KDEBUG_AREA) << "KeyValueMap::insert[double list]: "
|
|
"constructed string value is " << value << endl;
|
|
return insert(key, value, force);
|
|
// ###########################################################################
|
|
}
|
|
|
|
bool
|
|
KeyValueMap::get(const TQCString& key, list<double>& values) const
|
|
{
|
|
register bool GUARD; GUARD=false;
|
|
// ###########################################################################
|
|
kdDebug(GUARD, KAB_KDEBUG_AREA) << "KeyValueMap::get[double list]: trying to "
|
|
"decode double list for key " << key << endl;
|
|
kdDebug(!values.empty(), KAB_KDEBUG_AREA) << "KeyValueMap::get[double list]: "
|
|
"attention - list should be empty but is not." << endl;
|
|
TQCString value;
|
|
list<TQCString> tokens;
|
|
list<TQCString>::iterator pos;
|
|
double temp;
|
|
bool ok;
|
|
// -----
|
|
if(!get(key, value))
|
|
{
|
|
kdDebug(GUARD, KAB_KDEBUG_AREA) <<
|
|
"KeyValueMap::get[double list]: no such key." << endl;
|
|
return false;
|
|
}
|
|
// -----
|
|
tokenize(tokens, value, ',');
|
|
for(pos=tokens.begin(); pos!=tokens.end(); ++pos)
|
|
{
|
|
temp=(*pos).toDouble(&ok);
|
|
if(ok)
|
|
{
|
|
values.push_back(temp);
|
|
} else {
|
|
kdDebug() << "KeyValueMap::get[double list]: conversion error for "
|
|
<< *pos << endl;
|
|
}
|
|
}
|
|
// -----
|
|
kdDebug(GUARD, KAB_KDEBUG_AREA) << "KeyValueMap::get[int list]: done." << endl;
|
|
// ###########################################################################
|
|
return true;
|
|
}
|
|
|
|
// (^^^ lists of doubles)
|
|
// QDates:
|
|
|
|
bool
|
|
KeyValueMap::insert(const TQCString& key, const TQDate& value, bool force)
|
|
{
|
|
register bool GUARD; GUARD=false;
|
|
// ###########################################################################
|
|
kdDebug(GUARD, KAB_KDEBUG_AREA) << "KeyValueMap::insert[QDate]: trying to "
|
|
"insert TQDate into map." << endl;
|
|
list<long> values;
|
|
// -----
|
|
if(!value.isValid())
|
|
{
|
|
kdDebug(GUARD, KAB_KDEBUG_AREA) << "KeyValueMap::insert[QDate]: invalid "
|
|
"date, inserting a null date." << endl;
|
|
for(int i=0; i<3; ++i) values.push_back(0);
|
|
} else {
|
|
values.push_back(value.year());
|
|
values.push_back(value.month());
|
|
values.push_back(value.day());
|
|
}
|
|
// -----
|
|
return insert(key, values, force);
|
|
// ###########################################################################
|
|
}
|
|
|
|
bool
|
|
KeyValueMap::get(const TQCString& key, TQDate& date) const
|
|
{
|
|
register bool GUARD; GUARD=false;
|
|
// ###########################################################################
|
|
kdDebug(GUARD, KAB_KDEBUG_AREA) << "KeyValueMap::get[QDate]: trying to decode"
|
|
" TQDate for key " << key << endl;
|
|
list<long> values;
|
|
long y, m, d;
|
|
TQDate temp;
|
|
// -----
|
|
if(!get(key, values))
|
|
{
|
|
kdDebug(GUARD, KAB_KDEBUG_AREA) <<
|
|
"KeyValueMap::get[QDate]: no such key." << endl;
|
|
return false;
|
|
}
|
|
if(values.size()!=3)
|
|
{
|
|
kdDebug(GUARD, KAB_KDEBUG_AREA) <<
|
|
"KeyValueMap::get[QDate]: more or less than 3 values." << endl;
|
|
return false;
|
|
}
|
|
y=values.front(); values.pop_front();
|
|
m=values.front(); values.pop_front();
|
|
d=values.front();
|
|
// -----
|
|
if(y!=0 || m!=0 || d!=0) temp.setYMD(y, m, d); // avoid TQDate messages
|
|
if(!temp.isValid() && !temp.isNull())
|
|
{
|
|
kdDebug(GUARD, KAB_KDEBUG_AREA) <<
|
|
"KeyValueMap::get[QDate]: no valid date." << endl;
|
|
return false;
|
|
} else {
|
|
kdDebug(GUARD, KAB_KDEBUG_AREA) <<
|
|
"KeyValueMap::get[QDate]: done." << endl;
|
|
date=temp;
|
|
return true;
|
|
}
|
|
// ###########################################################################
|
|
}
|
|
|
|
// (^^^ QDates)
|
|
// Section class:
|
|
|
|
const int Section::indent_width=2;
|
|
|
|
Section::Section()
|
|
{
|
|
// ###########################################################################
|
|
// ###########################################################################
|
|
}
|
|
|
|
Section::Section(const KeyValueMap& contents)
|
|
{
|
|
// ###########################################################################
|
|
keys=contents;
|
|
// ###########################################################################
|
|
}
|
|
|
|
bool
|
|
Section::add(const TQCString& name)
|
|
{
|
|
register bool GUARD; GUARD=false;
|
|
// ###########################################################################
|
|
kdDebug(GUARD, KAB_KDEBUG_AREA) << "Section::add: adding section \""
|
|
<<name<<"\" to "
|
|
"this section ..." << endl;
|
|
Section* section;
|
|
bool rc;
|
|
// -----
|
|
if(name.isEmpty())
|
|
{
|
|
kdDebug(GUARD, KAB_KDEBUG_AREA) << "Section::add: empty key." << endl;
|
|
return false;
|
|
}
|
|
section=new Section; // create an empty section
|
|
if(section==0)
|
|
{
|
|
kdDebug() << "Section::add: out of memory." << endl;
|
|
return false;
|
|
}
|
|
rc=add(name, section);
|
|
if(!rc)
|
|
{
|
|
kdDebug(GUARD && !rc, KAB_KDEBUG_AREA) << " failed.\n";
|
|
delete section;
|
|
return false;
|
|
} else {
|
|
kdDebug(GUARD && rc, KAB_KDEBUG_AREA) << " success.\n";
|
|
return true;
|
|
}
|
|
// ###########################################################################
|
|
}
|
|
|
|
bool
|
|
Section::add(const TQCString& name, Section* section)
|
|
{
|
|
register bool GUARD; GUARD=false;
|
|
// ###########################################################################
|
|
if(sections.insert(StringSectionMap::value_type(name, section)).second)
|
|
{
|
|
kdDebug(GUARD, KAB_KDEBUG_AREA) <<
|
|
"Section::add: added section "<<name<<" successfully.\n";
|
|
return true;
|
|
} else {
|
|
kdDebug(GUARD, KAB_KDEBUG_AREA) << "Section::add: failed to add section "
|
|
<< name << ", section already exists.\n";
|
|
return false;
|
|
}
|
|
// ###########################################################################
|
|
}
|
|
|
|
bool
|
|
Section::find(const TQCString& name, StringSectionMap::iterator& result)
|
|
{
|
|
register bool GUARD; GUARD=false;
|
|
// ###########################################################################
|
|
kdDebug(GUARD, KAB_KDEBUG_AREA) << "Section::find: trying to get section "
|
|
"\""<<name<<"\" ... \n";
|
|
StringSectionMap::iterator pos;
|
|
// -----
|
|
pos=sections.find(name);
|
|
if(pos==sections.end())
|
|
{
|
|
kdDebug(GUARD, KAB_KDEBUG_AREA) << "failed, no such section." << endl;
|
|
return false;
|
|
} else {
|
|
kdDebug(GUARD, KAB_KDEBUG_AREA) << "success." << endl;
|
|
result=pos;
|
|
return true;
|
|
}
|
|
// ###########################################################################
|
|
}
|
|
|
|
bool
|
|
Section::remove(const TQCString& name)
|
|
{
|
|
// ###########################################################################
|
|
StringSectionMap::iterator pos;
|
|
// -----
|
|
if(!find(name, pos))
|
|
{
|
|
return false; // no such section
|
|
} else {
|
|
sections.erase(pos);
|
|
return true;
|
|
}
|
|
// ###########################################################################
|
|
}
|
|
|
|
bool
|
|
Section::find(const TQCString& name, Section*& section)
|
|
{
|
|
// ###########################################################################
|
|
StringSectionMap::iterator pos;
|
|
// -----
|
|
if(!find(name, pos))
|
|
{
|
|
return false;
|
|
} else {
|
|
section=(*pos).second;
|
|
return true;
|
|
}
|
|
// ###########################################################################
|
|
}
|
|
|
|
KeyValueMap*
|
|
Section::getKeys()
|
|
{
|
|
// ###########################################################################
|
|
return &keys;
|
|
// ###########################################################################
|
|
}
|
|
|
|
void
|
|
Section::insertIndentSpace(TQTextStream& file, int level)
|
|
{
|
|
// ###########################################################################
|
|
int i, j;
|
|
// -----
|
|
for(i=0; i<level; i++)
|
|
{
|
|
for(j=0; j<indent_width; j++)
|
|
file << ' ';
|
|
}
|
|
// ###########################################################################
|
|
}
|
|
|
|
bool
|
|
Section::save(TQTextStream& stream, int level)
|
|
{
|
|
register bool GUARD; GUARD=false;
|
|
// ###########################################################################
|
|
StringSectionMap::iterator pos;
|
|
// -----
|
|
if(!sections.empty())
|
|
{ // ----- insert a comment:
|
|
insertIndentSpace(stream, level);
|
|
stream << "# subsections:" << endl;
|
|
}
|
|
for(pos=sections.begin(); pos!=sections.end(); ++pos)
|
|
{
|
|
insertIndentSpace(stream, level);
|
|
stream << '[' << (*pos).first << ']' << endl;
|
|
if(!(*pos).second->save(stream, level+1))
|
|
{
|
|
kdDebug() << "Section::save: error saving child section \"" << (*pos).first.data() << "\"." << endl;
|
|
return false;
|
|
} else {
|
|
kdDebug(GUARD, KAB_KDEBUG_AREA) << "Section::save: saved section \""
|
|
<< (*pos).first
|
|
<< "\".\n";
|
|
}
|
|
insertIndentSpace(stream, level);
|
|
stream << "[END " << (*pos).first << ']' << endl;
|
|
}
|
|
if(!keys.empty())
|
|
{
|
|
insertIndentSpace(stream, level);
|
|
stream << "# key-value-pairs:" << endl;
|
|
if(!keys.save(stream, level*indent_width))
|
|
{
|
|
kdDebug() << "Section::save: error saving key-value-pairs." << endl;
|
|
return false;
|
|
}
|
|
}
|
|
// -----
|
|
return true;
|
|
// ###########################################################################
|
|
}
|
|
|
|
bool
|
|
Section::readSection(TQTextStream& file, bool finish)
|
|
{
|
|
register bool GUARD; GUARD=false;
|
|
// ###########################################################################
|
|
kdDebug(GUARD, KAB_KDEBUG_AREA) << "Section::readSection: reading section." << endl;
|
|
TQCString line;
|
|
TQCString name;
|
|
Section* temp;
|
|
// -----
|
|
for(;;)
|
|
{
|
|
line="";
|
|
line=ReadLineFromStream(file);
|
|
if(isEndOfSection(line))
|
|
{ // ----- eof does not matter:
|
|
return true;
|
|
} else { // ----- verify it:
|
|
if(file.eof())
|
|
{
|
|
kdDebug(GUARD, KAB_KDEBUG_AREA) <<
|
|
"Section::readSection: EOF, line is \""<<line<<"\".\n";
|
|
if(!line.isEmpty())
|
|
{
|
|
if(!keys.insertLine(line, false, true, false))
|
|
{
|
|
kdWarning() << "Attention: unable to parse key-value-pair "
|
|
<< endl << "\t\"" << line << "\"," << endl
|
|
<< "ignoring and continuing (maybe duplicate "
|
|
<< "declaration of the key)."
|
|
<< endl;
|
|
}
|
|
}
|
|
if(finish==true)
|
|
{
|
|
kdDebug() << "Section::readSection: missing end of section." << endl;
|
|
return false;
|
|
} else {
|
|
kdDebug(GUARD, KAB_KDEBUG_AREA) <<
|
|
"Section::readSection: EOF (no error)." << endl;
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
if(isBeginOfSection(line))
|
|
{
|
|
name=nameOfSection(line);
|
|
add(name);
|
|
find(name, temp);
|
|
if(!temp->readSection(file))
|
|
{
|
|
kdDebug() << "Section::readSection: unable to read "
|
|
"subsection \"" << name << "\".\n";
|
|
return false;
|
|
}
|
|
} else { // ----- it has to be a key-value-pair:
|
|
if(!keys.insertLine(line, false, true, false))
|
|
{
|
|
kdWarning() << "Attention: unable to parse key-value-pair " << endl
|
|
<< "\t\"" << line << "\"," << endl
|
|
<< "ignoring and continuing (maybe duplicate declaration of"
|
|
<< " the key)."
|
|
<< endl;
|
|
}
|
|
}
|
|
}
|
|
// ###########################################################################
|
|
}
|
|
|
|
bool
|
|
Section::isBeginOfSection(TQCString line)
|
|
{
|
|
register bool GUARD; GUARD=false;
|
|
// ###########################################################################
|
|
line=line.simplifyWhiteSpace();
|
|
if(line.isEmpty() || line.length()<2)
|
|
{
|
|
kdDebug(GUARD, KAB_KDEBUG_AREA) << "Section::isBeginOfSection: too short "
|
|
"or empty line." << endl;
|
|
return false;
|
|
}
|
|
if(line[0]!='[' || line[line.length()-1]!=']')
|
|
{
|
|
return false;
|
|
}
|
|
// -----
|
|
if(line.contains("END"))
|
|
{
|
|
return false;
|
|
} else {
|
|
return true;
|
|
}
|
|
// ###########################################################################
|
|
}
|
|
|
|
bool
|
|
Section::isEndOfSection(TQCString line)
|
|
{
|
|
register bool GUARD; GUARD=false;
|
|
// ###########################################################################
|
|
kdDebug(GUARD, KAB_KDEBUG_AREA) << "Section::isEndOfSection: is "
|
|
<< line <<" the end of"
|
|
" a section?" << endl;
|
|
int first=1, second;
|
|
TQCString temp;
|
|
// -----
|
|
line=line.simplifyWhiteSpace();
|
|
if(line.isEmpty() || line.length()<2)
|
|
{
|
|
kdDebug(GUARD, KAB_KDEBUG_AREA) << "Section::isBeginOfSection: too short "
|
|
"or empty line." << endl;
|
|
return false;
|
|
}
|
|
if(line[0]!='[' || line[line.length()-1]!=']')
|
|
{
|
|
kdDebug(GUARD, KAB_KDEBUG_AREA) <<
|
|
"Section::isBeginOfSection: does not match." << endl;
|
|
return false;
|
|
}
|
|
// ----- find the word inside the brackets:
|
|
for(first=1; line[first]==' '; ++first); // find first non-whitespace character
|
|
for(second=first; line[second]!=' ' && line[second]!=']'; ++second);
|
|
temp=line.mid(first, second-first);
|
|
if(temp=="END")
|
|
{
|
|
kdDebug(GUARD, KAB_KDEBUG_AREA) <<
|
|
"Section::isBeginOfSection: yes, it is." << endl;
|
|
return true;
|
|
} else {
|
|
kdDebug(GUARD, KAB_KDEBUG_AREA) <<
|
|
"Section::isBeginOfSection: no, it is not." << endl;
|
|
return false;
|
|
}
|
|
// ###########################################################################
|
|
}
|
|
|
|
TQCString
|
|
Section::nameOfSection(const TQCString& line)
|
|
{
|
|
register bool GUARD; GUARD=false;
|
|
// ###########################################################################
|
|
int first=1, second;
|
|
TQCString temp;
|
|
// -----
|
|
temp=line.simplifyWhiteSpace();
|
|
if(temp.isEmpty() || temp.length()<=2)
|
|
{ // empty section names are not allowed
|
|
kdDebug(GUARD, KAB_KDEBUG_AREA) <<
|
|
"Section::isBeginOfSection: too short or empty line." << endl;
|
|
return "";
|
|
}
|
|
if(temp[0]!='[' || temp[temp.length()-1]!=']')
|
|
{
|
|
return "";
|
|
}
|
|
// ----- find the word inside the brackets:
|
|
for(first=1; temp[first]==' '; ++first); // find first non-whitespace character
|
|
for(second=first; temp[second]!=' ' && temp[second]!=']'; ++second);
|
|
temp=temp.mid(first, second-first);
|
|
if(temp=="END")
|
|
{
|
|
return "";
|
|
} else {
|
|
return temp;
|
|
}
|
|
// ###########################################################################
|
|
}
|
|
|
|
bool
|
|
Section::clear()
|
|
{
|
|
// ###########################################################################
|
|
StringSectionMap::iterator pos;
|
|
// -----
|
|
for(pos=sections.begin(); pos!=sections.end(); ++pos)
|
|
{
|
|
if(!(*pos).second->clear()) return false;
|
|
delete(*pos).second;
|
|
}
|
|
// sections.clear(); // seems to be not implemented
|
|
sections.erase(sections.begin(), sections.end());
|
|
keys.clear();
|
|
// -----
|
|
return true;
|
|
// ###########################################################################
|
|
}
|
|
|
|
bool
|
|
Section::empty()
|
|
{
|
|
// ###########################################################################
|
|
return keys.empty() && sections.empty();
|
|
// ###########################################################################
|
|
}
|
|
|
|
Section::StringSectionMap::iterator
|
|
Section::sectionsBegin()
|
|
{
|
|
// ###########################################################################
|
|
return sections.begin();
|
|
// ###########################################################################
|
|
}
|
|
|
|
Section::StringSectionMap::iterator
|
|
Section::sectionsEnd()
|
|
{
|
|
// ###########################################################################
|
|
return sections.end();
|
|
// ###########################################################################
|
|
}
|
|
|
|
unsigned int
|
|
Section::noOfSections()
|
|
{
|
|
// ###########################################################################
|
|
return sections.size();
|
|
// ###########################################################################
|
|
}
|
|
|
|
QConfigDB::QConfigDB(TQWidget* parent, const char* name)
|
|
: TQWidget(parent, name),
|
|
timer(0),
|
|
readonly(true),
|
|
locked(false),
|
|
mtime(new TQDateTime)
|
|
{
|
|
// ###########################################################################
|
|
hide();
|
|
// ###########################################################################
|
|
}
|
|
|
|
|
|
QConfigDB::~QConfigDB()
|
|
{
|
|
// ############################################################################
|
|
// disconnect();
|
|
// -----
|
|
if(timer!=0)
|
|
{
|
|
delete timer; timer=0;
|
|
}
|
|
if(!clear()) // this will emit changed() a last time
|
|
{
|
|
kdDebug() << "QConfigDB destructor: cannot remove me." << endl;
|
|
}
|
|
if(locked)
|
|
{
|
|
unlock();
|
|
}
|
|
// ############################################################################
|
|
}
|
|
|
|
bool QConfigDB::invariant()
|
|
{
|
|
return true;
|
|
}
|
|
|
|
bool
|
|
QConfigDB::get(const list<TQCString>& key, KeyValueMap*& map)
|
|
{
|
|
register bool GUARD; GUARD=false;
|
|
// ############################################################################
|
|
kdDebug(GUARD, KAB_KDEBUG_AREA) << "QConfigDB::get: trying to get keys ... " << endl;
|
|
Section* section=⊤
|
|
list<TQCString>::const_iterator pos;
|
|
// -----
|
|
if(key.empty())
|
|
{
|
|
kdDebug(GUARD, KAB_KDEBUG_AREA) <<
|
|
"ConfigDB::get: path is empty, returning toplevel section." << endl;
|
|
map=top.getKeys();
|
|
return true;
|
|
}
|
|
for(pos=key.begin(); pos!=key.end(); ++pos)
|
|
{
|
|
if(!section->find(*pos, section))
|
|
{
|
|
kdDebug(GUARD, KAB_KDEBUG_AREA) <<
|
|
"failed,\n at least the element \""
|
|
<< *pos <<
|
|
"\" of "
|
|
"the key-list is not declared." << endl;
|
|
return false;
|
|
}
|
|
}
|
|
// -----
|
|
map=section->getKeys();
|
|
kdDebug(GUARD, KAB_KDEBUG_AREA) << "success." << endl;
|
|
return true;
|
|
// ############################################################################
|
|
}
|
|
|
|
KeyValueMap*
|
|
QConfigDB::get()
|
|
{
|
|
// ############################################################################
|
|
return top.getKeys();
|
|
// ############################################################################
|
|
}
|
|
|
|
bool
|
|
QConfigDB::createSection(const list<TQCString>& key)
|
|
{
|
|
// ############################################################################
|
|
Section* section=⊤
|
|
unsigned int index;
|
|
list<TQCString>::const_iterator pos;
|
|
Section* thenewone;
|
|
bool rc;
|
|
// -----
|
|
pos=key.begin();
|
|
for(index=0; index<key.size()-1; index++)
|
|
{
|
|
if(!section->find(*pos, section))
|
|
{ // this section is not declared
|
|
Section* temp=new Section; // WORK_TO_DO: memory hole?
|
|
if(section->add(*pos, temp))
|
|
{
|
|
section=temp;
|
|
} else {
|
|
delete temp;
|
|
return false;
|
|
}
|
|
}
|
|
++pos;
|
|
}
|
|
// pos now points to the last element of key,
|
|
// section to the parent of the section that will be inserted
|
|
thenewone=new Section;
|
|
rc=section->add(*pos, thenewone);
|
|
return rc; // missing error report! WORK_TO_DO
|
|
// ############################################################################
|
|
}
|
|
|
|
bool
|
|
QConfigDB::clear()
|
|
{
|
|
// ############################################################################
|
|
bool rc=top.clear();
|
|
emit(changed(this));
|
|
return rc;
|
|
// ############################################################################
|
|
}
|
|
|
|
bool
|
|
QConfigDB::empty()
|
|
{
|
|
// ############################################################################
|
|
return top.empty();
|
|
// ############################################################################
|
|
}
|
|
|
|
bool
|
|
QConfigDB::createSection(const TQCString& desc)
|
|
{
|
|
// ############################################################################
|
|
return createSection(stringToKeylist(desc));
|
|
// ############################################################################
|
|
}
|
|
|
|
bool
|
|
QConfigDB::get(const TQCString& key, KeyValueMap*& map)
|
|
{
|
|
// ############################################################################
|
|
return get(stringToKeylist(key), map);
|
|
// ############################################################################
|
|
}
|
|
|
|
list<TQCString>
|
|
QConfigDB::stringToKeylist(const TQCString& desc)
|
|
{
|
|
register bool GUARD; GUARD=false;
|
|
kdDebug(GUARD, KAB_KDEBUG_AREA) << "QConfigDB::stringToKeylist: parsing path " << desc << endl;
|
|
// ############################################################################
|
|
list<TQCString> key;
|
|
int first=0, second;
|
|
TQCString temp;
|
|
// -----
|
|
if(desc.isEmpty())
|
|
{
|
|
kdDebug(GUARD, KAB_KDEBUG_AREA) <<
|
|
"QConfigDB::stringToKeylist: path is empty." << endl;
|
|
return key;
|
|
}
|
|
for(;;)
|
|
{
|
|
second=desc.find('/', first);
|
|
if(second==-1)
|
|
{
|
|
if((unsigned)first<desc.length()+1)
|
|
{
|
|
temp=desc.mid(first, desc.length()-first);
|
|
kdDebug(GUARD, KAB_KDEBUG_AREA) <<
|
|
"QConfigDB::stringToKeylist: found last part "
|
|
<< temp << endl;
|
|
key.push_back(temp);
|
|
}
|
|
break;
|
|
}
|
|
temp=desc.mid(first, second-first);
|
|
kdDebug(GUARD, KAB_KDEBUG_AREA) <<
|
|
"QConfigDB::stringToKeylist: found part " << temp << endl;
|
|
key.push_back(temp);
|
|
first=second+1;
|
|
}
|
|
// -----
|
|
kdDebug(GUARD, KAB_KDEBUG_AREA) << "QConfigDB::stringToKeylist: done." << endl;
|
|
return key;
|
|
// ############################################################################
|
|
}
|
|
|
|
|
|
bool
|
|
QConfigDB::get(const TQCString& key, Section*& section)
|
|
{
|
|
// ############################################################################
|
|
return get(stringToKeylist(key), section);
|
|
// ############################################################################
|
|
}
|
|
|
|
bool
|
|
QConfigDB::get(const list<TQCString>& key, Section*& section)
|
|
{
|
|
register bool GUARD; GUARD=false;
|
|
// ############################################################################
|
|
kdDebug(GUARD, KAB_KDEBUG_AREA) << "QConfigDB::get: searching section ... " << endl;
|
|
Section* temp=⊤
|
|
list<TQCString>::const_iterator pos;
|
|
// -----
|
|
for(pos=key.begin(); pos!=key.end(); ++pos)
|
|
{
|
|
if(!temp->find(*pos, temp))
|
|
{
|
|
kdDebug(GUARD, KAB_KDEBUG_AREA) << "failure, no such section.";
|
|
return false;
|
|
}
|
|
}
|
|
// -----
|
|
section=temp;
|
|
kdDebug(GUARD, KAB_KDEBUG_AREA) << "success, section found." << endl;
|
|
return true;
|
|
// ############################################################################
|
|
}
|
|
|
|
bool
|
|
QConfigDB::isRO()
|
|
{
|
|
// ############################################################################
|
|
return readonly;
|
|
// ############################################################################
|
|
}
|
|
|
|
int
|
|
QConfigDB::IsLocked(const TQString& file)
|
|
{
|
|
register bool GUARD; GUARD=false;
|
|
// ############################################################################
|
|
TQString lockfile=file+".lock";
|
|
int pid=-1;
|
|
// -----
|
|
if(access(TQFile::encodeName(lockfile), F_OK)==0)
|
|
{
|
|
TQFile f(lockfile);
|
|
// -----
|
|
kdDebug(GUARD, KAB_KDEBUG_AREA) << "QConfigDB::IsLocked: the file\n"
|
|
<< file <<
|
|
"\nhas a lockfile.\n";
|
|
if(f.open(IO_ReadOnly))
|
|
{
|
|
TQTextStream stream(&f);
|
|
stream.setEncoding(TQTextStream::Latin1); // no conversion
|
|
// -----
|
|
stream >> pid;
|
|
if(pid==-1)
|
|
{
|
|
kdDebug(GUARD, KAB_KDEBUG_AREA) << "QConfigDB::IsLocked: the file "
|
|
"does not contain the ID\n of the process that "
|
|
"created it." << endl;
|
|
return -1;
|
|
}
|
|
f.close();
|
|
} else {
|
|
kdDebug(GUARD, KAB_KDEBUG_AREA) <<
|
|
"QConfigDB::IsLocked: cannot open the lockfile." << endl;
|
|
return -1;
|
|
}
|
|
return pid;
|
|
} else {
|
|
kdDebug(GUARD, KAB_KDEBUG_AREA) << "QConfigDB::IsLocked: the file\n"
|
|
<< file << "\nhas no lockfile.\n";
|
|
return 0;
|
|
}
|
|
// ############################################################################
|
|
}
|
|
|
|
bool
|
|
QConfigDB::lock()
|
|
{
|
|
register bool GUARD; GUARD=false;
|
|
// ############################################################################
|
|
if(locked)
|
|
{
|
|
kdDebug(GUARD, KAB_KDEBUG_AREA) << "QConfigDB::lock (current file): file "
|
|
"is already locked by this object." << endl;
|
|
return false;
|
|
}
|
|
if(lock(filename))
|
|
{
|
|
locked=true;
|
|
return true;
|
|
} else {
|
|
return false;
|
|
}
|
|
// ############################################################################
|
|
}
|
|
|
|
bool
|
|
QConfigDB::lock(const TQString& file)
|
|
{
|
|
register bool GUARD; GUARD=false;
|
|
// ############################################################################
|
|
kdDebug(GUARD, KAB_KDEBUG_AREA) << "QConfigDB::lock: locking the file "
|
|
<< file << endl;
|
|
TQString lockfile=file+".lock";
|
|
TQFile f(lockfile);
|
|
// -----
|
|
if(access(TQFile::encodeName(lockfile), F_OK)==0)
|
|
{
|
|
kdDebug(GUARD, KAB_KDEBUG_AREA) << "QConfigDB::lock: the file is locked by"
|
|
" another process." << endl;
|
|
return false;
|
|
} else {
|
|
if(f.open(IO_WriteOnly))
|
|
{
|
|
TQTextStream stream(&f);
|
|
stream.setEncoding(TQTextStream::Latin1); // no conversion
|
|
// -----
|
|
stream << getpid() << endl;
|
|
f.close();
|
|
} else {
|
|
kdDebug(GUARD, KAB_KDEBUG_AREA) << "QConfigDB::lock: unable to create"
|
|
" lockfile." << endl;
|
|
return false;
|
|
}
|
|
}
|
|
// -----
|
|
LockFiles.push_back(lockfile);
|
|
return true;
|
|
// ############################################################################
|
|
}
|
|
|
|
bool
|
|
QConfigDB::unlock()
|
|
{
|
|
register bool GUARD; GUARD=false;
|
|
// ############################################################################
|
|
kdDebug(GUARD, KAB_KDEBUG_AREA) << "QConfigDB::unlock: unlocking the file "
|
|
<< filename << endl;
|
|
TQString lockfile=filename+".lock";
|
|
list<TQString>::iterator pos;
|
|
// -----
|
|
if(!locked)
|
|
{
|
|
kdDebug(GUARD, KAB_KDEBUG_AREA) << "QConfigDB::unlock: this app did not "
|
|
"lock the file!" << endl;
|
|
return false;
|
|
}
|
|
if(access(TQFile::encodeName(lockfile), F_OK | W_OK)==0)
|
|
{
|
|
if(::remove(TQFile::encodeName(lockfile))==0)
|
|
{
|
|
kdDebug(GUARD, KAB_KDEBUG_AREA) <<
|
|
"QConfigDB::unlock: lockfile deleted." << endl;
|
|
for(pos=LockFiles.begin(); pos!=LockFiles.end(); ++pos)
|
|
{
|
|
if((*pos)==lockfile) break;
|
|
}
|
|
if(pos!=LockFiles.end())
|
|
{
|
|
LockFiles.erase(pos); --pos;
|
|
} else {
|
|
kdDebug() << "QConfigDB::unlock: file not mentioned in lockfile" << endl;
|
|
}
|
|
locked=false;
|
|
return true;
|
|
} else {
|
|
kdDebug(GUARD, KAB_KDEBUG_AREA) << "QConfigDB::unlock: unable to "
|
|
"delete lockfile.n" << endl;
|
|
return false;
|
|
}
|
|
} else {
|
|
kdDebug(GUARD, KAB_KDEBUG_AREA) << "QConfigDB::unlock: the file is not"
|
|
" locked or permission has been denied." << endl;
|
|
return false;
|
|
}
|
|
// ############################################################################
|
|
}
|
|
|
|
void
|
|
QConfigDB::CleanLockFiles(int)
|
|
{
|
|
register bool GUARD; GUARD=false;
|
|
// ############################################################################
|
|
list<TQString>::iterator pos;
|
|
// -----
|
|
kdDebug(GUARD, KAB_KDEBUG_AREA).form("QConfigDB::CleanLockFiles: removing %i "
|
|
"remaining lockfiles.", LockFiles.size()) << endl;
|
|
for(pos=LockFiles.begin(); pos!=LockFiles.end(); ++pos)
|
|
{
|
|
if(::remove(TQFile::encodeName(*pos))==0)
|
|
{
|
|
kdDebug(GUARD, KAB_KDEBUG_AREA) <<
|
|
" " << *pos << " removed.\n";
|
|
LockFiles.erase(pos); --pos;
|
|
} else {
|
|
kdDebug() << " could not remove " << *pos << endl;
|
|
}
|
|
}
|
|
// -----
|
|
kdDebug(GUARD, KAB_KDEBUG_AREA) << "QConfigDB::CleanLockFiles: done." << endl;
|
|
// ############################################################################
|
|
}
|
|
|
|
void
|
|
QConfigDB::watch(bool state)
|
|
{
|
|
// ############################################################################
|
|
if(state)
|
|
{ // start timer
|
|
if(timer==0)
|
|
{
|
|
timer=new TQTimer(this);
|
|
connect(timer, TQT_SIGNAL(timeout()), TQT_SLOT(checkFileChanged()));
|
|
}
|
|
timer->start(1000);
|
|
} else { // stop timer
|
|
if(timer!=0)
|
|
{
|
|
timer->stop();
|
|
}
|
|
}
|
|
// ############################################################################
|
|
}
|
|
|
|
bool
|
|
QConfigDB::CheckLockFile(const TQString& file)
|
|
{
|
|
register bool GUARD; GUARD=false;
|
|
// ############################################################################
|
|
kdDebug(GUARD, KAB_KDEBUG_AREA) << "QConfigDB::CheckLockFile: called." << endl;
|
|
int pid;
|
|
// -----
|
|
pid=IsLocked(file);
|
|
if(pid==0)
|
|
{
|
|
kdDebug(GUARD, KAB_KDEBUG_AREA) << "QConfigDB::CheckLockFile: the file is "
|
|
"not locked." << endl;
|
|
return false;
|
|
}
|
|
if(pid>0)
|
|
{
|
|
if(kill(pid, 0)!=0)
|
|
{ // ----- no such process, we may remove the lockfile:
|
|
return false;
|
|
}
|
|
}
|
|
if(pid<0)
|
|
{
|
|
kdDebug(GUARD, KAB_KDEBUG_AREA) << "QConfigDB::CheckLockFile: the file has "
|
|
"not been created by QConfigDB::lock." << endl;
|
|
}
|
|
// ----- check system time and creation time of lockfile:
|
|
// WORK_TO_DO: not implemented
|
|
kdDebug(GUARD, KAB_KDEBUG_AREA) << "QConfigDB::CheckLockFile: done." << endl;
|
|
return true;
|
|
// ############################################################################
|
|
}
|
|
|
|
bool
|
|
QConfigDB::checkFileChanged()
|
|
{
|
|
register bool GUARD; GUARD=false;
|
|
// ############################################################################
|
|
// kdDebug(GUARD, KAB_KDEBUG_AREA) << "QConfigDB::checkFileChanged: called." << endl;
|
|
if(filename.isEmpty())
|
|
{ // ----- false, as file does not exist and thus may be stored anyway
|
|
kdDebug(GUARD, KAB_KDEBUG_AREA) << "QConfigDB::checkFileChanged: no filename." << endl;
|
|
return false;
|
|
}
|
|
TQFileInfo file(filename);
|
|
// -----
|
|
if(file.exists())
|
|
{
|
|
if(file.lastModified() > *mtime)
|
|
{
|
|
kdDebug(GUARD, KAB_KDEBUG_AREA) <<
|
|
"QConfigDB::checkFileChanged: file has been changed.n" << endl;
|
|
emit(fileChanged());
|
|
return true;
|
|
} else {
|
|
return false;
|
|
}
|
|
} else {
|
|
kdDebug(GUARD, KAB_KDEBUG_AREA) << "QConfigDB::checkFileChanged: could "
|
|
"not stat file, file does not exist." << endl;
|
|
if(!mtime->isValid())
|
|
{ // the file did never exist for us:
|
|
return false; // ... so it has not changed
|
|
} else { // it existed, and now it does no more
|
|
emit(fileChanged());
|
|
return true;
|
|
}
|
|
}
|
|
// ############################################################################
|
|
}
|
|
|
|
bool
|
|
QConfigDB::storeFileAge()
|
|
{
|
|
register bool GUARD; GUARD=false;
|
|
// ############################################################################
|
|
kdDebug(GUARD, KAB_KDEBUG_AREA) << "QConfigDB::storeFileAge: called." << endl;
|
|
TQFileInfo file(filename);
|
|
// -----
|
|
if(file.exists())
|
|
{
|
|
*mtime=file.lastModified();
|
|
return true;
|
|
} else {
|
|
kdDebug(GUARD, KAB_KDEBUG_AREA) << "QConfigDB::save: could not stat file." << endl;
|
|
*mtime=TQDateTime(); // a null date
|
|
return false;
|
|
}
|
|
// ############################################################################
|
|
}
|
|
|
|
|
|
bool
|
|
QConfigDB::setFileName(const TQString& filename_, bool mustexist, bool readonly_)
|
|
{
|
|
register bool GUARD; GUARD=false;
|
|
// ############################################################################
|
|
kdDebug(GUARD, KAB_KDEBUG_AREA) << "QConfigDB::setFileName: setting filename "
|
|
"to \""
|
|
<< filename_ <<"\"" << (readonly_ ? " (read only)" : "") << endl;
|
|
// ----- remove previous lock:
|
|
if(locked)
|
|
{
|
|
if(!unlock())
|
|
{
|
|
kdDebug(GUARD, KAB_KDEBUG_AREA) << "QConfigDB::setFileName: cannot "
|
|
"release previous lock." << endl;
|
|
return false;
|
|
}
|
|
}
|
|
// ----- remove possible stale lockfile:
|
|
if(IsLocked(filename_)!=0 && !CheckLockFile(filename_))
|
|
{ // ----- it is stale:
|
|
if(::remove(TQFile::encodeName(filename_+".lock"))==0)
|
|
{
|
|
kdDebug(GUARD, KAB_KDEBUG_AREA) <<
|
|
"QConfigDB::setFileName: removed stale lockfile." << endl;
|
|
} else {
|
|
kdDebug(GUARD, KAB_KDEBUG_AREA) <<
|
|
"QConfigDB::setFileName: cannot remove stale lockfile." << endl;
|
|
return false;
|
|
}
|
|
}
|
|
// -----
|
|
if(mustexist)
|
|
{
|
|
if(access(TQFile::encodeName(filename_), readonly_==true ? R_OK : W_OK | R_OK)==0)
|
|
{
|
|
kdDebug(GUARD, KAB_KDEBUG_AREA) <<
|
|
"QConfigDB::setFileName: permission granted." << endl;
|
|
if(!readonly_)
|
|
{ // we need r/w access:
|
|
if(lock(filename_))
|
|
{
|
|
locked=true;
|
|
} else {
|
|
kdDebug(GUARD, KAB_KDEBUG_AREA) << "QConfigDB::setFileName: "
|
|
"could not lock the file." << endl;
|
|
return false;
|
|
}
|
|
}
|
|
readonly=readonly_;
|
|
filename=filename_;
|
|
storeFileAge();
|
|
return true;
|
|
} else {
|
|
kdDebug() << "QConfigDB::setFileName: permission denied, " << endl;
|
|
return false;
|
|
}
|
|
} else {
|
|
if(access(TQFile::encodeName(filename_), F_OK)==0)
|
|
{
|
|
kdDebug(GUARD, KAB_KDEBUG_AREA) << "QConfigDB::setFileName: file exists." << endl;
|
|
if(access(TQFile::encodeName(filename_), W_OK | R_OK)==0)
|
|
{
|
|
kdDebug(GUARD, KAB_KDEBUG_AREA) <<
|
|
"QConfigDB::setFileName: permission granted." << endl;
|
|
if(!readonly_)
|
|
{ // we need r/w access:
|
|
if(lock(filename_))
|
|
{
|
|
locked=true;
|
|
} else {
|
|
kdDebug(GUARD, KAB_KDEBUG_AREA) << "QConfigDB::setFileName: "
|
|
"could not lock the file." << endl;
|
|
return false;
|
|
}
|
|
}
|
|
readonly=readonly_;
|
|
filename=filename_;
|
|
storeFileAge();
|
|
return true;
|
|
} else {
|
|
kdDebug(GUARD, KAB_KDEBUG_AREA) << "QConfigDB::setFileName: "
|
|
"permission denied, filename not set." << endl;
|
|
return false;
|
|
}
|
|
} else {
|
|
kdDebug(GUARD, KAB_KDEBUG_AREA) <<
|
|
"QConfigDB::setFileName: permission granted, new file." << endl;
|
|
readonly=readonly_;
|
|
filename=filename_;
|
|
if(!readonly)
|
|
{
|
|
if(!lock())
|
|
{
|
|
kdDebug(GUARD, KAB_KDEBUG_AREA) <<
|
|
"QConfigDB::setFileName: could not lock the file." << endl;
|
|
return false;
|
|
}
|
|
}
|
|
storeFileAge();
|
|
return true;
|
|
}
|
|
}
|
|
// ############################################################################
|
|
}
|
|
|
|
TQString
|
|
QConfigDB::fileName()
|
|
{
|
|
// ############################################################################
|
|
return filename;
|
|
// ############################################################################
|
|
}
|
|
|
|
bool
|
|
QConfigDB::save(const char* header, bool force)
|
|
{
|
|
register bool GUARD; GUARD=true;
|
|
// ############################################################################
|
|
kdDebug(GUARD, KAB_KDEBUG_AREA) <<
|
|
"QConfigDB::save: saving database -->" << filename << "<--.\n";
|
|
bool wasRO=false;
|
|
bool rc;
|
|
// -----
|
|
if(checkFileChanged())
|
|
{
|
|
kdDebug(GUARD, KAB_KDEBUG_AREA) <<
|
|
"QConfigDB::save: file is newer, not saving." << endl;
|
|
return false;
|
|
}
|
|
if(force && isRO())
|
|
{
|
|
if(setFileName(fileName(), true, false))
|
|
{
|
|
wasRO=true;
|
|
kdDebug(GUARD, KAB_KDEBUG_AREA) <<
|
|
"QConfigDB::save: switched to (forced) r/w mode." << endl;
|
|
} else {
|
|
kdDebug(GUARD, KAB_KDEBUG_AREA) <<
|
|
"QConfigDB::save: cannot switch to (forced) r/w mode." << endl;
|
|
return false;
|
|
}
|
|
}
|
|
// ----- now save it:
|
|
if(!isRO())
|
|
{
|
|
TQFile file(filename);
|
|
if(file.open(IO_WriteOnly))
|
|
{
|
|
TQTextStream stream(&file);
|
|
stream.setEncoding(TQTextStream::Latin1); // no conversion
|
|
// -----
|
|
if(header!=0)
|
|
{
|
|
stream << "# " << header << endl;
|
|
}
|
|
stream << '#' << " [File created by QConfigDB object "
|
|
<< version() << "]" << endl;
|
|
if(!top.save(stream)) // traverse tree
|
|
{
|
|
kdDebug(GUARD, KAB_KDEBUG_AREA) <<
|
|
"QConfigDB::save: error saving subsections." << endl;
|
|
}
|
|
storeFileAge();
|
|
file.close();
|
|
rc=true;
|
|
} else {
|
|
kdDebug() << "QConfigDB::save: error opening file \""
|
|
<< filename <<
|
|
"\" for writing.\n";
|
|
rc=false;
|
|
}
|
|
} else {
|
|
rc=false;
|
|
}
|
|
// ----- reset r/o mode:
|
|
if(wasRO) // only true if we switched to forced r/w mode here
|
|
{
|
|
if(setFileName(fileName(), false, true))
|
|
{
|
|
kdDebug(GUARD, KAB_KDEBUG_AREA) <<
|
|
"QConfigDB::save: reset (forced) r/w mode." << endl;
|
|
} else {
|
|
kdDebug(GUARD, KAB_KDEBUG_AREA) <<
|
|
"QConfigDB::save: cannot reset (forced) r/w mode." << endl;
|
|
rc=false;
|
|
}
|
|
}
|
|
// -----
|
|
return rc;
|
|
// ############################################################################
|
|
}
|
|
|
|
bool
|
|
QConfigDB::load()
|
|
{
|
|
register bool GUARD; GUARD=false ;
|
|
// ############################################################################
|
|
TQFile file(filename);
|
|
// -----
|
|
if(file.open(IO_ReadOnly))
|
|
{
|
|
kdDebug(GUARD, KAB_KDEBUG_AREA) << "QConfigDB::load: file access OK." << endl;
|
|
TQTextStream stream(&file);
|
|
stream.setEncoding(TQTextStream::Latin1); // no conversion
|
|
// -----
|
|
clear();
|
|
bool rc=top.readSection(stream, false);
|
|
storeFileAge();
|
|
file.close();
|
|
emit(changed(this));
|
|
kdDebug(GUARD, KAB_KDEBUG_AREA) << "QConfigDB::load: done." << endl;
|
|
return rc;
|
|
} else {
|
|
kdDebug() << "QConfigDB::load: error opening file \"" << filename << "\" for reading." << endl;
|
|
return false;
|
|
}
|
|
// ############################################################################
|
|
}
|