/* This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. */ /* addressbook.cpp - This class gives function that interact with kaddressbook. begin: Fri 2004-07-23 copyright: (C) 2004 by John Tapsell email: john@geola.co.uk */ #include "addressbook.h" #include "../server.h" #include "../konversationapplication.h" #include "../konversationmainwindow.h" #include "../channel.h" #include #include #include #include #include #include #include namespace Konversation { AddressbookBase::AddressbookBase() { KABC::StdAddressBook::setAutomaticSave( false ); m_ticket=NULL; } AddressbookBase::~AddressbookBase() { } KABC::AddressBook *AddressbookBase::getAddressBook() { return addressBook; } KABC::Addressee AddressbookBase::getKABCAddresseeFromNick(const TQString &ircnick, const TQString &servername, const TQString &servergroup) { KABC::AddressBook::Iterator it; for( it = addressBook->begin(); it != addressBook->end(); ++it ) { if(hasNick(*it, ircnick, servername, servergroup)) return (*it); } return KABC::Addressee(); } KABC::Addressee AddressbookBase::getKABCAddresseeFromNick(const TQString &nick_server) { KABC::AddressBook::Iterator it; for( it = addressBook->begin(); it != addressBook->end(); ++it ) { if(hasNick(*it, nick_server)) return (*it); } return KABC::Addressee(); } bool AddressbookBase::hasNick(const KABC::Addressee &addressee, const TQString &ircnick, const TQString &servername, const TQString &servergroup) { TQString lnick = ircnick.lower(); TQString lnick_servername; TQString lnick_servergroup; if(!servername.isEmpty()) lnick_servername = lnick + TQChar(0xE120) + servername.lower(); if(!servergroup.isEmpty()) lnick_servergroup = lnick + TQChar(0xE120) + servergroup.lower(); TQString lit; TQStringList addresses = TQStringList::split( TQChar( 0xE000 ), addressee.custom("messaging/irc", "All") ); TQStringList::iterator end = addresses.end(); for ( TQStringList::iterator it = addresses.begin(); it != end; ++it ) { lit = (*it).lower(); if(lit == lnick || lit == lnick_servername || lit == lnick_servergroup) return true; } return false; } TQStringList AddressbookBase::allContactsNicksForServer(const TQString &servername, const TQString &servergroup) { TQStringList contacts; for( KABC::AddressBook::Iterator it = addressBook->begin(); it != addressBook->end(); ++it ) contacts += getNicks(*it, servername, servergroup); return contacts; } TQStringList AddressbookBase::getNicks(const KABC::Addressee &addressee, const TQString &servername, const TQString &servergroup) { TQStringList nicks; TQString lservername = servername.lower(); TQString lservergroup = servergroup.lower(); TQStringList addresses = TQStringList::split( TQChar( 0xE000 ), addressee.custom("messaging/irc", "All") ); TQStringList::iterator end = addresses.end(); for ( TQStringList::iterator it = addresses.begin(); it != end; ++it ) { if(!(*it).contains(TQChar( 0xE120))) nicks.append(*it); else { TQString it_server = (*it).section(TQChar( 0xE120), 0,0).lower(); if(it_server == lservername || it_server == lservergroup) nicks.append((*it).section(TQChar( 0xE120 ), 1,1)); } } return nicks; } bool AddressbookBase::hasNick(const KABC::Addressee &addressee, const TQString &nick_server) { TQString lnick_server = nick_server.lower(); TQStringList addresses = TQStringList::split( TQChar( 0xE000 ), addressee.custom("messaging/irc", "All") ); TQStringList::iterator end = addresses.end(); for ( TQStringList::iterator it = addresses.begin(); it != end; ++it ) { TQString it_server = (*it).section(TQChar( 0xE120), 0,0).lower(); if(it_server ==lnick_server) return true; } return false; } TQString AddressbookBase::getBestNick(const KABC::Addressee &addressee) { //Look for a nickinfo for this nick, and use that. That way we turn a nick that is online. NickInfoPtr nickInfo = getNickInfo(addressee); if(nickInfo) return nickInfo->getNickname(); //No online nickinfo - not connected to server maybe. just return the first nick. TQStringList addresses = TQStringList::split( TQChar( 0xE000 ), addressee.custom("messaging/irc", "All") ); if(!addresses.empty()) return addresses.first(); //No irc nicks- nothing left to try - return null return TQString(); } NickInfoPtr AddressbookBase::getNickInfo(const KABC::Addressee &addressee) { NickInfoPtr lastNickInfo; TQStringList addresses = TQStringList::split( TQChar( 0xE000 ), addressee.custom("messaging/irc", "All") ); TQStringList::iterator end = addresses.end(); for ( TQStringList::iterator it = addresses.begin(); it != end; ++it ) { TQString ircnick; TQString serverOrGroup; KonversationApplication::splitNick_Server(*it, ircnick, serverOrGroup); NickInfoPtr nickInfo = dynamic_cast(kapp)->getNickInfo(ircnick, serverOrGroup); if(nickInfo) { if(!nickInfo->isAway()) return nickInfo; //This nick is away. Keep looking, but use it if we can't find one that's on lastNickInfo = nickInfo; } } //Use a nick that's either away, or non-existant. return lastNickInfo; } bool AddressbookBase::hasAnyNicks(const KABC::Addressee &addressee) { return !addressee.custom("messaging/irc", "All").isEmpty(); } void AddressbookBase::unassociateNick(KABC::Addressee &addressee, const TQString &ircnick, const TQString &servername, const TQString &servergroup) { kdDebug() << "in unassociatenick for '" << ircnick << endl; if(ircnick.isEmpty()) return; TQString lnick = ircnick.lower(); TQString lnick_servername; TQString lnick_servergroup; if(!servername.isEmpty()) lnick_servername = lnick + TQChar(0xE120) + servername.lower(); if(!servergroup.isEmpty()) lnick_servergroup = lnick + TQChar(0xE120) + servergroup.lower(); //We should now have lnick = ircnick, and versions with servername and servergroup - // like johnflux, johnflux@freenode, or johnflux@irc.kde.org except with the unicode // separator char 0xe120 instead of the @ kdDebug() << "nick" << ircnick<< endl; bool changed = false; if(addressee.isEmpty()) { kdDebug() << "Ignoring unassociation command for empty addressee for nick " << ircnick << endl; } TQString lit; TQStringList addresses = TQStringList::split( TQChar( 0xE000 ), addressee.custom("messaging/irc", "All") ); TQStringList::iterator it = addresses.begin(); while(it != addresses.end()) { lit = (*it).lower(); if(lit == lnick || lit == lnick_servername || lit == lnick_servergroup) { changed = true; it = addresses.remove(it); } else { it++; } } if(!changed) return; //if(!getAndCheckTicket()) // return; TQString new_custom = addresses.join( TQChar( 0xE000 )); if(new_custom.isEmpty()) addressee.removeCustom("messaging/irc", "All"); else addressee.insertCustom("messaging/irc", "All", new_custom); addressBook->insertAddressee(addressee); //saveTicket(); } void AddressbookBase::focusAndShowErrorMessage(const TQString &errorMsg) { static_cast(kapp)->getMainWindow()->focusAndShowErrorMessage(errorMsg); } /**For a given contact, adds the ircnick if they don't already have it. If you pass an addressBook, the contact is inserted * if it has changed. */ void AddressbookBase::associateNick(KABC::Addressee &addressee, const TQString &ircnick, const TQString &servername, const TQString &servergroup) { //It's easiest to just remove it from the list if it's there already unassociateNick(addressee, ircnick, servername, servergroup); TQString nick_server = ircnick; if(!servergroup.isEmpty()) nick_server += TQChar(0xE120) + servergroup; else if(!servername.isEmpty()) nick_server += TQChar(0xE120) + servername; TQStringList addresses = TQStringList::split( TQChar( 0xE000 ), addressee.custom("messaging/irc", "All") ); //For sanity reasons, don't let the number of irc nicks go above 10. //To do this, just remove the irc nick at the end of the list. if(addresses.count() >= 10) addresses.pop_back(); addresses.append(nick_server); addressee.insertCustom("messaging/irc", "All", addresses.join( TQChar( 0xE000 ))); addressBook->insertAddressee(addressee); } /** This function associates the nick for a person, then iterates over all the contacts unassociating the nick from everyone else. It saves the addressses that have changed.*/ bool AddressbookBase::associateNickAndUnassociateFromEveryoneElse(KABC::Addressee &addressee, const TQString &ircnick, const TQString &servername, const TQString &servergroup) { for( KABC::AddressBook::Iterator it = addressBook->begin(); it != addressBook->end(); ++it ) if((*it).uid() != addressee.uid()) unassociateNick(*it, ircnick, servername, servergroup); associateNick(addressee, ircnick, servername, servergroup); return true;; } bool AddressbookBase::getAndCheckTicket() { if(m_ticket) { kdError() << "Internal error - getting new ticket without saving old" << endl; return false; } m_ticket = addressBook->requestSaveTicket(); if ( !m_ticket ) { kdError() << "Resource is locked by other application!" << endl; //emit error return false; } kdDebug() << "gotTicketSuccessfully" << endl; return true; } void AddressbookBase::releaseTicket() { addressBook->releaseSaveTicket(m_ticket); m_ticket = NULL; } bool AddressbookBase::saveTicket() { if(!addressBook->save( m_ticket) ) { kdError() << "Saving failed!" << endl; addressBook->releaseSaveTicket(m_ticket); m_ticket = NULL; return false; } kdDebug() << "saveTicket() was successful" << endl; m_ticket= NULL; emit addresseesChanged(); return true; } bool AddressbookBase::saveAddressbook() { if(m_ticket) { kdError() << "Internal error - getting new ticket without saving old" << endl; return false; } m_ticket = addressBook->requestSaveTicket(); if ( !m_ticket ) { kdError() << "Resource is locked by other application!" << endl; return false; } else { if ( !addressBook->save( m_ticket ) ) { kdError() << "Saving failed!" << endl; addressBook->releaseSaveTicket(m_ticket); m_ticket = NULL; return false; } } kdDebug() << "Save was successful" << endl; m_ticket = NULL; emit addresseesChanged(); return true; } bool AddressbookBase::saveAddressee(KABC::Addressee &addressee) { Q_ASSERT(&addressee); addressBook->insertAddressee(addressee); bool success = saveAddressbook(); if(success) emitContactPresenceChanged(addressee.uid(), presenceStatusByAddressee(addressee)); return success; } /** * Indicate the presence as a number. Checks all the nicks that that person has. * If we find them, return 4 (online). * If we are connected to any of the servers that they are on, and we don't find them, return 1 (offline) * If we find them, but they are set to away then return 3 (away) * If we are connected to none of the servers that they are on, return 0 (unknown) * @param addressee Addressbook contact you want to know of the presence of * @return 0 (unknown), 1 (offline), 3 (away), 4 (online) */ int AddressbookBase::presenceStatusByAddressee(const KABC::Addressee &addressee) { Q_ASSERT(&addressee); NickInfoPtr nickInfo = getNickInfo(addressee); if(!nickInfo) { if(hasAnyNicks(addressee)) return 1; //either offline, or we aren't on the same server. else return 0; //Not known to us } if(nickInfo->isAway()) return 3; return 4; } bool AddressbookBase::isOnline(KABC::Addressee &addressee) { return !!getNickInfo(addressee); } bool AddressbookBase::editAddressee(const TQString &uid) { Q_ASSERT(!uid.isEmpty()); //FIXME: This hack can be removed. I fixed the below mentioned bug in kde 3.4 cvs - 2005-01-02 // //Because of stupid bugs in kaddressbook, first load kaddressbook using startServiceByDesktopPath // then call it on the command line to actually put it in edit mode. This is stupid :( kapp->startServiceByDesktopName( "kaddressbook" ); TDEProcess *proc = new TDEProcess; *proc << "kaddressbook"; *proc << "--editor-only" << "--uid" << uid; kdDebug() << "running kaddressbook --editor-only --uid " << uid << endl; if(!proc->start()) { KMessageBox::error(0, i18n("Could not run your addressbook program (kaddressbook). This is most likely because it is not installed. Please install the 'tdepim' packages.")); return false; } return true; } bool AddressbookBase::sendEmail(const KABC::Addressee &addressee) { if(addressee.preferredEmail().isEmpty()) { KMessageBox::sorry(0, i18n("The contact that you have selected does not have an email address associated with them. "), i18n("Cannot Send Email")); return false; } return runEmailProgram(addressee.fullEmail()); } bool AddressbookBase::runEmailProgram(const TQString &mailtoaddress) { KRun *proc = new KRun(KURL(TQString("mailto:") + KStringHandler::from8Bit(mailtoaddress.ascii()))); kdDebug() << "Sending email to " << mailtoaddress << endl; if(proc->hasError()) { KMessageBox::error(0, i18n("Could not run your email program. This is possibly because one is not installed. To install the TDE email program (kmail) please install the 'tdepim' packages.")); return false; } return true; } bool AddressbookBase::sendEmail(const ChannelNickList &nickList) { if(nickList.isEmpty()) return false; TQString mailto; TQStringList nicksWithoutAddressee; TQStringList nicksWithoutEmails; TQStringList nicksWithEmails; for(ChannelNickList::ConstIterator it=nickList.begin();it!=nickList.end();++it) { NickInfoPtr nickInfo = (*it)->getNickInfo(); Q_ASSERT(nickInfo); if(!nickInfo) return false; KABC::Addressee addr = nickInfo->getAddressee(); if(addr.isEmpty()) { nicksWithoutAddressee.append(nickInfo->getNickname()); } else if(addr.preferredEmail().isEmpty()) { nicksWithoutEmails.append(nickInfo->getNickname()); } else { nicksWithEmails.append(nickInfo->getNickname()); if(!mailto.isEmpty()) mailto += ", "; mailto += addr.fullEmail(); } } if(!nicksWithoutAddressee.isEmpty() || !nicksWithoutEmails.isEmpty()) { TQString message; if(nicksWithoutEmails.isEmpty()) { if(nicksWithEmails.isEmpty()) { if(nicksWithoutAddressee.count() > 1) message = i18n("None of the contacts that you have selected were associated with an addressbook contacts. "); else message = i18n("The contact that you have selected is not associated with an addressbook contact. "); } else { if(nicksWithoutAddressee.count() > 1) message = i18n("Some of the contacts (%1) that you have selected are not associated with addressbook contacts. ").arg(nicksWithoutAddressee.join(", ")); else message = i18n("One of the contacts (%1) that you have selected is not associated with an addressbook contact. ").arg(nicksWithoutAddressee.join(", ")); } message += i18n("You can right click on a contact, and choose to edit the Addressbook Associations to link them to a contact in your addressbook."); } else if(nicksWithoutAddressee.isEmpty()) { if(nicksWithEmails.isEmpty()) { if(nicksWithoutEmails.count() > 1) message = i18n("None of the contacts that you have selected have an email address associated with them. "); else message = i18n("The contact that you have selected does not have an email address associated with them. "); } else { if(nicksWithoutEmails.count() > 1) message = i18n("Some of the contacts (%1) that you have selected do not have an email address associated with them. ").arg(nicksWithoutEmails.join(", ")); else message = i18n("One of the contacts (%1) that you have selected does not have an email address associated with them. ").arg(nicksWithoutEmails.join(", ")); } message += i18n("You can right click on a contact, and choose to edit the addressbook contact, adding an email for them."); } else { message = i18n("Some of the contacts (%1) that you have selected are not associated with addressbook contacts, and some of the contacts (%2) do not have an email address associated with them. ").arg(nicksWithoutAddressee.join(", ").arg(nicksWithoutEmails.join(", "))); message += i18n("You can right click on a contact, and choose to edit the Addressbook Associations to link them to a contact in your addressbook, and choose to edit the addressbook contact, adding an email for them."); } if(nicksWithEmails.isEmpty()) { KMessageBox::sorry(0, message, i18n("Cannot Send Email")); return false; } else { message += i18n("\nDo you want to send an email anyway to the nicks that do have an email address?"); int result = KMessageBox::questionYesNo(0, message, i18n("Send Email"), KGuiItem(i18n("&Send Email...")), KGuiItem(i18n("&Cancel"))); if(result == KMessageBox::No) { return false; } } } return runEmailProgram(mailto); } } // NAMESPACE #include "addressbook_base.moc"