kaddressbook Library API Documentation

gnokii_xxport.cpp

00001 /*
00002     This file is part of KAddressbook.
00003     Copyright (c) 2003 Helge Deller <deller@kde.org>
00004 
00005     This program is free software; you can redistribute it and/or modify
00006     it under the terms of the GNU General Public License as published by
00007     the Free Software Foundation; either version 2 of the License, or
00008     (at your option) any later version.
00009 
00010     This program is distributed in the hope that it will be useful,
00011     but WITHOUT ANY WARRANTY; without even the implied warranty of
00012     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
00013     GNU General Public License for more details.
00014 
00015     You should have received a copy of the GNU General Public License
00016     along with this program; if not, write to the Free Software
00017     Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
00018 
00019     As a special exception, permission is given to link this program
00020     with any edition of Qt, and distribute the resulting executable,
00021     without including the source code for Qt in the source distribution.
00022 */
00023 
00024 /* 
00025     Description:
00026     This filter allows you to import and export the KDE addressbook entries
00027     to/from a mobile phone, which is accessible via gnokii.
00028     Gnokii homepage: http://www.gnokii.org
00029 
00030     TODO:
00031     - modal mode (show dialog during up/download)
00032     - handle callergroup value (Friend, VIP, Family, ...) better
00033     - we do not yet write back to SIM memory (for security reasons)
00034 */
00035 
00036 #include "config.h"
00037 
00038 #include <kdebug.h>
00039 #include <klocale.h>
00040 #include <kmessagebox.h>
00041 
00042 #ifdef HAVE_GNOKII_H
00043 extern "C" {
00044 #include <gnokii.h>
00045 }
00046 #endif
00047 
00048 #include "gnokii_xxport.h"
00049 
00050 #define APP "GNOKII_XXPORT"
00051 
00052 #if 1 // !defined(NDEBUG)
00053  #define GNOKII_DEBUG(x)    do { kdWarning() << (x); } while (0)
00054 #else
00055  #define GNOKII_DEBUG(x)    do { } while (0)
00056 #endif
00057 #define GNOKII_CHECK_ERROR(error) \
00058     do { \
00059         if (error) \
00060             kdError() << QString("ERROR %1: %2\n").arg(error).arg(gn_error_print(error));\
00061     } while (0)
00062 
00063 
00064 class GNOKIIXXPortFactory : public KAB::XXPortFactory
00065 {
00066   public:
00067     KAB::XXPort *xxportObject( KABC::AddressBook *ab, QWidget *parent, const char *name )
00068     {
00069       return new GNOKIIXXPort( ab, parent, name );
00070     }
00071 };
00072 
00073 extern "C"
00074 {
00075   void *init_libkaddrbk_gnokii_xxport()
00076   {
00077     return ( new GNOKIIXXPortFactory() );
00078   }
00079 }
00080 
00081 
00082 GNOKIIXXPort::GNOKIIXXPort( KABC::AddressBook *ab, QWidget *parent, const char *name )
00083   : KAB::XXPort( ab, parent, name )
00084 {
00085     createImportAction( i18n( "Import From Nokia Mobile Phone..." ) );
00086     createExportAction( i18n( "Export to Nokia Mobile Phone..." ) );
00087 }
00088 
00089 /* import */
00090 
00091 #ifdef HAVE_GNOKII_H
00092 static char *BinDir;
00093 static char *lockfile = NULL;
00094 static char model[GN_MODEL_MAX_LENGTH+1], revision[GN_REVISION_MAX_LENGTH+1], imei[GN_IMEI_MAX_LENGTH+1];
00095 static QString PhoneProductId;
00096 
00097 static struct gn_statemachine state;
00098 static gn_data data;
00099 
00100 static void busterminate(void)
00101 {
00102     gn_sm_functions(GN_OP_Terminate, NULL, &state);
00103     if (lockfile) gn_device_unlock(lockfile);
00104 }
00105 
00106 static QString businit(void)
00107 {
00108     gn_error error;
00109     char *aux;
00110 
00111     if (gn_cfg_read(&BinDir)<0 || !gn_cfg_phone_load("", &state))
00112         return i18n("GNOKII isn't yet configured.");
00113 
00114     gn_data_clear(&data);
00115 
00116     aux = gn_cfg_get(gn_cfg_info, "global", "use_locking");
00117     // Defaults to 'no'
00118     if (aux && !strcmp(aux, "yes")) {
00119         lockfile = gn_device_lock(state.config.port_device);
00120         if (lockfile == NULL) {
00121             return i18n("Lock file error.\n "
00122             "Please exit all other running instances of gnokii and try again.");
00123         }
00124     }
00125 
00126     // Initialise the code for the GSM interface.
00127     int old_dcd = state.config.require_dcd; // work-around for older gnokii versions
00128     state.config.require_dcd = false;
00129     error = gn_gsm_initialise(&state);
00130     GNOKII_CHECK_ERROR(error);
00131     state.config.require_dcd = old_dcd;
00132     if (error != GN_ERR_NONE) {
00133         busterminate();
00134         return i18n("Mobile phone interface initialization failed:\n%1").arg(gn_error_print(error));
00135     }
00136 
00137     // model
00138     gn_data_clear(&data);
00139     data.model = model;
00140     model[0] = 0;
00141     error = gn_sm_functions(GN_OP_GetModel, &data, &state);
00142     GNOKII_CHECK_ERROR(error);
00143     if (model[0] == 0)
00144         strcpy(model, i18n("unknown").utf8());
00145     data.model = NULL;
00146 
00147     // revision
00148     data.revision = revision;
00149     revision[0] = 0;
00150     error = gn_sm_functions(GN_OP_GetRevision, &data, &state);
00151     GNOKII_CHECK_ERROR(error);
00152     data.revision = NULL;
00153 
00154     // imei 
00155     data.imei = imei;
00156     imei[0] = 0;
00157     error = gn_sm_functions(GN_OP_GetImei, &data, &state);
00158     GNOKII_CHECK_ERROR(error);
00159     data.imei = NULL;
00160 
00161     GNOKII_DEBUG( QString("Found mobile phone: Model: %1, Revision: %2, IMEI: %3\n")
00162                 .arg(model).arg(revision).arg(imei) ); 
00163 
00164     PhoneProductId = QString("%1-%2-%3-%4").arg(APP).arg(model).arg(revision).arg(imei);
00165 
00166     return QString::null;
00167 }
00168 
00169 
00170 // get number of entries in this phone memory type (internal/SIM-card)
00171 static gn_error read_phone_memstat( gn_memory_type memtype, gn_memory_status *memstat )
00172 {
00173     gn_error error;
00174 
00175     gn_data_clear(&data);
00176     memset(memstat, 0, sizeof(*memstat));
00177     memstat->memory_type = memtype;
00178     data.memory_status = memstat;
00179     error = gn_sm_functions(GN_OP_GetMemoryStatus, &data, &state);
00180     GNOKII_CHECK_ERROR(error);
00181     if (error != GN_ERR_NONE) {
00182         switch (memtype) {
00183           case GN_MT_SM:
00184             // use at least 100 entries
00185             memstat->used = 0;
00186             memstat->free = 100;
00187             break;
00188           default:
00189           case GN_MT_ME:
00190             // Phone doesn't support ME (5110)
00191             memstat->used = memstat->free = 0;
00192             break;
00193         }
00194     }
00195     GNOKII_DEBUG( QString("\n\nMobile phone memory status: Type: %1, used=%2, free=%3, total=%4\n\n")
00196                     .arg(memtype).arg(memstat->used).arg(memstat->free).arg(memstat->used+memstat->free) );
00197     return error;
00198 }
00199 
00200 
00201 // read phone entry #index from memory #memtype
00202 static gn_error read_phone_entry( int index, gn_memory_type memtype, gn_phonebook_entry *entry )
00203 {
00204     gn_error error;
00205     entry->memory_type = memtype;
00206     entry->location = index;
00207     data.phonebook_entry = entry;
00208     error = gn_sm_functions(GN_OP_ReadPhonebook, &data, &state);
00209     GNOKII_CHECK_ERROR(error);
00210     return error;
00211 }
00212 
00213 static bool phone_entry_empty( int index, gn_memory_type memtype )
00214 {
00215     gn_phonebook_entry entry;
00216     gn_error error;
00217     error = read_phone_entry( index, memtype, &entry );
00218     if (error == GN_ERR_EMPTYLOCATION)
00219         return true;
00220     if (error == GN_ERR_NONE && entry.empty)
00221         return true;
00222     return false;
00223 }
00224 
00225 // read and evaluate all phone entries
00226 static gn_error read_phone_entries( const char *memtypestr, gn_memory_type memtype, KABC::AddresseeList *addrList )
00227 {
00228   gn_error error;
00229   
00230   // get number of entries in this phone memory type (internal/SIM-card)
00231   gn_memory_status memstat;
00232   error = read_phone_memstat(memtype, &memstat);
00233 
00234   gn_phonebook_entry entry;
00235   QStringList addrlist;
00236   KABC::Address *addr;
00237   QString s, country;
00238 
00239   int num_read = 0;
00240 
00241   for (int i = 1; i <= (memstat.used + memstat.free); i++) {
00242     error = read_phone_entry( i, memtype, &entry );
00243 
00244     if (error == GN_ERR_EMPTYLOCATION)
00245         continue;
00246     if (error == GN_ERR_INVALIDLOCATION)
00247         break;
00248     if (error == GN_ERR_INVALIDMEMORYTYPE)
00249         break;
00250     if (error == GN_ERR_NONE) {
00251         GNOKII_DEBUG(QString("%1: %2, num=%3, location=%4, group=%5, count=%6\n").arg(i).arg(entry.name)
00252             .arg(entry.number).arg(entry.location).arg(entry.caller_group).arg(entry.subentries_count));
00253         KABC::Addressee *a = new KABC::Addressee();
00254         
00255         // try to split Name into FamilyName and GivenName
00256         s = QString(entry.name).simplifyWhiteSpace();
00257         if (s.find(',')!=-1) {
00258           addrlist = QStringList::split(',', s);
00259           if (addrlist.count()==2) {
00260             a->setFamilyName(addrlist[0]);
00261             a->setGivenName(addrlist[1]);
00262           } else
00263             a->setGivenName(s);
00264         } else {
00265           addrlist = QStringList::split(' ', s);
00266           if (addrlist.count()>=2) {
00267             a->setFamilyName(addrlist[0]);
00268             addrlist.remove(addrlist.first());
00269             a->setGivenName(addrlist.join(" "));
00270           } else
00271             a->setGivenName(s);
00272         }
00273 
00274         a->insertCustom(APP, "X_GSM_CALLERGROUP", s.setNum(entry.caller_group));
00275         a->insertCustom(APP, "X_GSM_STORE_AT", QString("%1%2").arg(memtypestr).arg(entry.location));
00276 
00277         // set ProductId
00278         a->setProductId(PhoneProductId);
00279 
00280         // evaluate timestamp (ignore timezone)
00281         QDateTime datetime;
00282         if (entry.date.year<1998)
00283             datetime = QDateTime::currentDateTime();
00284         else
00285             datetime = QDateTime( QDate(entry.date.year, entry.date.month, entry.date.day), 
00286                               QTime(entry.date.hour, entry.date.minute, entry.date.second) );
00287         GNOKII_DEBUG(QString(" date=%1\n").arg(datetime.toString()));
00288         a->setRevision(datetime);
00289 
00290         if (!entry.subentries_count)
00291           a->insertPhoneNumber(KABC::PhoneNumber(entry.number, KABC::PhoneNumber::Work | KABC::PhoneNumber::Pref));
00292 
00293         /* scan sub-entries */
00294         if (entry.subentries_count)
00295          for (int n=0; n<entry.subentries_count; n++) {
00296           QString s = QString(entry.subentries[n].data.number).simplifyWhiteSpace();
00297           GNOKII_DEBUG(QString(" Subentry#%1, entry_type=%2, number_type=%3, number=%4\n")
00298                 .arg(n).arg(entry.subentries[n].entry_type)
00299                 .arg(entry.subentries[n].number_type).arg(s));
00300           if (s.isEmpty())
00301             continue;
00302           switch(entry.subentries[n].entry_type) {
00303            case GN_PHONEBOOK_ENTRY_Name:
00304             a->setName(s);
00305             break;
00306            case GN_PHONEBOOK_ENTRY_Email:
00307             a->insertEmail(s);
00308             break;
00309            case GN_PHONEBOOK_ENTRY_Postal:
00310             s = s.simplifyWhiteSpace();
00311             addrlist = QStringList::split(';', s, true);
00312             addr = new KABC::Address(KABC::Address::Work);
00313             if (addrlist.count() <= 1 ) {
00314                 addr->setExtended(s);
00315             } else {
00316                 addr->setPostOfficeBox(addrlist[0]);
00317                 addr->setExtended(addrlist[1]);
00318                 addr->setStreet(addrlist[2]);
00319                 addr->setLocality(addrlist[3]);
00320                 addr->setRegion(addrlist[4]);
00321                 addr->setPostalCode(addrlist[5]);
00322                 country = addrlist[6];
00323                 if (!country.isEmpty())
00324                     addr->setCountry(i18n(country.utf8()));
00325             }
00326             a->insertAddress(*addr);
00327             delete addr;
00328             break;
00329            case GN_PHONEBOOK_ENTRY_Note:
00330             if (!a->note().isEmpty())
00331                 s = "\n" + s;
00332             a->setNote(a->note()+s);
00333             break;
00334            case GN_PHONEBOOK_ENTRY_Number:
00335             enum KABC::PhoneNumber::Types phonetype;
00336             switch (entry.subentries[n].number_type) {
00337              case GN_PHONEBOOK_NUMBER_Mobile: phonetype = KABC::PhoneNumber::Cell; break;
00338              case GN_PHONEBOOK_NUMBER_Fax:    phonetype = KABC::PhoneNumber::Fax;  break;
00339              case GN_PHONEBOOK_NUMBER_General:
00340              case GN_PHONEBOOK_NUMBER_Work:   phonetype = KABC::PhoneNumber::Work; break;
00341              default:
00342              case GN_PHONEBOOK_NUMBER_Home:   phonetype = KABC::PhoneNumber::Home; break;
00343             }
00344             //if (s == entry.number)
00345             //  type = (KABC::PhoneNumber::Types) (phonetype | KABC::PhoneNumber::Pref);
00346             a->insertPhoneNumber(KABC::PhoneNumber(s, phonetype));
00347             break;
00348            case GN_PHONEBOOK_ENTRY_URL:
00349             a->setUrl(s);
00350             break;
00351            case GN_PHONEBOOK_ENTRY_Group:
00352             a->insertCategory(s);
00353             break;
00354            default:
00355             GNOKII_DEBUG(QString(" Not handled id=%1, entry=%2\n")
00356                 .arg(entry.subentries[n].entry_type).arg(s));
00357             break;
00358           } // switch()
00359         } // if(subentry)
00360 
00361         // add only if entry was valid
00362         if (strlen(entry.name) || strlen(entry.number) || entry.subentries_count)
00363             addrList->append(*a);
00364 
00365         // did we read all valid phonebook-entries ?
00366         num_read++;
00367         delete a;
00368         if (num_read >= memstat.used)
00369             break;  // yes, all were read
00370         else
00371             continue; // no, we are still missing some.
00372     }
00373     GNOKII_CHECK_ERROR(error);
00374   }
00375 
00376   return GN_ERR_NONE;
00377 }
00378 #endif
00379 
00380 
00381 
00382 KABC::AddresseeList GNOKIIXXPort::importContacts( const QString& ) const
00383 {
00384     KABC::AddresseeList addrList;
00385 
00386 #ifndef HAVE_GNOKII_H
00387 
00388     KMessageBox::error(parentWidget(), i18n("Gnokii interface is not available.\n"
00389         "Please ask your distributor to add gnokii during compile time."));
00390 
00391 #else
00392 
00393     QString errStr = businit();
00394     if (!errStr.isEmpty()) {
00395         KMessageBox::error(parentWidget(), errStr);
00396         return addrList;
00397     }
00398 
00399     GNOKII_DEBUG("GNOKII import filter started.\n");
00400   
00401     read_phone_entries("ME", GN_MT_ME, &addrList); // internal phone memory
00402     read_phone_entries("SM", GN_MT_SM, &addrList); // SIM card
00403 
00404     GNOKII_DEBUG("GNOKII import filter finished.\n");
00405 
00406     busterminate();
00407 
00408 #endif
00409 
00410     return addrList;
00411 }
00412 
00413 
00414 // export to phone
00415 
00416 #ifdef HAVE_GNOKII_H
00417 
00418 static QString makeValidPhone( const QString &number )
00419 {
00420     // allowed chars: 0-9, *, #, p, w, +
00421     QString num = number.simplifyWhiteSpace();
00422     QString allowed("+0123456789*#pw");
00423     for (unsigned int i=num.length(); i>=1; i--) 
00424         if (allowed.find(num[i-1])==-1)
00425             num.remove(i-1,1);
00426     if (num.isEmpty())
00427         num = "0";
00428     return num;
00429 }
00430 
00431 static gn_error xxport_phone_write_entry( int phone_location, gn_memory_type memtype, 
00432             const KABC::Addressee *addr)
00433 {
00434     gn_phonebook_entry entry;
00435     QString s;
00436 
00437     memset(&entry, 0, sizeof(entry));
00438     strncpy(entry.name, addr->realName().latin1(), sizeof(entry.name)-1);
00439     s = addr->phoneNumber(KABC::PhoneNumber::Pref).number();
00440     if (s.isEmpty())
00441         s = addr->phoneNumber(KABC::PhoneNumber::Work).number();
00442     if (s.isEmpty())
00443         s = addr->phoneNumber(KABC::PhoneNumber::Home).number();
00444     if (s.isEmpty())
00445         s = addr->phoneNumber(KABC::PhoneNumber::Cell).number();
00446     if (s.isEmpty() && addr->phoneNumbers().count()>0)
00447         s = (*addr->phoneNumbers().at(0)).number();
00448     s = makeValidPhone(s);
00449     strncpy(entry.number, s.latin1(), sizeof(entry.number)-1);
00450     entry.memory_type = memtype;
00451     QString cg = addr->custom(APP, "X_GSM_CALLERGROUP");
00452     if (cg.isEmpty())
00453         entry.caller_group = 5;     // default group
00454     else
00455         entry.caller_group = cg.toInt();
00456     entry.location = phone_location;
00457     
00458     // set date/revision
00459     QDateTime datetime = addr->revision();
00460     QDate date(datetime.date());
00461     QTime time(datetime.time());
00462     entry.date.year = date.year();
00463     entry.date.month = date.month();
00464     entry.date.day = date.day();
00465     entry.date.hour = time.hour();
00466     entry.date.minute = time.minute();
00467     entry.date.second = time.second();
00468 
00469     GNOKII_DEBUG(QString("Write #%1: name=%2, number=%3\n").arg(phone_location)
00470                     .arg(entry.name).arg(entry.number));
00471 
00472     const KABC::Address homeAddr = addr->address(KABC::Address::Home);
00473     const KABC::Address workAddr = addr->address(KABC::Address::Work);
00474 
00475     entry.subentries_count = 0;
00476     gn_phonebook_subentry *subentry = &entry.subentries[0];
00477     // add all phone numbers
00478     const KABC::PhoneNumber::List phoneList = addr->phoneNumbers();
00479     KABC::PhoneNumber::List::ConstIterator it;
00480     for ( it = phoneList.begin(); it != phoneList.end(); ++it ) {
00481         const KABC::PhoneNumber *phonenumber = &(*it);
00482         s = phonenumber->number();
00483         if (s.isEmpty()) continue;
00484         subentry->entry_type  = GN_PHONEBOOK_ENTRY_Number;
00485         gn_phonebook_number_type type;
00486         switch (phonenumber->type() & ~KABC::PhoneNumber::Pref) {
00487             case KABC::PhoneNumber::Home:   type = GN_PHONEBOOK_NUMBER_Home;    break;
00488             case KABC::PhoneNumber::Voice:
00489             case KABC::PhoneNumber::Work:   type = GN_PHONEBOOK_NUMBER_Work;    break;
00490             case KABC::PhoneNumber::Pager:
00491             case KABC::PhoneNumber::Cell:   type = GN_PHONEBOOK_NUMBER_Mobile;  break;
00492             case KABC::PhoneNumber::Fax:    type = GN_PHONEBOOK_NUMBER_Fax;     break;
00493             default:            type = GN_PHONEBOOK_NUMBER_General; break;
00494         }
00495         subentry->number_type = type;
00496         strncpy(subentry->data.number, makeValidPhone(s).latin1(), sizeof(subentry->data.number)-1);
00497         subentry->id = phone_location<<8+entry.subentries_count;
00498         entry.subentries_count++;
00499         subentry++;
00500         if (entry.subentries_count >= GN_PHONEBOOK_SUBENTRIES_MAX_NUMBER)
00501             break; // Phonebook full
00502     }
00503     // add URL
00504     s = addr->url().prettyURL();
00505     if (!s.isEmpty() && (entry.subentries_count<GN_PHONEBOOK_SUBENTRIES_MAX_NUMBER)) {
00506         subentry->entry_type = GN_PHONEBOOK_ENTRY_URL;
00507         strncpy(subentry->data.number, s.latin1(), sizeof(subentry->data.number)-1);
00508         entry.subentries_count++;
00509         subentry++;
00510     }
00511     // add E-Mails
00512     QStringList emails = addr->emails();
00513     for (unsigned int n=0; n<emails.count(); n++) {
00514         if (entry.subentries_count >= GN_PHONEBOOK_SUBENTRIES_MAX_NUMBER)
00515             break; // Phonebook full
00516         s = emails[n].simplifyWhiteSpace();
00517         if (s.isEmpty()) continue;
00518         subentry->entry_type  = GN_PHONEBOOK_ENTRY_Email;
00519         strncpy(subentry->data.number, s.latin1(), sizeof(subentry->data.number)-1);
00520         entry.subentries_count++;
00521         subentry++;
00522     }
00523     // add Adresses
00524     const KABC::Address::List addresses = addr->addresses();
00525     KABC::Address::List::ConstIterator it2;
00526     for ( it2 = addresses.begin(); it2 != addresses.end(); ++it2 ) {
00527         if (entry.subentries_count >= GN_PHONEBOOK_SUBENTRIES_MAX_NUMBER)
00528             break; // Phonebook full
00529         const KABC::Address *Addr = &(*it2);
00530         if (Addr->isEmpty()) continue;
00531         subentry->entry_type  = GN_PHONEBOOK_ENTRY_Postal;
00532         QStringList a;
00533         QChar sem(';');
00534         QString sem_repl(QString::fromLatin1(","));
00535             a.append( Addr->postOfficeBox().replace( sem, sem_repl ) );
00536         a.append( Addr->extended()     .replace( sem, sem_repl ) );
00537         a.append( Addr->street()       .replace( sem, sem_repl ) );
00538         a.append( Addr->locality()     .replace( sem, sem_repl ) );
00539         a.append( Addr->region()       .replace( sem, sem_repl ) );
00540         a.append( Addr->postalCode()   .replace( sem, sem_repl ) );
00541         a.append( Addr->country()      .replace( sem, sem_repl ) );
00542         s = a.join(sem);
00543         strncpy(subentry->data.number, s.latin1(), sizeof(subentry->data.number)-1);
00544         entry.subentries_count++;
00545         subentry++;
00546     }
00547     // add Note
00548     s = addr->note().simplifyWhiteSpace();
00549     if (!s.isEmpty() && (entry.subentries_count<GN_PHONEBOOK_SUBENTRIES_MAX_NUMBER)) {
00550         subentry->entry_type = GN_PHONEBOOK_ENTRY_Note;
00551         strncpy(subentry->data.number, s.latin1(), sizeof(subentry->data.number)-1);
00552         entry.subentries_count++;
00553         subentry++;
00554     }
00555 
00556     // debug output
00557     for (int st=0; st<entry.subentries_count; st++) {
00558         gn_phonebook_subentry *subentry = &entry.subentries[st];
00559         GNOKII_DEBUG(QString(" SubTel #%1: entry_type=%2, number_type=%3, number=%4\n")
00560                         .arg(st).arg(subentry->entry_type)
00561                         .arg(subentry->number_type).arg(subentry->data.number));
00562     }
00563 
00564     data.phonebook_entry = &entry;
00565     gn_error error = gn_sm_functions(GN_OP_WritePhonebook, &data, &state);
00566     GNOKII_CHECK_ERROR(error);
00567 
00568     return error;
00569 }
00570 
00571 
00572 static gn_error xxport_phone_delete_entry( int phone_location, gn_memory_type memtype )
00573 {
00574     gn_phonebook_entry entry;
00575     memset(&entry, 0, sizeof(entry));
00576     entry.empty = 1;
00577     entry.memory_type = memtype;
00578     entry.location = phone_location;
00579     data.phonebook_entry = &entry;
00580     GNOKII_DEBUG(QString("Deleting entry %1\n").arg(phone_location));
00581     gn_error error = gn_sm_functions(GN_OP_WritePhonebook, &data, &state);
00582     GNOKII_CHECK_ERROR(error);
00583     return error;
00584 }
00585 
00586 #endif
00587 
00588 bool GNOKIIXXPort::exportContacts( const KABC::AddresseeList &list, const QString & )
00589 {
00590 #ifndef HAVE_GNOKII_H
00591 
00592     Q_UNUSED(list);
00593     KMessageBox::error(parentWidget(), i18n("Gnokii interface is not available.\n"
00594         "Please ask your distributor to add gnokii during compile time."));
00595 
00596 #else
00597 
00598     KABC::AddresseeList::ConstIterator it;
00599 
00600     gn_error error;
00601 
00602     QString errStr = businit();
00603     if (!errStr.isEmpty()) {
00604         KMessageBox::error(parentWidget(), errStr);
00605         return false;
00606     }
00607 
00608     GNOKII_DEBUG("GNOKII export filter started.\n");
00609 
00610     gn_memory_type memtype = GN_MT_ME;  // internal phone memory
00611 
00612     int phone_count;    // num entries in phone
00613     bool overwrite_phone_entries = false;
00614     int phone_entry_no;
00615     bool entry_empty;
00616 
00617     // get number of entries in this phone memory
00618     gn_memory_status memstat;
00619     error = read_phone_memstat(memtype, &memstat);
00620     if (error == GN_ERR_NONE) {
00621         GNOKII_DEBUG("Writing to internal phone memory.\n");
00622     } else {
00623         memtype = GN_MT_SM; // try SIM card instead
00624         error = read_phone_memstat(memtype, &memstat);
00625         if (error != GN_ERR_NONE)
00626             goto finish;
00627         GNOKII_DEBUG("Writing to SIM card memory.\n");
00628     }
00629     phone_count = memstat.used;
00630 
00631     if (memstat.free >= (int) list.count()) {
00632         if (KMessageBox::No == KMessageBox::questionYesNo(parentWidget(),
00633             i18n("The selected phonebook entries can either be added to the mobile phonebook or they "
00634                  "can replace existing phonebook entries.\n\n"
00635                  "Do you want to just add the new entries ?"),
00636             i18n("Export to mobile phone") ) )
00637             overwrite_phone_entries = true;
00638     }
00639     
00640     if (overwrite_phone_entries) {
00641       if (KMessageBox::Continue != KMessageBox::warningContinueCancel(parentWidget(),
00642             i18n("During the export now all your existing phonebook entries in the mobile phone "
00643                  "will be deleted and replaced with the new entries.\n"
00644                  "Do you really want to continue ?"),
00645             i18n("Export to mobile phone") ) )
00646         goto finish;
00647     }
00648 
00649     // Now run the loop...
00650     phone_entry_no = 1;
00651     for ( it = list.begin(); it != list.end(); ++it ) {
00652         const KABC::Addressee *addr = &(*it);
00653         if (addr->isEmpty())
00654             continue;
00655         // don't write back SIM-card entries !
00656         if (addr->custom(APP, "X_GSM_STORE_AT").startsWith("SM"))
00657             continue;
00658 
00659 try_next_phone_entry:
00660         // End of phone memory reached ?
00661         if (phone_entry_no > (memstat.used + memstat.free))
00662             break;
00663 
00664         GNOKII_DEBUG(QString("Try to write entry '%1' at phone_entry_no=%2, phone_count=%3\n")
00665                 .arg(addr->realName()).arg(phone_entry_no).arg(phone_count));
00666 
00667         error = GN_ERR_NONE;
00668 
00669         // is this phone entry empty ?
00670         entry_empty = phone_entry_empty(phone_entry_no, memtype);
00671         if (overwrite_phone_entries) {
00672             // overwrite this phonebook entry ...
00673             if (!entry_empty)
00674                 phone_count--;
00675             error = xxport_phone_write_entry( phone_entry_no, memtype, addr);
00676             phone_entry_no++;
00677         } else {
00678             // add this phonebook entry if possible ...
00679             if (entry_empty) {
00680                 error = xxport_phone_write_entry( phone_entry_no, memtype, addr);
00681                 phone_entry_no++;
00682             } else {
00683                 phone_entry_no++;
00684                 goto try_next_phone_entry;
00685             }
00686         }
00687 
00688         // break if we got an error on the first entry
00689         if (error != GN_ERR_NONE && it==list.begin())
00690             break;
00691 
00692     } // for()
00693 
00694     // if we wanted to overwrite all entries, make sure, that we also
00695     // delete all remaining entries in the mobile phone.
00696     while (overwrite_phone_entries && error==GN_ERR_NONE && phone_count>0) {
00697         if (phone_entry_no > (memstat.used + memstat.free))
00698             break;
00699         entry_empty = phone_entry_empty(phone_entry_no, memtype);
00700         if (!entry_empty) {
00701             error = xxport_phone_delete_entry(phone_entry_no, memtype);
00702             phone_count--;
00703         }
00704         phone_entry_no++;
00705     }
00706 
00707 finish:
00708     GNOKII_DEBUG("GNOKII export filter finished.\n");
00709 
00710     busterminate();
00711 
00712 #endif
00713 
00714     return true;
00715 }
00716 
00717 #include "gnokii_xxport.moc"
00718 /* vim: set sts=4 ts=4 sw=4: */
00719 
KDE Logo
This file is part of the documentation for kaddressbook Library Version 3.2.2.
Documentation copyright © 1996-2004 the KDE developers.
Generated on Sat May 1 11:38:51 2004 by doxygen 1.2.15 written by Dimitri van Heesch, © 1997-2003