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.
2041 lines
54 KiB
2041 lines
54 KiB
/* -*- C++ -*-
|
|
This file implements the basic personal information management class
|
|
used in the KDE addressbook.
|
|
|
|
the KDE 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 "addressbook.h"
|
|
#include "qconfigDB.h"
|
|
|
|
#include <tqfileinfo.h>
|
|
#include <tqstringlist.h>
|
|
|
|
#include <kapplication.h>
|
|
#include <kglobal.h>
|
|
#include <kstandarddirs.h>
|
|
#include <klocale.h>
|
|
#include <kdebug.h>
|
|
#include <kmessagebox.h>
|
|
|
|
extern "C" {
|
|
#include <sys/stat.h>
|
|
#include <sys/types.h>
|
|
#include <fcntl.h>
|
|
#include <unistd.h>
|
|
}
|
|
|
|
// ----- some defines:
|
|
#ifdef KAB_KDEBUG_AREA
|
|
#undef KAB_KDEBUG_AREA
|
|
#endif
|
|
|
|
#define KAB_KDEBUG_AREA 800
|
|
|
|
#ifdef STD_USERFILENAME
|
|
#undef STD_USERFILENAME
|
|
#endif
|
|
#define STD_USERFILENAME "kab/addressbook.kab"
|
|
|
|
#ifdef STD_CONFIGFILENAME
|
|
#undef STD_CONFIGFILENAME
|
|
#endif
|
|
#define STD_CONFIGFILENAME "kab/kab.config"
|
|
|
|
#ifdef ENTRY_SECTION
|
|
#undef ENTRY_SECTION
|
|
#endif
|
|
#define ENTRY_SECTION "entries"
|
|
|
|
// the name of the file-local configuration section
|
|
#ifdef LOCAL_CONFIG_SECTION
|
|
#undef LOCAL_CONFIG_SECTION
|
|
#endif
|
|
#define LOCAL_CONFIG_SECTION "config"
|
|
|
|
// the name of the subsection for each entry
|
|
#ifdef ADDRESS_SUBSECTION
|
|
#undef ADDRESS_SUBSECTION
|
|
#endif
|
|
#define ADDRESS_SUBSECTION "addresses"
|
|
|
|
#ifdef KAB_TEMPLATEFILE
|
|
#undef KAB_TEMPLATEFILE
|
|
#endif
|
|
#define KAB_TEMPLATEFILE "kab/template.kab"
|
|
|
|
#ifdef KAB_CONFIGTEMPLATE
|
|
#undef KAB_CONFIGTEMPLATE
|
|
#endif
|
|
#define KAB_CONFIGTEMPLATE "kab/template.config"
|
|
|
|
#ifdef KAB_CATEGORY_KEY
|
|
#undef KAB_CATEGORY_KEY
|
|
#endif
|
|
#define KAB_CATEGORY_KEY "categories"
|
|
|
|
const char* AddressBook::Entry::Address::Fields[]= {
|
|
"headline", "position",
|
|
"org", "orgunit", "orgsubunit",
|
|
"deliverylabel", "address", "zip", "town", "country", "state" };
|
|
const int AddressBook::Entry::Address::NoOfFields
|
|
=sizeof(AddressBook::Entry::Address::Fields)
|
|
/sizeof(AddressBook::Entry::Address::Fields[0]);
|
|
|
|
const char* AddressBook::Entry::Fields[]= {
|
|
"title", "rank", "fn", "nameprefix", "firstname", "middlename", "lastname",
|
|
"birthday", "comment", "talk", "emails", "keywords", "telephone",
|
|
"urls", "user1", "user2", "user3", "user4", "custom", "categories" };
|
|
const int AddressBook::Entry::NoOfFields
|
|
=sizeof(AddressBook::Entry::Fields)/sizeof(AddressBook::Entry::Fields[0]);
|
|
|
|
struct QStringLess
|
|
: public binary_function<const TQString&, const TQString&, bool>
|
|
{
|
|
/** The function operator, inline. */
|
|
bool operator()(const TQString& x, const TQString& y) const
|
|
{
|
|
return x < y; // make one Qt operator fit exactly
|
|
}
|
|
};
|
|
|
|
// ----- the derived map class:
|
|
class StringKabKeyMap : public map<TQString, KabKey, QStringLess>
|
|
{ /* Same as map, but a class for compilation reasons. This way we do not need
|
|
* to include the QStringLess class into the addressbook header file. */
|
|
};
|
|
|
|
// ----- another derived map class:
|
|
class KeyNameMap : public map<const char*, TQString, less<const char*> >
|
|
{ // same thing
|
|
};
|
|
|
|
KeyNameMap* AddressBook::Entry::fields;
|
|
KeyNameMap* AddressBook::Entry::Address::fields;
|
|
|
|
bool
|
|
KabKey::operator == (const KabKey& key) const
|
|
{
|
|
// ###########################################################################
|
|
return key.getKey()==getKey();
|
|
// ###########################################################################
|
|
}
|
|
|
|
void
|
|
KabKey::setKey(const TQCString& text)
|
|
{
|
|
// ###########################################################################
|
|
key=text;
|
|
// ###########################################################################
|
|
}
|
|
|
|
TQCString
|
|
KabKey::getKey() const
|
|
{
|
|
// ###########################################################################
|
|
return key;
|
|
// ###########################################################################
|
|
}
|
|
|
|
|
|
|
|
AddressBook::Entry::Address::Address()
|
|
{
|
|
}
|
|
|
|
bool AddressBook::Entry::Address::nameOfField(const char* key, TQString& value)
|
|
{
|
|
KeyNameMap::iterator pos;
|
|
// -----
|
|
if(fields==0)
|
|
{ // this is executed exactly one time per application instance,
|
|
// as fields is static
|
|
int counter=0;
|
|
fields=new KeyNameMap;
|
|
TQ_CHECK_PTR(fields);
|
|
if(!fields->insert
|
|
(map<const char*, TQString, less<const char*> >::value_type
|
|
(Fields[counter++], i18n("Headline"))).second
|
|
||
|
|
!fields->insert
|
|
(map<const char*, TQString, less<const char*> >::value_type
|
|
(Fields[counter++], i18n("Position"))).second
|
|
||
|
|
!fields->insert
|
|
(map<const char*, TQString, less<const char*> >::value_type
|
|
(Fields[counter++], i18n("Organization"))).second
|
|
||
|
|
!fields->insert
|
|
(map<const char*, TQString, less<const char*> >::value_type
|
|
(Fields[counter++], i18n("Department"))).second
|
|
||
|
|
!fields->insert
|
|
(map<const char*, TQString, less<const char*> >::value_type
|
|
(Fields[counter++], i18n("Sub-Department"))).second
|
|
||
|
|
!fields->insert
|
|
(map<const char*, TQString, less<const char*> >::value_type
|
|
(Fields[counter++], i18n("Delivery Label"))).second
|
|
||
|
|
!fields->insert
|
|
(map<const char*, TQString, less<const char*> >::value_type
|
|
(Fields[counter++], i18n("street/postal","Address"))).second
|
|
||
|
|
!fields->insert
|
|
(map<const char*, TQString, less<const char*> >::value_type
|
|
(Fields[counter++], i18n("Zipcode"))).second
|
|
||
|
|
!fields->insert
|
|
(map<const char*, TQString, less<const char*> >::value_type
|
|
(Fields[counter++], i18n("City"))).second
|
|
||
|
|
!fields->insert
|
|
(map<const char*, TQString, less<const char*> >::value_type
|
|
(Fields[counter++], i18n("Country"))).second
|
|
||
|
|
!fields->insert
|
|
(map<const char*, TQString, less<const char*> >::value_type
|
|
(Fields[counter++], i18n("As in addresses", "State"))).second)
|
|
{
|
|
kdDebug(KAB_KDEBUG_AREA)
|
|
<< "AddressBook::Entry::Address::nameOfField (while "
|
|
<< " creating field-name map): TYPO, correct this."
|
|
<< endl;
|
|
} else {
|
|
kdDebug(KAB_KDEBUG_AREA)
|
|
<< "AddressBook::Entry::Address::nameOfField: "
|
|
<< "inserted field names." << endl;
|
|
}
|
|
#if ! defined NDEBUG
|
|
TQString name;
|
|
kdDebug(KAB_KDEBUG_AREA)
|
|
<< "AddressBook::Entry::Address::nameOfField:" << endl
|
|
<< "Created key-fieldname-map. Defined fields are:"
|
|
<< endl;
|
|
for(counter=0; counter<AddressBook::Entry::Address::NoOfFields;
|
|
++counter)
|
|
{
|
|
pos=fields->find(Fields[counter]);
|
|
if(pos==fields->end())
|
|
{
|
|
kdDebug(KAB_KDEBUG_AREA) << " UNDEFINED" << endl;
|
|
} else {
|
|
kdDebug(KAB_KDEBUG_AREA)
|
|
<< " " << Fields[counter] << " ("
|
|
<< (*pos).second.utf8() << ")" << endl;
|
|
}
|
|
}
|
|
#endif
|
|
}
|
|
// ----- now finally do the lookup:
|
|
pos=fields->find(key);
|
|
if(pos==fields->end())
|
|
{
|
|
return false;
|
|
} else {
|
|
value=(*pos).second;
|
|
return true;
|
|
}
|
|
}
|
|
|
|
bool AddressBook::Entry::nameOfField(const char* key, TQString& value)
|
|
{
|
|
KeyNameMap::iterator pos;
|
|
// -----
|
|
if(fields==0)
|
|
{ // this is executed exactly one time per application instance,
|
|
// as fields is static
|
|
int counter=0;
|
|
fields=new KeyNameMap;
|
|
TQ_CHECK_PTR(fields);
|
|
if(!fields->insert
|
|
(map<const char*, TQString, less<const char*> >::value_type
|
|
(Fields[counter++], i18n("person","Title"))).second
|
|
||
|
|
!fields->insert
|
|
(map<const char*, TQString, less<const char*> >::value_type
|
|
(Fields[counter++], i18n("Rank"))).second
|
|
||
|
|
!fields->insert
|
|
(map<const char*, TQString, less<const char*> >::value_type
|
|
(Fields[counter++], i18n("Formatted Name"))).second
|
|
||
|
|
!fields->insert
|
|
(map<const char*, TQString, less<const char*> >::value_type
|
|
(Fields[counter++], i18n("Name Prefix"))).second
|
|
||
|
|
!fields->insert
|
|
(map<const char*, TQString, less<const char*> >::value_type
|
|
(Fields[counter++], i18n("First Name"))).second
|
|
||
|
|
!fields->insert
|
|
(map<const char*, TQString, less<const char*> >::value_type
|
|
(Fields[counter++], i18n("Middle Name"))).second
|
|
||
|
|
!fields->insert
|
|
(map<const char*, TQString, less<const char*> >::value_type
|
|
(Fields[counter++], i18n("Last Name"))).second
|
|
||
|
|
!fields->insert
|
|
(map<const char*, TQString, less<const char*> >::value_type
|
|
(Fields[counter++], i18n("Birthday"))).second
|
|
||
|
|
!fields->insert
|
|
(map<const char*, TQString, less<const char*> >::value_type
|
|
(Fields[counter++], i18n("Comment"))).second
|
|
||
|
|
!fields->insert
|
|
(map<const char*, TQString, less<const char*> >::value_type
|
|
(Fields[counter++], i18n("Talk Addresses"))).second
|
|
||
|
|
!fields->insert
|
|
(map<const char*, TQString, less<const char*> >::value_type
|
|
(Fields[counter++], i18n("Email Addresses"))).second
|
|
||
|
|
!fields->insert
|
|
(map<const char*, TQString, less<const char*> >::value_type
|
|
(Fields[counter++], i18n("Keywords"))).second
|
|
||
|
|
!fields->insert
|
|
(map<const char*, TQString, less<const char*> >::value_type
|
|
(Fields[counter++], i18n("Telephone Number"))).second
|
|
||
|
|
!fields->insert
|
|
(map<const char*, TQString, less<const char*> >::value_type
|
|
(Fields[counter++], i18n("URLs"))).second
|
|
||
|
|
!fields->insert
|
|
(map<const char*, TQString, less<const char*> >::value_type
|
|
(Fields[counter++], i18n("User Field 1"))).second
|
|
||
|
|
!fields->insert
|
|
(map<const char*, TQString, less<const char*> >::value_type
|
|
(Fields[counter++], i18n("User Field 2"))).second
|
|
||
|
|
!fields->insert
|
|
(map<const char*, TQString, less<const char*> >::value_type
|
|
(Fields[counter++], i18n("User Field 3"))).second
|
|
||
|
|
!fields->insert
|
|
(map<const char*, TQString, less<const char*> >::value_type
|
|
(Fields[counter++], i18n("User Field 4"))).second
|
|
||
|
|
!fields->insert
|
|
(map<const char*, TQString, less<const char*> >::value_type
|
|
(Fields[counter++], i18n("Custom"))).second
|
|
||
|
|
!fields->insert
|
|
(map<const char*, TQString, less<const char*> >::value_type
|
|
(Fields[counter++], i18n("Categories"))).second)
|
|
{
|
|
kdDebug(KAB_KDEBUG_AREA)
|
|
<< "AddressBook::Entry::Address::nameOfField (while "
|
|
<< " creating field-name map): TYPO, correct this." << endl;
|
|
} else {
|
|
kdDebug(KAB_KDEBUG_AREA)
|
|
<< "AddressBook::Entry::Address::nameOfField: "
|
|
<< "inserted field names." << endl;
|
|
}
|
|
#if ! defined NDEBUG
|
|
TQString name;
|
|
kdDebug(KAB_KDEBUG_AREA)
|
|
<< "AddressBook::Entry::nameOfField:" << endl
|
|
<< "Created key-fieldname-map. Defined fields are:" << endl;
|
|
for(counter=0; counter<AddressBook::Entry::Address::NoOfFields;
|
|
++counter)
|
|
{
|
|
pos=fields->find(Fields[counter]);
|
|
if(pos==fields->end())
|
|
{
|
|
kdDebug(KAB_KDEBUG_AREA) << " UNDEFINED" << endl;
|
|
} else {
|
|
kdDebug(KAB_KDEBUG_AREA)
|
|
<< " " << Fields[counter] << " ("
|
|
<< (*pos).second.utf8() << ")" << endl;
|
|
}
|
|
}
|
|
#endif
|
|
}
|
|
// ----- now finally do the lookup:
|
|
pos=fields->find(key);
|
|
if(pos==fields->end())
|
|
{
|
|
return false;
|
|
} else {
|
|
value=(*pos).second;
|
|
return true;
|
|
}
|
|
}
|
|
|
|
AddressBook::ErrorCode
|
|
AddressBook::Entry::getAddress(int index, Address& address) const
|
|
{
|
|
// ###########################################################################
|
|
list<Address>::const_iterator pos;
|
|
// -----
|
|
if(index>=0 && (unsigned)index<addresses.size())
|
|
{
|
|
pos=addresses.begin();
|
|
advance(pos, index);
|
|
address=*pos;
|
|
return AddressBook::NoError;
|
|
} else {
|
|
return AddressBook::OutOfRange;
|
|
}
|
|
// ###########################################################################
|
|
}
|
|
|
|
int AddressBook::Entry::noOfAddresses() const
|
|
{
|
|
return addresses.size();
|
|
}
|
|
|
|
AddressBook::AddressBook(TQWidget* parent, const char* name, bool loadit)
|
|
: TQFrame(parent, name),
|
|
config(new QConfigDB(this)),
|
|
data(new QConfigDB(this)),
|
|
entries(new StringKabKeyMap),
|
|
state(NoFile)
|
|
{
|
|
register bool GUARD; GUARD=true;
|
|
// ###########################################################################
|
|
TQString dir, filename;
|
|
bool createBackup=true;
|
|
KeyValueMap *keys;
|
|
// ----- do memory checks (do not rely on exception handling):
|
|
if(config==0 || data==0 || entries==0)
|
|
{
|
|
KMessageBox::error(this,
|
|
i18n("Cannot initialize local variables."),
|
|
i18n("Out of Memory"));
|
|
kapp->quit(); // It is critical, but will possibly never happen.
|
|
}
|
|
connect(data, TQT_SIGNAL(fileChanged()), TQT_SLOT(dataFileChanged()));
|
|
connect(data, TQT_SIGNAL(changed(QConfigDB*)),
|
|
TQT_SLOT(reloaded(QConfigDB*)));
|
|
connect(config, TQT_SIGNAL(fileChanged()), TQT_SLOT(configFileChanged()));
|
|
// ----- set style:
|
|
|
|
filename = locate( "data", STD_CONFIGFILENAME);
|
|
if (filename.isEmpty())
|
|
{
|
|
filename = locateLocal( "data", STD_CONFIGFILENAME );
|
|
// config does not exist yet
|
|
if(createConfigFile()!=NoError)
|
|
{
|
|
KMessageBox::sorry(this,
|
|
i18n("Your local kab configuration file "
|
|
"\"%1\" "
|
|
"could not be created. kab will probably not "
|
|
"work correctly without it.\n"
|
|
"Make sure you have not removed write permission "
|
|
"from your local KDE directory (usually ~/.kde).").arg(filename));
|
|
state=PermDenied;
|
|
}
|
|
}
|
|
loadConfigFile();
|
|
// ----- now get some configuration settings:
|
|
if(config->get("config", keys))
|
|
{
|
|
keys->get("CreateBackupOnStartup", createBackup);
|
|
}
|
|
// ----- check and possibly create user standard file:
|
|
filename = locate( "data", STD_USERFILENAME );
|
|
|
|
if(filename.isEmpty()) // if it does not exist
|
|
{
|
|
filename = locateLocal( "data", STD_USERFILENAME);
|
|
if(createNew(filename)!=NoError) // ...and we cannot create it
|
|
{
|
|
KMessageBox::sorry(this,
|
|
i18n("Your standard kab database file "
|
|
"\"%1\" "
|
|
"could not be created. kab will probably not "
|
|
"work correctly without it.\n"
|
|
"Make sure you have not removed write permission "
|
|
"from your local KDE directory (usually ~/.kde).").arg(filename));
|
|
state=PermDenied;
|
|
} else {
|
|
KMessageBox::information
|
|
(this,
|
|
i18n("kab has created your standard addressbook in\n\"%1\"")
|
|
.arg(filename));
|
|
}
|
|
}
|
|
// ----- load the user standard file:
|
|
if(loadit)
|
|
{
|
|
if(load(filename)!=NoError)
|
|
{ // ----- the standard file could not be loaded
|
|
state=PermDenied;
|
|
} else {
|
|
if(createBackup)
|
|
{
|
|
// ----- create the backup file:
|
|
TQString temp=data->fileName();
|
|
if(data->setFileName(temp+".backup", false, false))
|
|
{
|
|
if(!data->save())
|
|
{
|
|
KMessageBox::information
|
|
(this,
|
|
i18n("Cannot create backup file (permission denied)."),
|
|
i18n("File Error"));
|
|
}
|
|
} else {
|
|
KMessageBox::error
|
|
(this,
|
|
i18n("Cannot open backup file for "
|
|
"writing (permission denied)."),
|
|
i18n("File Error"));
|
|
}
|
|
// ----- reset the filename:
|
|
if(!data->setFileName(temp, true, true))
|
|
{
|
|
KMessageBox::error
|
|
(this,
|
|
i18n("Critical error:\n"
|
|
"Permissions changed in local directory!"),
|
|
i18n("File Error"));
|
|
closeFile(false);
|
|
state=PermDenied;
|
|
} else {
|
|
state=NoError;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
// -----
|
|
data->watch(true);
|
|
// ###########################################################################
|
|
}
|
|
|
|
AddressBook::~AddressBook()
|
|
{
|
|
// ###########################################################################
|
|
delete data;
|
|
delete config;
|
|
delete entries;
|
|
// ###########################################################################
|
|
}
|
|
|
|
QConfigDB* AddressBook::getConfig()
|
|
{
|
|
// ###########################################################################
|
|
return config;
|
|
// ###########################################################################
|
|
}
|
|
|
|
AddressBook::ErrorCode AddressBook::getState()
|
|
{
|
|
// ###########################################################################
|
|
return state;
|
|
// ###########################################################################
|
|
}
|
|
|
|
AddressBook::ErrorCode AddressBook::load(const TQString& filename)
|
|
{
|
|
// ----- Remark: Close the file if it could not be loaded!
|
|
// ###########################################################################
|
|
ErrorCode rc=NoError;
|
|
TQFileInfo newfile, oldfile;
|
|
// -----
|
|
TQString fname = (filename.isEmpty()) ? data->fileName() : filename ;
|
|
if(fname.isEmpty()) // there was never a filename set:
|
|
{
|
|
state=NoFile;
|
|
return NoFile;
|
|
}
|
|
// -----
|
|
newfile.setFile(fname);
|
|
oldfile.setFile(data->fileName());
|
|
if(isSameFile(fname, data->fileName()))
|
|
{ // ----- possibly deleted file:
|
|
if(data->load())
|
|
{
|
|
emit(setStatus(i18n("File reloaded.")));
|
|
state=NoError;
|
|
} else {
|
|
switch
|
|
(KMessageBox::questionYesNo
|
|
(this,
|
|
i18n("The currently loaded file "
|
|
"\"%1\" "
|
|
"cannot be reloaded. kab may close or save it.\n"
|
|
"Save it if you accidentally deleted your data file.\n"
|
|
"Close it if you intended to do so.\n"
|
|
"Your file will be closed by default.")
|
|
.arg(oldfile.absFilePath()),
|
|
i18n("File Error"),
|
|
KStdGuiItem::close(), KStdGuiItem::save()))
|
|
{
|
|
case KMessageBox::No: // save
|
|
if(!data->save(i18n("(Safety copy on file error)").ascii(), true))
|
|
{
|
|
KMessageBox::information(this,
|
|
i18n("Cannot save the file; will close it now."),
|
|
i18n("File Error"));
|
|
closeFile(false);
|
|
state=NoFile;
|
|
rc=PermDenied;
|
|
} else {
|
|
state=NoError;
|
|
rc=NoError;
|
|
}
|
|
break; // no error if we could save the file
|
|
default: // close
|
|
closeFile(false);
|
|
state=NoFile;
|
|
rc=NoSuchFile;
|
|
break;
|
|
}
|
|
}
|
|
} else { // ----- set new filename
|
|
if(data->setFileName(fname, true, true))
|
|
{
|
|
if(data->load())
|
|
{
|
|
emit(changed());
|
|
emit(setStatus(i18n("File opened.")));
|
|
state=NoError;
|
|
} else {
|
|
KMessageBox::information(this,
|
|
i18n("Could not load the file."),
|
|
i18n("File Error"));
|
|
closeFile(false);
|
|
emit(setStatus(i18n("No such file.")));
|
|
rc=NoSuchFile;
|
|
}
|
|
} else {
|
|
if(KMessageBox::questionYesNo
|
|
(this,
|
|
i18n("The file \"%1\" cannot be found. "
|
|
"Create a new one?").arg(fname),
|
|
i18n("No Such File"),
|
|
i18n("Create"), KStdGuiItem::cancel())==KMessageBox::Yes)
|
|
{
|
|
if(createNew(fname)==NoError)
|
|
{
|
|
emit(setStatus(i18n("New file.")));
|
|
} else { // ----- do not close here, stick with the old file:
|
|
emit(setStatus(i18n("Canceled.")));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
// -----
|
|
if(rc==NoError)
|
|
{
|
|
data->watch(true);
|
|
updateMirrorMap();
|
|
}
|
|
// -----
|
|
return rc;
|
|
// ###########################################################################
|
|
}
|
|
|
|
AddressBook::ErrorCode
|
|
AddressBook::getListOfNames(TQStringList* strings, bool reverse, bool initials)
|
|
{
|
|
register bool GUARD; GUARD=false;
|
|
// ###########################################################################
|
|
kdDebug(GUARD, KAB_KDEBUG_AREA) << "AddressBook::getListOfNames: called.\n";
|
|
StringKabKeyMap::iterator pos;
|
|
TQString desc;
|
|
ErrorCode rc=NoError;
|
|
ErrorCode temp;
|
|
// ----- erase the list contents:
|
|
strings->clear();
|
|
// ----- ...and fill it:
|
|
for(pos=entries->begin(); pos!=entries->end(); ++pos)
|
|
{
|
|
temp=literalName((*pos).second, desc, reverse, initials);
|
|
if(temp!=AddressBook::NoError)
|
|
{
|
|
desc=i18n("(Internal error in kab)");
|
|
rc=InternError;
|
|
}
|
|
if(desc.isEmpty())
|
|
{
|
|
desc=i18n("(empty entry)");
|
|
}
|
|
kdDebug(GUARD, KAB_KDEBUG_AREA) <<
|
|
"AddressBook::getListOfNames: adding " << desc << endl;
|
|
strings->append(desc);
|
|
}
|
|
// ----- any problems?
|
|
kdDebug(GUARD, KAB_KDEBUG_AREA)
|
|
<< "AddressBook::getListOfNames: done, "
|
|
<< strings->count()
|
|
<< " entries.\n";
|
|
return rc;
|
|
// ###########################################################################
|
|
}
|
|
|
|
AddressBook::ErrorCode
|
|
AddressBook::literalName(const KabKey& key, TQString& text, bool rev, bool init)
|
|
{
|
|
// ###########################################################################
|
|
Entry entry;
|
|
ErrorCode rc;
|
|
// ----- get the entry:
|
|
rc=getEntry(key, entry);
|
|
if(rc!=NoError)
|
|
{
|
|
return rc;
|
|
}
|
|
// -----
|
|
return literalName(entry, text, rev, init);
|
|
// ###########################################################################
|
|
}
|
|
|
|
AddressBook::ErrorCode
|
|
AddressBook::literalName(const Entry& entry, TQString& text, bool rev, bool init)
|
|
{
|
|
register bool GUARD; GUARD=false;
|
|
// ###########################################################################
|
|
kdDebug(GUARD, KAB_KDEBUG_AREA) << "AddressBook::literalName: called.\n";
|
|
TQString firstname, middlename, lastname, nameprefix;
|
|
// ----- is the formatted name set?
|
|
if(!entry.fn.isEmpty())
|
|
{
|
|
text=entry.fn;
|
|
kdDebug(GUARD, KAB_KDEBUG_AREA) <<
|
|
"AddressBook::literalName: done (fn).\n";
|
|
return NoError;
|
|
}
|
|
// ----- prepare the strings:
|
|
firstname=entry.firstname.simplifyWhiteSpace();
|
|
middlename=entry.middlename.simplifyWhiteSpace();
|
|
lastname=entry.lastname.simplifyWhiteSpace();
|
|
nameprefix=entry.nameprefix.simplifyWhiteSpace();
|
|
// ----- create the initials:
|
|
if(init)
|
|
{
|
|
if(!firstname.isEmpty()) firstname=firstname.mid(0, 1)+'.';
|
|
if(!middlename.isEmpty()) middlename=middlename.mid(0, 1)+'.';
|
|
// if(!lastname.isEmpty()) lastname=lastname.mid(0, 1)+'.';
|
|
}
|
|
// ----- assemble the string:
|
|
text="";
|
|
if(rev)
|
|
{ // name, firstname - add. name - name prefix
|
|
if(!lastname.isEmpty())
|
|
{
|
|
text=lastname;
|
|
}
|
|
if(!firstname.isEmpty() || !middlename.isEmpty() || !nameprefix.isEmpty())
|
|
{
|
|
text+=',';
|
|
}
|
|
if(!firstname.isEmpty())
|
|
{
|
|
if(!text.isEmpty())
|
|
{
|
|
text+=' ';
|
|
}
|
|
text+=firstname;
|
|
}
|
|
if(!middlename.isEmpty())
|
|
{
|
|
if(!text.isEmpty())
|
|
{
|
|
text+=' ';
|
|
}
|
|
text+=middlename;
|
|
}
|
|
if(!nameprefix.isEmpty())
|
|
{
|
|
if(!text.isEmpty())
|
|
{
|
|
text+=' ';
|
|
}
|
|
text+=nameprefix;
|
|
}
|
|
} else {
|
|
// firstname - add. name - name prefix - name
|
|
text=firstname;
|
|
if(!middlename.isEmpty())
|
|
{
|
|
if(!text.isEmpty())
|
|
{
|
|
text+=' ';
|
|
}
|
|
text+=middlename;
|
|
}
|
|
if(!nameprefix.isEmpty())
|
|
{
|
|
if(!text.isEmpty())
|
|
{
|
|
text+=' ';
|
|
}
|
|
text+=nameprefix;
|
|
}
|
|
if(!lastname.isEmpty())
|
|
{
|
|
if(!text.isEmpty())
|
|
{
|
|
text+=' ';
|
|
}
|
|
text+=lastname;
|
|
}
|
|
}
|
|
// -----
|
|
kdDebug(GUARD, KAB_KDEBUG_AREA) << "AddressBook::literalName: done: "
|
|
<< text << ".\n";
|
|
return NoError;
|
|
// ###########################################################################
|
|
}
|
|
|
|
unsigned int
|
|
AddressBook::noOfEntries()
|
|
{
|
|
// ###########################################################################
|
|
return entries->size();
|
|
// ###########################################################################
|
|
}
|
|
|
|
void
|
|
AddressBook::dataFileChanged()
|
|
{
|
|
// ###########################################################################
|
|
data->watch(false); // will be restarted after successful load
|
|
load();
|
|
// ###########################################################################
|
|
}
|
|
|
|
void
|
|
AddressBook::configFileChanged()
|
|
{
|
|
register bool GUARD; GUARD=true;
|
|
// ###########################################################################
|
|
if(!config->load())
|
|
{
|
|
KMessageBox::error(this,
|
|
i18n("Cannot reload configuration file!"),
|
|
i18n("File Error"));
|
|
} else {
|
|
kdDebug(GUARD, KAB_KDEBUG_AREA) << "AddressBook::configFileChanged: "
|
|
"config file reloaded.\n";
|
|
emit(setStatus(i18n("Configuration file reloaded.")));
|
|
}
|
|
// ###########################################################################
|
|
}
|
|
|
|
void
|
|
AddressBook::reloaded(QConfigDB* db)
|
|
{
|
|
register bool GUARD; GUARD=false;
|
|
// ###########################################################################
|
|
if(db==data)
|
|
{
|
|
kdDebug(GUARD, KAB_KDEBUG_AREA) << "AddressBook::reloaded: file has been "
|
|
"reloaded.\n";
|
|
updateMirrorMap(); // WORK_TO_DO: what's up with the return value?
|
|
changed();
|
|
}
|
|
// ###########################################################################
|
|
}
|
|
|
|
AddressBook::ErrorCode
|
|
AddressBook::save(const TQString& filename, bool force)
|
|
{
|
|
// ###########################################################################
|
|
if(filename.isEmpty())
|
|
{
|
|
if(data->save(0, force))
|
|
{
|
|
emit(setStatus(i18n("File saved.")));
|
|
return NoError;
|
|
} else {
|
|
return PermDenied;
|
|
}
|
|
} else {
|
|
if(data->setFileName(filename, false, false))
|
|
{
|
|
if(data->save(0, true))
|
|
{
|
|
emit(newFile(filename));
|
|
return NoError;
|
|
} else {
|
|
return PermDenied;
|
|
}
|
|
} else {
|
|
return PermDenied;
|
|
}
|
|
}
|
|
// ###########################################################################
|
|
}
|
|
|
|
bool
|
|
AddressBook::isSameFile(const TQString& a, const TQString& b)
|
|
{
|
|
// ###########################################################################
|
|
TQFileInfo filea(a), fileb(b);
|
|
// -----
|
|
return filea.absFilePath()==fileb.absFilePath();
|
|
// ###########################################################################
|
|
}
|
|
|
|
AddressBook::ErrorCode
|
|
AddressBook::closeFile(bool saveit)
|
|
{
|
|
// ###########################################################################
|
|
if(saveit)
|
|
{
|
|
if(save()!=NoError)
|
|
{
|
|
emit(setStatus(i18n("Permission denied.")));
|
|
return PermDenied;
|
|
}
|
|
}
|
|
data->clear();
|
|
// data->reset(); WORK_TO_DO: File name is not reset by now.
|
|
emit(setStatus(i18n("File closed.")));
|
|
return NoError;
|
|
// ###########################################################################
|
|
}
|
|
|
|
AddressBook::ErrorCode
|
|
AddressBook::getEntry(const KabKey& key, Entry& entry)
|
|
{
|
|
// ###########################################################################
|
|
Section *section;
|
|
// -----
|
|
if(getEntry(key, section)==NoError)
|
|
{
|
|
return makeEntryFromSection(section, entry);
|
|
} else {
|
|
return NoSuchEntry;
|
|
}
|
|
// ###########################################################################
|
|
}
|
|
|
|
AddressBook::ErrorCode
|
|
AddressBook::getEntry(const KabKey& key, Section*& section)
|
|
{
|
|
register bool GUARD; GUARD=false;
|
|
// ###########################################################################
|
|
kdDebug(GUARD, KAB_KDEBUG_AREA) << "AddressBook::getEntry: searching entry "
|
|
"with key " << key.getKey().data() << endl;
|
|
StringKabKeyMap::iterator pos;
|
|
// -----
|
|
for(pos=entries->begin(); pos!=entries->end(); ++pos)
|
|
{
|
|
if((*pos).second==key)
|
|
{
|
|
kdDebug(GUARD, KAB_KDEBUG_AREA) <<
|
|
"AddressBook::getEntry: key exists." << endl;
|
|
break;
|
|
}
|
|
}
|
|
if(pos==entries->end())
|
|
{
|
|
kdDebug(GUARD, KAB_KDEBUG_AREA) <<
|
|
"AddressBook::getEntry: no such entry.\n";
|
|
return NoSuchEntry;
|
|
} else {
|
|
if(data->get((TQCString)ENTRY_SECTION+'/'+key.getKey(), section))
|
|
{
|
|
kdDebug(GUARD, KAB_KDEBUG_AREA) <<
|
|
"AddressBook::getEntry: done." << endl;
|
|
return NoError;
|
|
} else {
|
|
return InternError;
|
|
}
|
|
}
|
|
// ###########################################################################
|
|
}
|
|
|
|
AddressBook::ErrorCode
|
|
AddressBook::getEntries(list<Entry>& thelist)
|
|
{
|
|
// ###########################################################################
|
|
StringKabKeyMap::iterator pos;
|
|
Entry entry;
|
|
ErrorCode rc;
|
|
// -----
|
|
kdDebug(!thelist.empty(), KAB_KDEBUG_AREA)
|
|
<< "AddressBook::getEntries: warning - non-empty value list!" << endl;
|
|
thelist.erase(thelist.begin(), thelist.end());
|
|
for(pos=entries->begin(); pos!=entries->end(); ++pos)
|
|
{
|
|
rc=getEntry((*pos).second, entry);
|
|
if(rc==NoError)
|
|
{
|
|
thelist.push_back(entry);
|
|
} else {
|
|
return InternError;
|
|
}
|
|
}
|
|
// -----
|
|
return NoError;
|
|
// ###########################################################################
|
|
}
|
|
|
|
AddressBook::ErrorCode
|
|
AddressBook::getKey(int index, KabKey& key)
|
|
{
|
|
// ###########################################################################
|
|
StringKabKeyMap::iterator pos;
|
|
// -----
|
|
if((unsigned)index<entries->size())
|
|
{
|
|
pos=entries->begin();
|
|
advance(pos, index);
|
|
key=(*pos).second;
|
|
return NoError;
|
|
} else {
|
|
return NoSuchEntry;
|
|
}
|
|
// ###########################################################################
|
|
}
|
|
|
|
AddressBook::ErrorCode
|
|
AddressBook::getIndex(const KabKey& key, int& index)
|
|
{
|
|
register bool GUARD; GUARD=true;
|
|
// ###########################################################################
|
|
StringKabKeyMap::iterator pos;
|
|
// -----
|
|
index=0;
|
|
for(pos=entries->begin(); pos!=entries->end(); ++pos)
|
|
{
|
|
// kdDebug(KAB_KDEBUG_AREA) << (*pos).second.getKey().data() << " <--> " <<
|
|
// key.getKey().data() << endl;
|
|
if((*pos).second==key) break;
|
|
++index;
|
|
}
|
|
kdDebug(pos==entries->end(), KAB_KDEBUG_AREA) <<
|
|
"AddressBook::getIndex: no such key." << endl;
|
|
if(pos==entries->end())
|
|
{
|
|
return NoSuchEntry;
|
|
} else {
|
|
return NoError;
|
|
}
|
|
// ###########################################################################
|
|
}
|
|
|
|
Section*
|
|
AddressBook::entrySection()
|
|
{
|
|
// ###########################################################################
|
|
Section* section;
|
|
// -----
|
|
if(!data->get(ENTRY_SECTION, section))
|
|
{
|
|
return 0;
|
|
} else {
|
|
return section;
|
|
}
|
|
// ###########################################################################
|
|
}
|
|
|
|
AddressBook::ErrorCode
|
|
AddressBook::add(const Entry& entry, KabKey& key, bool update)
|
|
{
|
|
bool GUARD; GUARD=true;
|
|
kdDebug(GUARD, KAB_KDEBUG_AREA) << "AddressBook::add: called." << endl;
|
|
// ###########################################################################
|
|
Section* theEntries=entrySection();
|
|
Section* newEntry;
|
|
KabKey nextKey;
|
|
ErrorCode locked;
|
|
ErrorCode rc;
|
|
// -----
|
|
if(theEntries==0)
|
|
{
|
|
kdDebug(KAB_KDEBUG_AREA) << "AddressBook::add: no entries section."
|
|
<< endl;
|
|
return NoFile;
|
|
}
|
|
newEntry=new Section;
|
|
if(newEntry==0)
|
|
{
|
|
KMessageBox::error(this,
|
|
i18n("Cannot initialize local variables."),
|
|
i18n("Out of Memory"));
|
|
kapp->quit(); // It is critical, but will possibly never happen.
|
|
return InternError; // shut the compiler up...
|
|
}
|
|
// ----- lock the file:
|
|
locked=lock();
|
|
switch(locked)
|
|
{
|
|
case PermDenied:
|
|
kdDebug(GUARD, KAB_KDEBUG_AREA)
|
|
<< "AddressBook::add: permission denied." << endl;
|
|
return PermDenied; // cannot get r/w mode
|
|
case Locked:
|
|
kdDebug(GUARD, KAB_KDEBUG_AREA)
|
|
<< "AddressBook::add: db is already in r/w mode." << endl;
|
|
break;
|
|
case NoError:
|
|
kdDebug(GUARD, KAB_KDEBUG_AREA)
|
|
<< "AddressBook::add: got writing permissions." << endl;
|
|
break;
|
|
default:
|
|
kdDebug(GUARD, KAB_KDEBUG_AREA)
|
|
<< "AddressBook::add: unknown response, exiting." << endl;
|
|
return InternError;
|
|
}
|
|
// -----
|
|
if(makeSectionFromEntry(entry, *newEntry)==NoError)
|
|
{
|
|
nextKey=nextAvailEntryKey();
|
|
if(!theEntries->add(nextKey.getKey(), newEntry))
|
|
{
|
|
kdDebug(KAB_KDEBUG_AREA)
|
|
<< "AddressBook::add: Cannot insert section.\n";
|
|
rc=InternError;
|
|
} else {
|
|
key=nextKey;
|
|
emit(changed());
|
|
rc=NoError;
|
|
}
|
|
if(update) updateMirrorMap();
|
|
} else {
|
|
rc=InternError;
|
|
}
|
|
if(locked!=Locked)
|
|
{ // ----- unlock the file here:
|
|
kdDebug(GUARD, KAB_KDEBUG_AREA)
|
|
<< "AddressBook::add: dropped writing permissions." << endl;
|
|
locked=unlock();
|
|
}
|
|
// -----
|
|
kdDebug(GUARD, KAB_KDEBUG_AREA) << "AddressBook::add: done." << endl;
|
|
if(locked!=NoError)
|
|
{
|
|
return locked;
|
|
}
|
|
if(rc!=NoError)
|
|
{
|
|
return rc;
|
|
}
|
|
return NoError;
|
|
// ###########################################################################
|
|
}
|
|
|
|
AddressBook::ErrorCode
|
|
AddressBook::change(const KabKey& key, const Entry& entry)
|
|
{
|
|
// ###########################################################################
|
|
Section* theEntries=entrySection();
|
|
Section* oldEntry;
|
|
ErrorCode locked;
|
|
ErrorCode rc;
|
|
// -----
|
|
if(theEntries==0)
|
|
{
|
|
return NoFile;
|
|
}
|
|
// ----- lock the file:
|
|
locked=lock();
|
|
if(locked==PermDenied)
|
|
{
|
|
return PermDenied; // cannot get r/w mode
|
|
}
|
|
// -----
|
|
if(!theEntries->find(key.getKey(), oldEntry))
|
|
{
|
|
rc=NoSuchEntry;
|
|
} else {
|
|
oldEntry->clear();
|
|
rc=makeSectionFromEntry(entry, *oldEntry);
|
|
emit(changed());
|
|
}
|
|
// -----
|
|
if(locked!=PermDenied)
|
|
{ // ----- unlock the file here:
|
|
locked=unlock();
|
|
}
|
|
if(locked==NoError)
|
|
{
|
|
return rc;
|
|
} else {
|
|
return locked;
|
|
}
|
|
// ###########################################################################
|
|
}
|
|
|
|
AddressBook::ErrorCode
|
|
AddressBook::remove(const KabKey& key)
|
|
{
|
|
// ###########################################################################
|
|
Section *theEntries=entrySection();
|
|
ErrorCode locked;
|
|
ErrorCode rc;
|
|
// -----
|
|
if(theEntries==0)
|
|
{
|
|
return NoFile;
|
|
}
|
|
// ----- lock the file:
|
|
locked=lock();
|
|
if(locked==PermDenied)
|
|
{
|
|
return PermDenied; // cannot get r/w mode
|
|
}
|
|
// -----
|
|
if(theEntries->remove(key.getKey()))
|
|
{
|
|
rc=NoError;
|
|
emit(changed());
|
|
} else {
|
|
rc=NoSuchEntry;
|
|
}
|
|
// -----
|
|
if(locked!=PermDenied)
|
|
{ // ----- unlock the file here:
|
|
locked=unlock();
|
|
}
|
|
if(locked==NoError)
|
|
{
|
|
return rc;
|
|
} else {
|
|
return locked;
|
|
}
|
|
// ###########################################################################
|
|
}
|
|
|
|
AddressBook::ErrorCode
|
|
AddressBook::lock()
|
|
{
|
|
// ###########################################################################
|
|
if(!data->isRO()) return Locked;
|
|
if(data->setFileName(data->fileName(), false, false))
|
|
{
|
|
return NoError;
|
|
} else {
|
|
KMessageBox::information(this,
|
|
i18n("The file you wanted to change could not be locked.\n"
|
|
"It is probably in use by another application or read-only."),
|
|
i18n("File Error"));
|
|
return PermDenied;
|
|
}
|
|
// ###########################################################################
|
|
}
|
|
|
|
AddressBook::ErrorCode
|
|
AddressBook::unlock()
|
|
{
|
|
// ###########################################################################
|
|
if(data->isRO()) return PermDenied;
|
|
if(data->setFileName(data->fileName(), true, true))
|
|
{
|
|
return NoError;
|
|
} else {
|
|
return InternError;
|
|
}
|
|
// ###########################################################################
|
|
}
|
|
|
|
KabKey
|
|
AddressBook::nextAvailEntryKey()
|
|
{
|
|
// ###########################################################################
|
|
int max=0;
|
|
int temp;
|
|
Section::StringSectionMap::iterator pos;
|
|
Section *section=entrySection();
|
|
KabKey key;
|
|
TQCString dummy;
|
|
bool good=true;
|
|
// -----
|
|
if(section!=0)
|
|
{
|
|
for(pos=section->sectionsBegin(); pos!=section->sectionsEnd(); ++pos)
|
|
{
|
|
temp=0;
|
|
temp=(*pos).first.toInt(&good);
|
|
if(!good)
|
|
{
|
|
kdDebug(KAB_KDEBUG_AREA)
|
|
<< "AddressBook::nextAvailEntryKey: non-integer entry "
|
|
<< endl;
|
|
}
|
|
if(temp>max)
|
|
{
|
|
max=temp;
|
|
}
|
|
}
|
|
}
|
|
// -----
|
|
dummy.setNum(++max);
|
|
key.setKey(dummy);
|
|
// CHECK(key.getKey().toInt(&good)==max);
|
|
return key;
|
|
// ###########################################################################
|
|
}
|
|
|
|
AddressBook::ErrorCode
|
|
AddressBook::updateMirrorMap()
|
|
{
|
|
register bool GUARD; GUARD=false;
|
|
// ###########################################################################
|
|
kdDebug(GUARD, KAB_KDEBUG_AREA)
|
|
<< "AddressBook::updateMirrorMap: updating mirror map.\n";
|
|
TQString key;
|
|
Entry entry;
|
|
ErrorCode ec;
|
|
KabKey kk;
|
|
Section *section=entrySection();
|
|
Section::StringSectionMap::iterator pos;
|
|
// -----
|
|
entries->erase(entries->begin(), entries->end());
|
|
if(section==0)
|
|
{
|
|
kdDebug(GUARD, KAB_KDEBUG_AREA) << "AddressBook::updateMirrorMap: done, "
|
|
"no file loaded." << endl;
|
|
return NoError;
|
|
}
|
|
for(pos=section->sectionsBegin(); pos!=section->sectionsEnd(); ++pos)
|
|
{
|
|
if(makeEntryFromSection((*pos).second, entry)!=NoError)
|
|
{
|
|
// return InternError; // it is saver to continue without a key
|
|
}
|
|
key="";
|
|
ec=literalName(entry, key, true, false);
|
|
if(key.isEmpty() || ec!=NoError)
|
|
{
|
|
key=i18n("(empty entry)");
|
|
}
|
|
key+=(*pos).first; // append the section name to make the key unique
|
|
kk.setKey((*pos).first);
|
|
entries->insert(StringKabKeyMap::value_type(key, kk));
|
|
}
|
|
// -----
|
|
kdDebug(GUARD, KAB_KDEBUG_AREA) << "AddressBook::updateMirrorMap: done."
|
|
<< endl;
|
|
return NoError;
|
|
// ###########################################################################
|
|
}
|
|
|
|
AddressBook::ErrorCode
|
|
AddressBook::makeEntryFromSection(Section* section, Entry& entry)
|
|
{
|
|
// ###########################################################################
|
|
Section *addresses;
|
|
Section *addressSection;
|
|
Section::StringSectionMap::iterator pos;
|
|
KeyValueMap *keys;
|
|
Entry temp;
|
|
Entry::Address address;
|
|
Entry::Address addressDummy;
|
|
int count;
|
|
// ----- create the aggregats:
|
|
const TQCString StringKeys[]= {
|
|
"title",
|
|
"rank",
|
|
"fn",
|
|
"nameprefix",
|
|
"firstname",
|
|
"middlename",
|
|
"lastname",
|
|
"comment",
|
|
"user1",
|
|
"user2",
|
|
"user3",
|
|
"user4"
|
|
};
|
|
TQString* StringValues[]= {
|
|
&temp.title,
|
|
&temp.rank,
|
|
&temp.fn,
|
|
&temp.nameprefix,
|
|
&temp.firstname,
|
|
&temp.middlename,
|
|
&temp.lastname,
|
|
&temp.comment,
|
|
&temp.user1,
|
|
&temp.user2,
|
|
&temp.user3,
|
|
&temp.user4
|
|
};
|
|
const int StringKeySize=sizeof(StringKeys)/sizeof(StringKeys[0]);
|
|
const TQCString StringListKeys[]= {
|
|
"talk",
|
|
"emails",
|
|
"keywords",
|
|
"telephone",
|
|
"URLs",
|
|
"custom",
|
|
"categories"
|
|
};
|
|
TQStringList* StringListValues[]= {
|
|
&temp.talk,
|
|
&temp.emails,
|
|
&temp.keywords,
|
|
&temp.telephone,
|
|
&temp.URLs,
|
|
&temp.custom,
|
|
&temp.categories
|
|
};
|
|
const int StringListKeySize=sizeof(StringListKeys)/sizeof(StringListKeys[0]);
|
|
// ----- first parse "addresses" subsection:
|
|
if(!section->find(ADDRESS_SUBSECTION, addresses))
|
|
{
|
|
return InternError; // no subsection called "addresses"
|
|
}
|
|
for(pos=addresses->sectionsBegin(); pos!=addresses->sectionsEnd(); ++pos)
|
|
{
|
|
if(!addresses->find((*pos).first, addressSection))
|
|
{
|
|
return InternError; // no section we have an iterator for?
|
|
}
|
|
keys=addressSection->getKeys();
|
|
address=addressDummy; // clean it up
|
|
if(makeAddressFromMap(keys, address)==AddressBook::NoError)
|
|
{
|
|
// ----- add the address to the list of addresses:
|
|
temp.addresses.push_back(address);
|
|
} else {
|
|
kdDebug(KAB_KDEBUG_AREA)
|
|
<< "AddressBook::makeEntryFromSection: cannot find all fields "
|
|
<< "in an address subsection." << endl;
|
|
}
|
|
}
|
|
// ----- now parse all other fields directly:
|
|
keys=section->getKeys();
|
|
for(count=0; count<StringKeySize; ++count)
|
|
{
|
|
if(!keys->get(StringKeys[count], *StringValues[count]))
|
|
{
|
|
/* Spits out lots of warnings:
|
|
kdDebug(KAB_KDEBUG_AREA)
|
|
<< "AddressBook::makeEntryFromSection: error: could not get "
|
|
<< "value for key " << (const char*)StringKeys[count]
|
|
<< "." << endl;
|
|
*/
|
|
}
|
|
}
|
|
for(count=0; count<StringListKeySize; ++count)
|
|
{
|
|
if(!keys->get(StringListKeys[count], *StringListValues[count]))
|
|
{
|
|
/* Spits out lots of warnings:
|
|
kdDebug(KAB_KDEBUG_AREA)
|
|
<< "AddressBook::makeEntryFromSection: error: could not get "
|
|
<< "value for key " << (const char*)StringListKeys[count]
|
|
<< "." << endl;
|
|
*/
|
|
}
|
|
}
|
|
// ----- finally get the birthday:
|
|
keys->get("birthday", temp.birthday); // this may return false (no date)
|
|
// -----
|
|
entry=temp;
|
|
return NoError;
|
|
// ###########################################################################
|
|
}
|
|
|
|
AddressBook::ErrorCode
|
|
AddressBook::makeAddressFromMap(KeyValueMap* keys, Entry::Address& address)
|
|
{
|
|
// ###########################################################################
|
|
const TQCString Keys[]= {
|
|
"headline",
|
|
"position",
|
|
"org",
|
|
"orgunit",
|
|
"orgsubunit",
|
|
// "role",
|
|
"deliverylabel",
|
|
"address",
|
|
"zip",
|
|
"town",
|
|
"country",
|
|
"state"
|
|
};
|
|
TQString* strings[]= {
|
|
&address.headline,
|
|
&address.position,
|
|
&address.org,
|
|
&address.orgUnit,
|
|
&address.orgSubUnit,
|
|
// &address.role,
|
|
&address.deliveryLabel,
|
|
&address.address,
|
|
&address.zip,
|
|
&address.town,
|
|
&address.country,
|
|
&address.state
|
|
};
|
|
const int Size=sizeof(Keys)/sizeof(Keys[0]);
|
|
int count;
|
|
// -----
|
|
for(count=0; count<Size; ++count)
|
|
{
|
|
keys->get(Keys[count], *strings[count]);
|
|
}
|
|
return NoError;
|
|
// ###########################################################################
|
|
}
|
|
|
|
AddressBook::ErrorCode
|
|
AddressBook::makeSectionFromEntry(const Entry& entry, Section& section)
|
|
{
|
|
// ###########################################################################
|
|
list<Entry::Address>::const_iterator addPos;
|
|
Section *addresses=0;
|
|
Section *address=0;
|
|
TQCString key; // used for creating address subsection keys
|
|
int count=0; // counts the addresses
|
|
KeyValueMap *keys;
|
|
// ----- prepare the section object:
|
|
section.clear();
|
|
// ----- first create "addresses" subsection:
|
|
if(!section.add(ADDRESS_SUBSECTION))
|
|
{
|
|
kdDebug(KAB_KDEBUG_AREA)
|
|
<< "AddressBook::makeSectionFromEntry: cannot create " << "subsection."
|
|
<< " " << endl;
|
|
return InternError;
|
|
}
|
|
if(!section.find(ADDRESS_SUBSECTION, addresses))
|
|
{
|
|
kdDebug(KAB_KDEBUG_AREA)
|
|
<< "AddressBook::makeSectionFromEntry: cannot get new section." << endl;
|
|
return InternError;
|
|
}
|
|
// ----- now insert addresses:
|
|
for(addPos=entry.addresses.begin(); addPos!=entry.addresses.end(); ++addPos)
|
|
{
|
|
++count;
|
|
key.setNum(count);
|
|
if(!addresses->add(key))
|
|
{
|
|
kdDebug(KAB_KDEBUG_AREA)
|
|
<< "AddressBook::makeSectionFromEntry: cannot create address " << endl;
|
|
return InternError;
|
|
}
|
|
if(!addresses->find(key, address))
|
|
{
|
|
kdDebug(KAB_KDEBUG_AREA)
|
|
<< "AddressBook::makeSectionFromEntry: cannot get new " << endl;
|
|
return InternError;
|
|
}
|
|
keys=address->getKeys();
|
|
// ----- now insert keys into address:
|
|
if(!keys->insert("headline", (*addPos).headline) ||
|
|
!keys->insert("position", (*addPos).position) ||
|
|
!keys->insert("org", (*addPos).org) ||
|
|
!keys->insert("orgunit", (*addPos).orgUnit) ||
|
|
!keys->insert("orgsubunit", (*addPos).orgSubUnit) ||
|
|
// !keys->insert("role", (*addPos).role) ||
|
|
!keys->insert("deliverylabel", (*addPos).deliveryLabel) ||
|
|
!keys->insert("address", (*addPos).address) ||
|
|
!keys->insert("zip", (*addPos).zip) ||
|
|
!keys->insert("town", (*addPos).town) ||
|
|
!keys->insert("country", (*addPos).country) ||
|
|
!keys->insert("state", (*addPos).state))
|
|
{
|
|
kdDebug(KAB_KDEBUG_AREA)
|
|
<< "AddressBook::makeSectionFromEntry: cannot completely "
|
|
<< "insert this address." << endl;
|
|
return InternError;
|
|
}
|
|
}
|
|
// ----- now add the other fields:
|
|
keys=section.getKeys();
|
|
if(!keys->insert("title", entry.title) ||
|
|
!keys->insert("rank", entry.rank) ||
|
|
!keys->insert("fn", entry.fn) ||
|
|
!keys->insert("nameprefix", entry.nameprefix) ||
|
|
!keys->insert("firstname", entry.firstname) ||
|
|
!keys->insert("middlename", entry.middlename) ||
|
|
!keys->insert("lastname", entry.lastname) ||
|
|
!keys->insert("birthday", entry.birthday) ||
|
|
!keys->insert("comment", entry.comment) ||
|
|
!keys->insert("talk", entry.talk) ||
|
|
!keys->insert("emails", entry.emails) ||
|
|
!keys->insert("keywords", entry.keywords) ||
|
|
!keys->insert("telephone", entry.telephone) ||
|
|
!keys->insert("URLs", entry.URLs) ||
|
|
!keys->insert("user1", entry.user1) ||
|
|
!keys->insert("user2", entry.user2) ||
|
|
!keys->insert("user3", entry.user3) ||
|
|
!keys->insert("user4", entry.user4) ||
|
|
!keys->insert("custom", entry.custom) ||
|
|
!keys->insert("categories", entry.categories))
|
|
{
|
|
kdDebug(KAB_KDEBUG_AREA)
|
|
<< "AddressBook::makeEntryFromSection: cannot insert "
|
|
<< "all fields of the entry." << endl;
|
|
return InternError;
|
|
}
|
|
// -----
|
|
return NoError;
|
|
// ###########################################################################
|
|
}
|
|
|
|
AddressBook::ErrorCode
|
|
AddressBook::createNew(const TQString& filename)
|
|
{
|
|
// ###########################################################################
|
|
const TQString KabTemplateFile=locate("data", "kab/template.kab");
|
|
kdDebug(KAB_KDEBUG_AREA)
|
|
<< "AddressBook::createNew: template file is \""
|
|
<< (const char*)KabTemplateFile.utf8() << "\"." << endl;
|
|
QConfigDB db;
|
|
// -----
|
|
if(KabTemplateFile.isEmpty()
|
|
|| !db.setFileName(KabTemplateFile, true, true))
|
|
{
|
|
KMessageBox::error(this,
|
|
i18n("Cannot find kab's template file.\n"
|
|
"You cannot create new files."),
|
|
i18n("File Error"));
|
|
return InternError;
|
|
}
|
|
if(!db.load())
|
|
{
|
|
KMessageBox::error(this,
|
|
i18n("Cannot read kab's template file.\n"
|
|
"You cannot create new files."),
|
|
i18n("Format Error"));
|
|
|
|
return InternError;
|
|
}
|
|
if(!db.setFileName(filename, false, false))
|
|
{
|
|
KMessageBox::error(this,
|
|
i18n("Cannot create the file\n\"")
|
|
+filename+"\"\n"+
|
|
i18n("Could not create the new file."),
|
|
i18n("File Error"));
|
|
return PermDenied;
|
|
}
|
|
if(!db.save())
|
|
{
|
|
KMessageBox::error(this,
|
|
i18n("Cannot save the file\n\"")
|
|
+filename+"\"\n"+
|
|
i18n("Could not create the new file."),
|
|
i18n("File Error"));
|
|
return InternError;
|
|
}
|
|
// -----
|
|
return NoError;
|
|
// ###########################################################################
|
|
}
|
|
|
|
AddressBook::ErrorCode
|
|
AddressBook::createConfigFile()
|
|
{
|
|
// ###########################################################################
|
|
const TQString ConfigTemplateFile=locate("data", "kab/template.config");
|
|
kdDebug(KAB_KDEBUG_AREA)
|
|
<< "AddressBook::createConfigFile: config template file is \""
|
|
<< (const char*)ConfigTemplateFile.utf8() << "\"." << endl;
|
|
const TQString filename= locateLocal( "data", STD_CONFIGFILENAME);
|
|
QConfigDB db;
|
|
// -----
|
|
if(ConfigTemplateFile.isEmpty()
|
|
|| !db.setFileName(ConfigTemplateFile, true, true))
|
|
{
|
|
KMessageBox::error(this,
|
|
i18n("Cannot find kab's configuration template file.\n"
|
|
"kab cannot be configured."),
|
|
i18n("File Error"));
|
|
|
|
return InternError;
|
|
}
|
|
if(!db.load())
|
|
{
|
|
KMessageBox::error(this,
|
|
i18n("Cannot read kab's configuration template file.\n"
|
|
"kab cannot be configured."),
|
|
i18n("File Error"));
|
|
return InternError;
|
|
}
|
|
if(!db.setFileName(filename, false, false))
|
|
{
|
|
KMessageBox::error(this,
|
|
i18n("Cannot create the file\n\"")
|
|
+filename+"\"\n"+
|
|
i18n("Could not create the new configuration file."),
|
|
i18n("File Error"));
|
|
return PermDenied;
|
|
}
|
|
if(!db.save())
|
|
{
|
|
KMessageBox::error(this,
|
|
i18n("Cannot save the file\n\"")
|
|
+filename+"\"\n"+
|
|
i18n("Could not create the new configuration file."),
|
|
i18n("File Error"));
|
|
return InternError;
|
|
}
|
|
// -----
|
|
return NoError;
|
|
// ###########################################################################
|
|
}
|
|
|
|
AddressBook::ErrorCode
|
|
AddressBook::loadConfigFile()
|
|
{
|
|
// ###########################################################################
|
|
TQString file = locateLocal( "data", STD_CONFIGFILENAME);
|
|
if(config->setFileName(file, true, true))
|
|
{
|
|
if(config->load())
|
|
{
|
|
return NoError;
|
|
} else {
|
|
KMessageBox::information(this,
|
|
i18n("Cannot load kab's local configuration file.\n"
|
|
"There may be a formatting error.\n"
|
|
"kab cannot be configured."),
|
|
i18n("File Error"));
|
|
return InternError;
|
|
}
|
|
} else {
|
|
KMessageBox::information(this,
|
|
i18n("Cannot find kab's local configuration file.\n"
|
|
"kab cannot be configured."),
|
|
i18n("File Error"));
|
|
return NoSuchFile;
|
|
}
|
|
// ###########################################################################
|
|
}
|
|
|
|
AddressBook::ErrorCode
|
|
AddressBook::makeVCardFromEntry(const Entry&, const TQString&)
|
|
{
|
|
// ###########################################################################
|
|
return NotImplemented;
|
|
// ###########################################################################
|
|
}
|
|
|
|
AddressBook::ErrorCode
|
|
AddressBook::makeEntryFromVCard(const TQString&, Entry&)
|
|
{
|
|
// ###########################################################################
|
|
return NotImplemented;
|
|
// ###########################################################################
|
|
}
|
|
|
|
TQString
|
|
AddressBook::getStandardFileName()
|
|
{
|
|
// ###########################################################################
|
|
return locateLocal( "data", STD_USERFILENAME);
|
|
// ###########################################################################
|
|
}
|
|
|
|
TQString AddressBook::phoneType(AddressBook::Telephone phone)
|
|
{
|
|
switch(phone)
|
|
{
|
|
case Fixed: return i18n("fixed"); break;
|
|
case Mobile: return i18n("mobile"); break;
|
|
case Fax: return i18n("fax"); break;
|
|
case Modem: return i18n("modem"); break;
|
|
default: return i18n("general");
|
|
}
|
|
}
|
|
|
|
void AddressBook::externalChange()
|
|
{
|
|
updateMirrorMap();
|
|
}
|
|
|
|
Section* AddressBook::configurationSection()
|
|
{
|
|
Section *section;
|
|
if(data!=0)
|
|
{
|
|
if(data->get(LOCAL_CONFIG_SECTION, section))
|
|
{
|
|
return section;
|
|
} else {
|
|
return 0;
|
|
}
|
|
} else {
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
AddressBook::ErrorCode AddressBook::Entry::get(const char* fieldname, TQVariant& field)
|
|
{
|
|
// "title", "rank", "fn", "nameprefix", "firstname", "middlename", "lastname",
|
|
// "birthday", "comment", "talk", "emails", "keywords", "telephone",
|
|
// "urls", "user1", "user2", "user3", "user4", "custom"
|
|
int dummy=0;
|
|
// -----
|
|
if(fieldname==Fields[dummy++])
|
|
{ // the title
|
|
field=title;
|
|
return NoError;
|
|
}
|
|
if(fieldname==Fields[dummy++])
|
|
{ // the rank
|
|
field=rank;
|
|
return NoError;
|
|
}
|
|
if(fieldname==Fields[dummy++])
|
|
{ // the formatted name
|
|
field=fn;
|
|
return NoError;
|
|
}
|
|
if(fieldname==Fields[dummy++])
|
|
{ // the nameprefix
|
|
field=nameprefix;
|
|
return NoError;
|
|
}
|
|
if(fieldname==Fields[dummy++])
|
|
{ // the firstname
|
|
field=firstname;
|
|
return NoError;
|
|
}
|
|
if(fieldname==Fields[dummy++])
|
|
{ // the middle name
|
|
field=middlename;
|
|
return NoError;
|
|
}
|
|
if(fieldname==Fields[dummy++])
|
|
{ // the last name
|
|
field=lastname;
|
|
return NoError;
|
|
}
|
|
if(fieldname==Fields[dummy++])
|
|
{ // the birthday
|
|
field=TQString(birthday.toString());
|
|
return NoError;
|
|
}
|
|
if(fieldname==Fields[dummy++])
|
|
{ // the comment
|
|
field=comment;
|
|
return NoError;
|
|
}
|
|
if(fieldname==Fields[dummy++])
|
|
{ // the talk addresses
|
|
field=talk;
|
|
return NoError;
|
|
}
|
|
if(fieldname==Fields[dummy++])
|
|
{ // the email addresses
|
|
field=emails;
|
|
return NoError;
|
|
}
|
|
if(fieldname==Fields[dummy++])
|
|
{ // the keywords
|
|
field=keywords;
|
|
return NoError;
|
|
}
|
|
if(fieldname==Fields[dummy++])
|
|
{ // the telephones
|
|
field=telephone;
|
|
return NoError;
|
|
}
|
|
if(fieldname==Fields[dummy++])
|
|
{ // the urls
|
|
field=URLs;
|
|
return NoError;
|
|
}
|
|
if(fieldname==Fields[dummy++])
|
|
{ // the user field 1
|
|
field=user1;
|
|
return NoError;
|
|
}
|
|
if(fieldname==Fields[dummy++])
|
|
{ // the user field 2
|
|
field=user2;
|
|
return NoError;
|
|
}
|
|
if(fieldname==Fields[dummy++])
|
|
{ // the user field 3
|
|
field=user3;
|
|
return NoError;
|
|
}
|
|
if(fieldname==Fields[dummy++])
|
|
{ // the user field 4
|
|
field=user4;
|
|
return NoError;
|
|
}
|
|
if(fieldname==Fields[dummy++])
|
|
{ // the custom fields (app specific)
|
|
field=custom;
|
|
return NoError;
|
|
}
|
|
// ----- we did not find that field:
|
|
return NoSuchField;
|
|
}
|
|
|
|
AddressBook::ErrorCode AddressBook::Entry::Address::get(const char* fieldname,
|
|
TQVariant& field)
|
|
{
|
|
// "headline", "position",
|
|
// "org", "orgunit", "orgsubunit",
|
|
// "deliverylabel", "address", "zip", "town", "country", "state"
|
|
int dummy=0;
|
|
// -----
|
|
if(fieldname==Fields[dummy++])
|
|
{ // the headline
|
|
field=headline;
|
|
return NoError;
|
|
}
|
|
if(fieldname==Fields[dummy++])
|
|
{ // the position
|
|
field=position;
|
|
return NoError;
|
|
}
|
|
if(fieldname==Fields[dummy++])
|
|
{ // the organization
|
|
field=org;
|
|
return NoError;
|
|
}
|
|
if(fieldname==Fields[dummy++])
|
|
{ // the organizational unit
|
|
field=orgUnit;
|
|
return NoError;
|
|
}
|
|
if(fieldname==Fields[dummy++])
|
|
{ // the organizational subunit
|
|
field=orgSubUnit;
|
|
return NoError;
|
|
}
|
|
if(fieldname==Fields[dummy++])
|
|
{ // the delivery label
|
|
field=deliveryLabel;
|
|
return NoError;
|
|
}
|
|
if(fieldname==Fields[dummy++])
|
|
{ // the address
|
|
field=address;
|
|
return NoError;
|
|
}
|
|
if(fieldname==Fields[dummy++])
|
|
{ // the zip code
|
|
field=zip;
|
|
return NoError;
|
|
}
|
|
if(fieldname==Fields[dummy++])
|
|
{ // the town
|
|
field=town;
|
|
return NoError;
|
|
}
|
|
if(fieldname==Fields[dummy++])
|
|
{ // the country
|
|
field=country;
|
|
return NoError;
|
|
}
|
|
if(fieldname==Fields[dummy++])
|
|
{ // the state
|
|
field=state;
|
|
return NoError;
|
|
}
|
|
// ----- we did not find that field:
|
|
return NoSuchField;
|
|
}
|
|
|
|
Section* AddressBook::categoriesSection()
|
|
{
|
|
const TQString Predefines[]= {
|
|
i18n("Business"),
|
|
i18n("Private"),
|
|
i18n("Dates") };
|
|
size_t Size=sizeof(Predefines)/sizeof(Predefines[0]);
|
|
Section* section;
|
|
Section* categories;
|
|
KeyValueMap *keys;
|
|
// -----
|
|
if(data->get(KAB_CATEGORY_KEY, section))
|
|
{
|
|
// it exists, go ahead
|
|
return section;
|
|
} else {
|
|
kdDebug(KAB_KDEBUG_AREA)
|
|
<< "AddressBook::categoriesSection: creating categories structure." << endl;
|
|
// it does not exist - create it
|
|
if(!data->createSection(KAB_CATEGORY_KEY))
|
|
{
|
|
kdDebug(KAB_KDEBUG_AREA)
|
|
<< "AddressBook::categoriesSection: error creating categories section."
|
|
<< endl;
|
|
return 0;
|
|
}
|
|
data->get(KAB_CATEGORY_KEY, section);
|
|
// add the predefined categories:
|
|
categories=new Section;
|
|
keys=categories->getKeys();
|
|
for(size_t count=0; count<Size; ++count)
|
|
{
|
|
TQStringList values;
|
|
values.append(Predefines[count]);
|
|
keys->insert(TQCString().setNum(count), values);
|
|
}
|
|
section->add(KAB_CATEGORY_KEY, categories);
|
|
keys=section->getKeys();
|
|
keys->insert("NextAvailableCatKey", (long)Size);
|
|
}
|
|
save();
|
|
if(data->get(KAB_CATEGORY_KEY, section))
|
|
return section;
|
|
return 0; // might not happen
|
|
}
|
|
|
|
AddressBook::ErrorCode AddressBook::categories(CategoriesMap& cat)
|
|
{ // WORK_TO_DO: use a permanent cached map and update on changed()
|
|
kdDebug(KAB_KDEBUG_AREA, !cat.isEmpty())
|
|
<< "AddressBook::categories: warning - categories map is supposed to be empty!"
|
|
<< endl;
|
|
Section *section;
|
|
Section *categories;
|
|
KeyValueMap* keys;
|
|
int key;
|
|
bool rc;
|
|
TQStringList values;
|
|
StringStringMap::iterator pos;
|
|
// ----- query categories section:
|
|
section=categoriesSection();
|
|
TQ_CHECK_PTR(section);
|
|
// -----
|
|
if(!section->find(KAB_CATEGORY_KEY, categories))
|
|
{
|
|
kdDebug(KAB_KDEBUG_AREA)
|
|
<< "AddressBook::categories: error in database structure."
|
|
<< endl;
|
|
return InternError;
|
|
}
|
|
// ----- everything is set up, create the categories map:
|
|
// use an iterator to walk over all elements of categories key-value-map:
|
|
keys=categories->getKeys();
|
|
for(pos=keys->begin(); pos!=keys->end(); ++pos)
|
|
{
|
|
if(!keys->get((*pos).first, values))
|
|
{
|
|
kdDebug(KAB_KDEBUG_AREA)
|
|
<< "AddressBook::categories: internal error querying categories."
|
|
<< endl;
|
|
} else {
|
|
key=(*pos).first.toInt(&rc);
|
|
if(rc)
|
|
{
|
|
cat.insert(key, values[0]);
|
|
} else {
|
|
kdDebug(KAB_KDEBUG_AREA)
|
|
<< "AddressBook::categories: error - non-integer category key - ignored."
|
|
<< endl;
|
|
}
|
|
}
|
|
}
|
|
return NoError;
|
|
}
|
|
|
|
#include "addressbook.moc"
|