00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033 #include "config.h"
00034
00035 #ifdef HAVE_GNOKII_H
00036 extern "C" {
00037 #include <gnokii.h>
00038 }
00039 #else
00040 #ifdef __GNUC__
00041 # warning "Please install gnokii (http://www.gnokii.org) development headers and libraries !"
00042 # warning "Please use at least version 0.6.13 or later of gnokii."
00043 #endif
00044 #endif
00045
00046 #include <tqcursor.h>
00047
00048 #include <kdebug.h>
00049 #include <tdelocale.h>
00050 #include <tdemessagebox.h>
00051 #include <kprogress.h>
00052 #include <kguiitem.h>
00053
00054 #include "gnokii_xxport.h"
00055
00056 #define APP "GNOKII_XXPORT"
00057
00058 #if 1 // !defined(NDEBUG)
00059 #define GNOKII_DEBUG(x) do { kdWarning() << (x); } while (0)
00060 #else
00061 #define GNOKII_DEBUG(x) do { } while (0)
00062 #endif
00063 #define GNOKII_CHECK_ERROR(error) \
00064 do { \
00065 if (error) \
00066 kdError() << TQString("ERROR %1: %2\n").arg(error).arg(gn_error_print(error));\
00067 } while (0)
00068
00069
00070
00071 #define GN_FROM(x) TQString::fromLocal8Bit(x)
00072 #define GN_TO(x) (x).local8Bit()
00073
00074
00075 static GNOKIIXXPort *this_filter;
00076 static KProgressDialog *m_progressDlg;
00077
00078 K_EXPORT_KADDRESSBOOK_XXFILTER( libkaddrbk_gnokii_xxport, GNOKIIXXPort )
00079
00080 GNOKIIXXPort::GNOKIIXXPort( TDEABC::AddressBook *ab, TQWidget *parent, const char *name )
00081 : KAB::XXPort( ab, parent, name )
00082 {
00083 this_filter = this;
00084 m_progressDlg = NULL;
00085 createImportAction( i18n( "Import From Mobile Phone..." ) );
00086 createExportAction( i18n( "Export to Mobile Phone..." ) );
00087 }
00088
00089
00090 #ifdef HAVE_GNOKII_H
00091 static TQString makeValidPhone( const TQString &number )
00092 {
00093
00094 TQString num = number.simplifyWhiteSpace();
00095 TQString allowed("0123456789*+#pw");
00096 for (unsigned int i=num.length(); i>=1; i--)
00097 if (allowed.find(num[i-1])==-1)
00098 num.remove(i-1,1);
00099 if (num.isEmpty())
00100 num = "0";
00101 return num;
00102 }
00103 #endif
00104
00105
00106
00107
00108
00109
00110
00111 #if defined(HAVE_GNOKII_H) && defined(LIBGNOKII_VERSION_MAJOR) && (LIBGNOKII_VERSION_MAJOR >= 3)
00112
00113
00114
00115 static const char *manufacturer, *model, *revision, *imei;
00116 static struct gn_statemachine *state;
00117
00118 static void busterminate(void)
00119 {
00120 gn_lib_phone_close(state);
00121 gn_lib_phoneprofile_free(&state);
00122 gn_lib_library_free();
00123 }
00124
00125 static TQString businit(void)
00126 {
00127 GNOKII_DEBUG( "Using new gnokii version." );
00128
00129 GNOKII_DEBUG( TQString("Compiled with libgnokii version 0x%1\n").arg(TQString::number(LIBGNOKII_VERSION,16)) );
00130 GNOKII_DEBUG( TQString("Using libgnokii runtime version 0x%1\n").arg(TQString::number(gn_lib_version(),16)) );
00131
00132 gn_error error = gn_lib_phoneprofile_load(NULL, &state);
00133 if (error)
00134 return i18n("Failed to initialize the gnokii library.");
00135
00136 error = gn_lib_phone_open( state );
00137 GNOKII_CHECK_ERROR(error);
00138 if (error != GN_ERR_NONE) {
00139 busterminate();
00140 return i18n("<qt><center>Mobile Phone interface initialization failed.<br><br>"
00141 "The returned error message was:<br><b>%1</b><br><br>"
00142 "You might try to run \"gnokii --identify\" on the command line to "
00143 "check any cable/transport issues and to verify if your gnokii "
00144 "configuration is correct.</center></qt>")
00145 .arg(gn_error_print(error));
00146 }
00147
00148
00149 manufacturer = gn_lib_get_phone_manufacturer(state);
00150 model = gn_lib_get_phone_model(state);
00151 revision = gn_lib_get_phone_revision(state);
00152 imei = gn_lib_get_phone_imei(state);
00153
00154 GNOKII_DEBUG( TQString("Found mobile phone: %1 %2, Revision: %3, IMEI: %4\n")
00155 .arg(manufacturer, model, revision, imei) );
00156
00157 return TQString();
00158 }
00159
00160
00161
00162 static gn_error read_phone_memstat( const gn_memory_type memtype, gn_memory_status *memstat )
00163 {
00164 gn_error error;
00165
00166 error = gn_lib_addressbook_memstat(state, memtype, &memstat->used, &memstat->free);
00167
00168 GNOKII_DEBUG( TQString("\n\nMobile phone memory status: Type: %1, used=%2, free=%3, total=%4\n\n")
00169 .arg(memtype).arg(memstat->used).arg(memstat->free).arg(memstat->used+memstat->free) );
00170 return error;
00171 }
00172
00173
00174 static TQString buildPhoneInfoString( const gn_memory_status &memstat )
00175 {
00176 TQString format = TQString::fromLatin1("<tr><td><b>%1</b></td><td>%2</td></tr>");
00177
00178 return TQString::fromLatin1("<b>%1</b><br><table>%2%3%4%5%6</table><br>")
00179 .arg(i18n("Mobile Phone information:"))
00180 .arg(format.arg(i18n("Manufacturer")).arg(GN_FROM(manufacturer)))
00181 .arg(format.arg(i18n("Phone model")).arg(GN_FROM(model)))
00182 .arg(format.arg(i18n("Revision")).arg(GN_FROM(revision)))
00183 .arg(format.arg(i18n("IMEI")).arg(GN_FROM(imei)))
00184 .arg(format.arg(i18n("Phonebook status"))
00185 .arg(i18n("%1 out of %2 contacts used").arg(memstat.used).arg(memstat.used+memstat.free)));
00186 }
00187
00188
00189 static gn_error read_phone_entries( const char *memtypestr, gn_memory_type memtype,
00190 TDEABC::AddresseeList *addrList )
00191 {
00192 gn_error error;
00193
00194 if (m_progressDlg->wasCancelled())
00195 return GN_ERR_NONE;
00196
00197 KProgress* progress = (KProgress*)m_progressDlg->progressBar();
00198
00199 progress->setProgress(0);
00200 this_filter->processEvents();
00201
00202
00203 gn_memory_status memstat;
00204 error = read_phone_memstat(memtype, &memstat);
00205
00206 TQStringList addrlist;
00207 TDEABC::Address *addr;
00208 TQString s, country;
00209
00210 progress->setTotalSteps(memstat.used);
00211 m_progressDlg->setLabel(i18n("<qt>Importing <b>%1</b> contacts from <b>%2</b> of the Mobile Phone.<br><br>%3</qt>")
00212 .arg(memstat.used)
00213 .arg(gn_memory_type2str(memtype))
00214 .arg(buildPhoneInfoString(memstat)) );
00215
00216 int num_read = 0;
00217
00218 for (int i = 1; !m_progressDlg->wasCancelled() && i <= memstat.used + memstat.free; i++) {
00219 error = gn_lib_phonebook_read_entry(state, memtype, i);
00220 GNOKII_CHECK_ERROR(error);
00221
00222 progress->setProgress(num_read);
00223 this_filter->processEvents();
00224
00225 if (error == GN_ERR_EMPTYLOCATION)
00226 continue;
00227 if (error == GN_ERR_INVALIDLOCATION)
00228 break;
00229 if (error == GN_ERR_INVALIDMEMORYTYPE)
00230 break;
00231 if (error == GN_ERR_NONE) {
00232 const int subentries_count = gn_lib_get_pb_num_subentries(state);
00233 const char *name = gn_lib_get_pb_name(state);
00234 const char *number = gn_lib_get_pb_number(state);
00235
00236 GNOKII_DEBUG(TQString("%1: %2, num=%3, location=%4, group=%5, count=%6\n").arg(i)
00237 .arg(GN_FROM(name)).arg(GN_FROM(number))
00238 .arg(gn_lib_get_pb_location(state)).arg(gn_lib_get_pb_caller_group(state))
00239 .arg(subentries_count));
00240 TDEABC::Addressee *a = new TDEABC::Addressee();
00241
00242
00243 s = GN_FROM(name).simplifyWhiteSpace();
00244 a->setFormattedName(s);
00245 if (s.find(',') == -1) {
00246
00247 addrlist = TQStringList::split(' ', s);
00248 if (addrlist.count() == 1) {
00249
00250 a->setGivenName(s);
00251 } else {
00252
00253 a->setFamilyName(addrlist.last().simplifyWhiteSpace());
00254 addrlist.remove(addrlist.last());
00255 a->setGivenName(addrlist.join(" ").simplifyWhiteSpace());
00256 }
00257 } else {
00258
00259 addrlist = TQStringList::split(',', s);
00260 a->setFamilyName(addrlist.first().simplifyWhiteSpace());
00261 addrlist.remove(addrlist.first());
00262 a->setGivenName(addrlist.join(" ").simplifyWhiteSpace());
00263 }
00264
00265 a->insertCustom(APP, "X_GSM_CALLERGROUP", s.setNum(gn_lib_get_pb_caller_group(state)));
00266 a->insertCustom(APP, "X_GSM_STORE_AT", TQString("%1%2").arg(memtypestr).arg(gn_lib_get_pb_location(state)));
00267
00268
00269 a->setProductId(TQString("%1-%2-%3-%4").arg(APP).arg(model).arg(revision).arg(imei));
00270
00271
00272 TQDateTime datetime;
00273 gn_timestamp ts = gn_lib_get_pb_date(state);
00274 if (ts.year<1998)
00275 datetime = TQDateTime::currentDateTime();
00276 else
00277 datetime = TQDateTime( TQDate(ts.year, ts.month, ts.day),
00278 TQTime(ts.hour, ts.minute, ts.second) );
00279 GNOKII_DEBUG(TQString(" date=%1\n").arg(datetime.toString()));
00280 a->setRevision(datetime);
00281
00282 if (!subentries_count)
00283 a->insertPhoneNumber(TDEABC::PhoneNumber(number,
00284 TDEABC::PhoneNumber::Work | TDEABC::PhoneNumber::Pref));
00285
00286
00287 if (subentries_count)
00288 for (int n=0; n<subentries_count; n++) {
00289 gn_phonebook_entry_type entry_type;
00290 gn_phonebook_number_type number_type;
00291 const char *number;
00292
00293 error = gn_lib_get_pb_subentry(state, n, &entry_type, &number_type, &number);
00294 GNOKII_CHECK_ERROR(error);
00295
00296 TQString s = GN_FROM(number).simplifyWhiteSpace();
00297 GNOKII_DEBUG(TQString(" Subentry#%1, entry_type=%2, number_type=%3, number=%4\n")
00298 .arg(n).arg(entry_type).arg(number_type).arg(s));
00299 if (s.isEmpty())
00300 continue;
00301 switch(entry_type) {
00302 case GN_PHONEBOOK_ENTRY_Name:
00303 a->setName(s);
00304 break;
00305 case GN_PHONEBOOK_ENTRY_Email:
00306 a->insertEmail(s);
00307 break;
00308 case GN_PHONEBOOK_ENTRY_Postal:
00309 addrlist = TQStringList::split(';', s, true);
00310 addr = new TDEABC::Address(TDEABC::Address::Work);
00311 if (addrlist.count() <= 1) {
00312 addrlist = TQStringList::split(',', s, true);
00313 if (addrlist.count() > 1 ) {
00314
00315 addr->setLocality(addrlist[0]);
00316 addr->setPostalCode(addrlist[1]);
00317 if (!addrlist[2].isEmpty())
00318 addr->setCountry(i18n(GN_TO(addrlist[2])));
00319 } else {
00320
00321 addr->setLocality(s);
00322 }
00323 } else {
00324
00325 addr->setPostOfficeBox(addrlist[0]);
00326 addr->setExtended(addrlist[1]);
00327 addr->setStreet(addrlist[2]);
00328 addr->setLocality(addrlist[3]);
00329 addr->setRegion(addrlist[4]);
00330 addr->setPostalCode(addrlist[5]);
00331 country = addrlist[6];
00332 if (!country.isEmpty())
00333 addr->setCountry(i18n(GN_TO(country)));
00334 }
00335 a->insertAddress(*addr);
00336 delete addr;
00337 break;
00338 case GN_PHONEBOOK_ENTRY_Note:
00339 if (!a->note().isEmpty())
00340 s = "\n" + s;
00341 a->setNote(a->note()+s);
00342 break;
00343 case GN_PHONEBOOK_ENTRY_Number:
00344 enum TDEABC::PhoneNumber::Types phonetype;
00345 switch (number_type) {
00346 case GN_PHONEBOOK_NUMBER_Mobile: phonetype = TDEABC::PhoneNumber::Cell; break;
00347 case GN_PHONEBOOK_NUMBER_Fax: phonetype = TDEABC::PhoneNumber::Fax; break;
00348 case GN_PHONEBOOK_NUMBER_General:
00349 case GN_PHONEBOOK_NUMBER_Work: phonetype = TDEABC::PhoneNumber::Work; break;
00350 default:
00351 case GN_PHONEBOOK_NUMBER_Home: phonetype = TDEABC::PhoneNumber::Home; break;
00352 }
00353
00354
00355 a->insertPhoneNumber(TDEABC::PhoneNumber(s, phonetype));
00356 break;
00357 case GN_PHONEBOOK_ENTRY_URL:
00358 a->setUrl(s);
00359 break;
00360 case GN_PHONEBOOK_ENTRY_Group:
00361 a->insertCategory(s);
00362 break;
00363 default:
00364 GNOKII_DEBUG(TQString(" Not handled id=%1, entry=%2\n")
00365 .arg(entry_type).arg(s));
00366 break;
00367 }
00368 }
00369
00370
00371 if (strlen(name) || strlen(number) || subentries_count)
00372 addrList->append(*a);
00373
00374
00375 num_read++;
00376 delete a;
00377 if (num_read >= memstat.used)
00378 break;
00379 else
00380 continue;
00381 }
00382 GNOKII_CHECK_ERROR(error);
00383 }
00384
00385 return GN_ERR_NONE;
00386 }
00387
00388
00389
00390 static gn_error xxport_phone_write_entry( int phone_location, gn_memory_type memtype,
00391 const TDEABC::Addressee *addr)
00392 {
00393 TQString s;
00394
00395
00396 gn_lib_phonebook_prepare_write_entry(state);
00397
00398 gn_lib_set_pb_location(state, phone_location);
00399
00400 gn_lib_set_pb_name(state, GN_TO(addr->realName()));
00401 s = addr->phoneNumber(TDEABC::PhoneNumber::Pref).number();
00402 if (s.isEmpty())
00403 s = addr->phoneNumber(TDEABC::PhoneNumber::Work).number();
00404 if (s.isEmpty())
00405 s = addr->phoneNumber(TDEABC::PhoneNumber::Home).number();
00406 if (s.isEmpty())
00407 s = addr->phoneNumber(TDEABC::PhoneNumber::Cell).number();
00408 if (s.isEmpty() && addr->phoneNumbers().count()>0)
00409 s = (*addr->phoneNumbers().at(0)).number();
00410 s = makeValidPhone(s);
00411 gn_lib_set_pb_number(state, s.ascii());
00412 gn_lib_set_pb_memtype(state, memtype);
00413 TQString cg = addr->custom(APP, "X_GSM_CALLERGROUP");
00414 if (cg.isEmpty())
00415 gn_lib_set_pb_caller_group(state, GN_PHONEBOOK_GROUP_None);
00416 else
00417 gn_lib_set_pb_caller_group(state, (gn_phonebook_group_type) cg.toInt());
00418
00419
00420 TQDateTime datetime = addr->revision();
00421 TQDate date(datetime.date());
00422 TQTime time(datetime.time());
00423 gn_timestamp ts;
00424 gn_timestamp_set( &ts, date.year(), date.month(), date.day(),
00425 time.hour(), time.minute(), time.second(), 0 );
00426 gn_lib_set_pb_date(state, ts);
00427
00428 GNOKII_DEBUG(TQString("Write #%1: name=%2, number=%3\n").arg(phone_location)
00429 .arg(GN_FROM(gn_lib_get_pb_name(state))).arg(GN_FROM(gn_lib_get_pb_number(state))));
00430
00431 const TDEABC::Address homeAddr = addr->address(TDEABC::Address::Home);
00432 const TDEABC::Address workAddr = addr->address(TDEABC::Address::Work);
00433
00434
00435 const TDEABC::PhoneNumber::List phoneList = addr->phoneNumbers();
00436 TDEABC::PhoneNumber::List::ConstIterator it;
00437 for ( it = phoneList.begin(); it != phoneList.end(); ++it ) {
00438 const TDEABC::PhoneNumber *phonenumber = &(*it);
00439 s = phonenumber->number();
00440 if (s.isEmpty()) continue;
00441 gn_phonebook_number_type type;
00442 int pn_type = phonenumber->type();
00443 if ((pn_type & TDEABC::PhoneNumber::Cell))
00444 type = GN_PHONEBOOK_NUMBER_Mobile;
00445 else if ((pn_type & TDEABC::PhoneNumber::Fax))
00446 type = GN_PHONEBOOK_NUMBER_Fax;
00447 else if ((pn_type & TDEABC::PhoneNumber::Home))
00448 type = GN_PHONEBOOK_NUMBER_Home;
00449 else if ((pn_type & TDEABC::PhoneNumber::Work))
00450 type = GN_PHONEBOOK_NUMBER_Work;
00451 else type = GN_PHONEBOOK_NUMBER_General;
00452 gn_lib_set_pb_subentry(state, -1 ,
00453 GN_PHONEBOOK_ENTRY_Number, type, makeValidPhone(s).ascii());
00454
00455 }
00456
00457 s = addr->url().prettyURL();
00458 if (!s.isEmpty()) {
00459 gn_lib_set_pb_subentry(state, -1 ,
00460 GN_PHONEBOOK_ENTRY_URL, GN_PHONEBOOK_NUMBER_General, GN_TO(s));
00461 }
00462
00463 TQStringList emails = addr->emails();
00464 for (unsigned int n=0; n<emails.count(); n++) {
00465 s = emails[n].simplifyWhiteSpace();
00466 if (s.isEmpty()) continue;
00467
00468 if (n && !addr->url().isEmpty() && !addr->note().isEmpty() && addr->addresses().count()) {
00469 GNOKII_DEBUG(TQString(" DROPPED email %1 in favor of URLs, notes and addresses.\n")
00470 .arg(s));
00471 continue;
00472 }
00473 gn_lib_set_pb_subentry(state, -1 ,
00474 GN_PHONEBOOK_ENTRY_Email, GN_PHONEBOOK_NUMBER_General, GN_TO(s));
00475 }
00476
00477 const TDEABC::Address::List addresses = addr->addresses();
00478 TDEABC::Address::List::ConstIterator it2;
00479 for ( it2 = addresses.begin(); it2 != addresses.end(); ++it2 ) {
00480 const TDEABC::Address *Addr = &(*it2);
00481 if (Addr->isEmpty()) continue;
00482 TQStringList a;
00483 TQChar sem(';');
00484 TQString sem_repl(TQString::fromLatin1(","));
00485 a.append( Addr->postOfficeBox().replace( sem, sem_repl ) );
00486 a.append( Addr->extended() .replace( sem, sem_repl ) );
00487 a.append( Addr->street() .replace( sem, sem_repl ) );
00488 a.append( Addr->locality() .replace( sem, sem_repl ) );
00489 a.append( Addr->region() .replace( sem, sem_repl ) );
00490 a.append( Addr->postalCode() .replace( sem, sem_repl ) );
00491 a.append( Addr->country() .replace( sem, sem_repl ) );
00492 s = a.join(sem);
00493 gn_lib_set_pb_subentry(state, -1 ,
00494 GN_PHONEBOOK_ENTRY_Postal, GN_PHONEBOOK_NUMBER_General, GN_TO(s));
00495 }
00496
00497 s = addr->note().simplifyWhiteSpace();
00498 if (!s.isEmpty()) {
00499 gn_lib_set_pb_subentry(state, -1 ,
00500 GN_PHONEBOOK_ENTRY_Note, GN_PHONEBOOK_NUMBER_General, GN_TO(s));
00501 }
00502
00503
00504 for (int st=0; st<gn_lib_get_pb_num_subentries(state); st++) {
00505 gn_phonebook_entry_type entry_type;
00506 gn_phonebook_number_type number_type;
00507 const char *number;
00508 gn_lib_get_pb_subentry(state, st, &entry_type, &number_type, &number);
00509 GNOKII_DEBUG(TQString(" SubTel #%1: entry_type=%2, number_type=%3, number=%4\n")
00510 .arg(st).arg(entry_type)
00511 .arg(number_type).arg(GN_FROM(number)));
00512 }
00513
00514 gn_error error = gn_lib_phonebook_write_entry(state, memtype, phone_location);
00515 GNOKII_CHECK_ERROR(error);
00516
00517 return error;
00518 }
00519
00520
00521 static gn_error xxport_phone_delete_entry( int phone_location, gn_memory_type memtype )
00522 {
00523 return gn_lib_phonebook_entry_delete(state, memtype, phone_location);
00524 }
00525
00526
00527 TDEABC::AddresseeList GNOKIIXXPort::importContacts( const TQString& ) const
00528 {
00529 TDEABC::AddresseeList addrList;
00530
00531 if (KMessageBox::Continue != KMessageBox::warningContinueCancel(parentWidget(),
00532 i18n("<qt>Please connect your Mobile Phone to your computer and press "
00533 "<b>Continue</b> to start importing the personal contacts.<br><br>"
00534 "Please note that if your Mobile Phone is not properly connected "
00535 "the following detection phase might take up to two minutes, during which "
00536 "KAddressbook will behave unresponsively.</qt>") ))
00537 return addrList;
00538
00539 m_progressDlg = new KProgressDialog( parentWidget(), "importwidget",
00540 i18n("Mobile Phone Import"),
00541 i18n("<qt><center>Establishing connection to the Mobile Phone.<br><br>"
00542 "Please wait...</center></qt>") );
00543 m_progressDlg->setAllowCancel(true);
00544 m_progressDlg->progressBar()->setProgress(0);
00545 m_progressDlg->progressBar()->setCenterIndicator(true);
00546 m_progressDlg->setModal(true);
00547 m_progressDlg->setInitialSize(TQSize(450,350));
00548 m_progressDlg->show();
00549 processEvents();
00550
00551 m_progressDlg->setCursor( TQt::BusyCursor );
00552 TQString errStr = businit();
00553 m_progressDlg->unsetCursor();
00554
00555 if (!errStr.isEmpty()) {
00556 KMessageBox::error(parentWidget(), errStr);
00557 delete m_progressDlg;
00558 return addrList;
00559 }
00560
00561 GNOKII_DEBUG("GNOKII import filter started.\n");
00562 m_progressDlg->setButtonText(i18n("&Stop Import"));
00563
00564 read_phone_entries("ME", GN_MT_ME, &addrList);
00565 read_phone_entries("SM", GN_MT_SM, &addrList);
00566
00567 GNOKII_DEBUG("GNOKII import filter finished.\n");
00568
00569 busterminate();
00570 delete m_progressDlg;
00571
00572 return addrList;
00573 }
00574
00575
00576 bool GNOKIIXXPort::exportContacts( const TDEABC::AddresseeList &list, const TQString & )
00577 {
00578 if (KMessageBox::Continue != KMessageBox::warningContinueCancel(parentWidget(),
00579 i18n("<qt>Please connect your Mobile Phone to your computer and press "
00580 "<b>Continue</b> to start exporting the selected personal contacts.<br><br>"
00581 "Please note that if your Mobile Phone is not properly connected "
00582 "the following detection phase might take up to two minutes, during which "
00583 "KAddressbook will behave unresponsively.</qt>") ))
00584 return false;
00585
00586 m_progressDlg = new KProgressDialog( parentWidget(), "importwidget",
00587 i18n("Mobile Phone Export"),
00588 i18n("<qt><center>Establishing connection to the Mobile Phone.<br><br>"
00589 "Please wait...</center></qt>") );
00590 m_progressDlg->setAllowCancel(true);
00591 m_progressDlg->progressBar()->setProgress(0);
00592 m_progressDlg->progressBar()->setCenterIndicator(true);
00593 m_progressDlg->setModal(true);
00594 m_progressDlg->setInitialSize(TQSize(450,350));
00595 m_progressDlg->show();
00596 processEvents();
00597
00598 KProgress* progress = (KProgress*)m_progressDlg->progressBar();
00599
00600 TDEABC::AddresseeList::ConstIterator it;
00601 TQStringList failedList;
00602
00603 gn_error error;
00604 bool deleteLabelInitialized = false;
00605
00606 m_progressDlg->setCursor( TQt::BusyCursor );
00607 TQString errStr = businit();
00608 m_progressDlg->unsetCursor();
00609
00610 if (!errStr.isEmpty()) {
00611 KMessageBox::error(parentWidget(), errStr);
00612 delete m_progressDlg;
00613 return false;
00614 }
00615
00616 GNOKII_DEBUG("GNOKII export filter started.\n");
00617
00618 gn_memory_type memtype = GN_MT_ME;
00619
00620 int phone_count;
00621 bool overwrite_phone_entries = false;
00622 int phone_entry_no, entries_written;
00623 bool entry_empty;
00624
00625
00626 gn_memory_status memstat;
00627 error = read_phone_memstat(memtype, &memstat);
00628 if (error == GN_ERR_NONE) {
00629 GNOKII_DEBUG("Writing to internal phone memory.\n");
00630 } else {
00631 memtype = GN_MT_SM;
00632 error = read_phone_memstat(memtype, &memstat);
00633 if (error != GN_ERR_NONE)
00634 goto finish;
00635 GNOKII_DEBUG("Writing to SIM card memory.\n");
00636 }
00637 phone_count = memstat.used;
00638
00639 if (memstat.free >= (int) list.count()) {
00640 if (KMessageBox::No == KMessageBox::questionYesNo(parentWidget(),
00641 i18n("<qt>Do you want the selected contacts to be <b>appended</b> to "
00642 "the current mobile phonebook or should they <b>replace</b> all "
00643 "currently existing phonebook entries ?<br><br>"
00644 "Please note, that in case you choose to replace the phonebook "
00645 "entries, every contact in your phone will be deleted and only "
00646 "the newly exported contacts will be available from inside your phone.</qt>"),
00647 i18n("Export to Mobile Phone"),
00648 KGuiItem(i18n("&Append to Current Phonebook")),
00649 KGuiItem(i18n("&Replace Current Phonebook with New Contacts")) ) )
00650 overwrite_phone_entries = true;
00651 }
00652
00653 progress->setTotalSteps(list.count());
00654 entries_written = 0;
00655 progress->setProgress(entries_written);
00656 m_progressDlg->setButtonText(i18n("&Stop Export"));
00657 m_progressDlg->setLabel(i18n("<qt>Exporting <b>%1</b> contacts to the <b>%2</b> "
00658 "of the Mobile Phone.<br><br>%3</qt>")
00659 .arg(list.count())
00660 .arg(gn_memory_type2str(memtype))
00661 .arg(buildPhoneInfoString(memstat)) );
00662
00663
00664 phone_entry_no = 1;
00665 for ( it = list.begin(); it != list.end(); ++it ) {
00666 const TDEABC::Addressee *addr = &(*it);
00667 if (addr->isEmpty())
00668 continue;
00669
00670 if (addr->custom(APP, "X_GSM_STORE_AT").startsWith("SM"))
00671 continue;
00672
00673 progress->setProgress(entries_written++);
00674
00675 try_next_phone_entry:
00676 this_filter->processEvents();
00677 if (m_progressDlg->wasCancelled())
00678 break;
00679
00680
00681 if (phone_entry_no > (memstat.used + memstat.free))
00682 break;
00683
00684 GNOKII_DEBUG(TQString("Try to write entry '%1' at phone_entry_no=%2, phone_count=%3\n")
00685 .arg(addr->realName()).arg(phone_entry_no).arg(phone_count));
00686
00687 error = GN_ERR_NONE;
00688
00689
00690 entry_empty = gn_lib_phonebook_entry_isempty(state, memtype, phone_entry_no);
00691 if (overwrite_phone_entries) {
00692
00693 if (!entry_empty)
00694 phone_count--;
00695 error = xxport_phone_write_entry( phone_entry_no, memtype, addr);
00696 phone_entry_no++;
00697 } else {
00698
00699 if (entry_empty) {
00700 error = xxport_phone_write_entry( phone_entry_no, memtype, addr);
00701 phone_entry_no++;
00702 } else {
00703 phone_entry_no++;
00704 goto try_next_phone_entry;
00705 }
00706 }
00707
00708 if (error != GN_ERR_NONE)
00709 failedList.append(addr->realName());
00710
00711
00712 if (error != GN_ERR_NONE && it==list.begin())
00713 break;
00714
00715 }
00716
00717
00718
00719 while (overwrite_phone_entries && error==GN_ERR_NONE && phone_count>0) {
00720 if (m_progressDlg->wasCancelled())
00721 break;
00722 if (!deleteLabelInitialized) {
00723 m_progressDlg->setLabel(
00724 i18n("<qt><center>"
00725 "All selected contacts have been sucessfully copied to "
00726 "the Mobile Phone.<br><br>"
00727 "Please wait until all remaining orphaned contacts from "
00728 "the Mobile Phone have been deleted.</center></qt>") );
00729 m_progressDlg->setButtonText(i18n("&Stop Delete"));
00730 deleteLabelInitialized = true;
00731 progress->setTotalSteps(phone_count);
00732 entries_written = 0;
00733 progress->setProgress(entries_written);
00734 this_filter->processEvents();
00735 }
00736 if (phone_entry_no > (memstat.used + memstat.free))
00737 break;
00738 entry_empty = gn_lib_phonebook_entry_isempty(state, memtype, phone_entry_no);
00739 if (!entry_empty) {
00740 error = xxport_phone_delete_entry(phone_entry_no, memtype);
00741 phone_count--;
00742 progress->setProgress(++entries_written);
00743 this_filter->processEvents();
00744 }
00745 phone_entry_no++;
00746 }
00747
00748 finish:
00749 m_progressDlg->setLabel(i18n("Export to phone finished."));
00750 this_filter->processEvents();
00751
00752 GNOKII_DEBUG("GNOKII export filter finished.\n");
00753
00754 busterminate();
00755 delete m_progressDlg;
00756
00757 if (!failedList.isEmpty()) {
00758 GNOKII_DEBUG(TQString("Failed to export: %1\n").arg(failedList.join(", ")));
00759 KMessageBox::informationList(parentWidget(),
00760 i18n("<qt>The following contacts could not be exported to the Mobile Phone. "
00761 "Possible Reasons for this problem could be:<br><ul>"
00762 "<li>The contacts contain more information per entry than the phone can store.</li>"
00763 "<li>Your phone does not allow to store multiple addresses, emails, homepages, ...</li>"
00764 "<li>other storage size related problems.</li>"
00765 "</ul>"
00766 "To avoid those kind of problems in the future please reduce the amount of different "
00767 "fields in the above contacts.</qt>"),
00768 failedList,
00769 i18n("Mobile Phone Export") );
00770 }
00771
00772
00773 return true;
00774 }
00775
00776
00777
00778
00779
00780
00781
00782 #elif defined(HAVE_GNOKII_H)
00783
00784 #ifdef __GNUC__
00785 # warning "Please upgrade your gnokii installation to at least version 0.6.13"
00786 # warning "Older gnokii versions below 0.6.13 are not binary compatible and"
00787 # warning "prevents TDE users to upgrade gnokii to newer versions later."
00788 #endif
00789
00790
00791
00792
00793 static char *lockfile = NULL;
00794 static char manufacturer[64], model[GN_MODEL_MAX_LENGTH+1],
00795 revision[GN_REVISION_MAX_LENGTH+1], imei[GN_IMEI_MAX_LENGTH+1];
00796 static TQString PhoneProductId;
00797
00798 static struct gn_statemachine state;
00799 static gn_data data;
00800
00801 static void busterminate(void)
00802 {
00803 gn_sm_functions(GN_OP_Terminate, NULL, &state);
00804 if (lockfile) gn_device_unlock(lockfile);
00805 }
00806
00807 static TQString businit(void)
00808 {
00809 gn_error error;
00810 char *aux;
00811
00812 GNOKII_DEBUG( "Using old gnokii version." );
00813
00814 #if defined(LIBGNOKII_VERSION)
00815 if (gn_cfg_read_default()<0)
00816 #else
00817 static char *BinDir;
00818 if (gn_cfg_read(&BinDir)<0)
00819 #endif
00820 return i18n("Failed to initialize the gnokii library.");
00821
00822 if (!gn_cfg_phone_load("", &state))
00823 return i18n("Gnokii is not yet configured.");
00824
00825
00826
00827
00828 gn_data_clear(&data);
00829
00830 aux = gn_cfg_get(gn_cfg_info, "global", "use_locking");
00831
00832 if (aux && !strcmp(aux, "yes")) {
00833 lockfile = gn_device_lock(state.config.port_device);
00834 if (lockfile == NULL) {
00835 return i18n("Gnokii reports a 'Lock File Error'.\n "
00836 "Please exit all other running instances of gnokii, check if you have "
00837 "write permissions in the /var/lock directory and try again.");
00838 }
00839 }
00840
00841
00842 int old_dcd = state.config.require_dcd;
00843 state.config.require_dcd = false;
00844 error = gn_gsm_initialise(&state);
00845 GNOKII_CHECK_ERROR(error);
00846 state.config.require_dcd = old_dcd;
00847 if (error != GN_ERR_NONE) {
00848 busterminate();
00849 return i18n("<qt><center>Mobile Phone interface initialization failed.<br><br>"
00850 "The returned error message was:<br><b>%1</b><br><br>"
00851 "You might try to run \"gnokii --identify\" on the command line to "
00852 "check any cable/transport issues and to verify if your gnokii "
00853 "configuration is correct.</center></qt>")
00854 .arg(gn_error_print(error));
00855 }
00856
00857
00858 gn_data_clear(&data);
00859 data.manufacturer = manufacturer;
00860 data.model = model;
00861 data.revision = revision;
00862 data.imei = imei;
00863
00864 TQCString unknown(GN_TO(i18n("Unknown")));
00865 tqstrncpy(manufacturer, unknown, sizeof(manufacturer)-1);
00866 tqstrncpy(model, unknown, sizeof(model)-1);
00867 tqstrncpy(revision, unknown, sizeof(revision)-1);
00868 tqstrncpy(imei, unknown, sizeof(imei)-1);
00869
00870 if (m_progressDlg->wasCancelled())
00871 return TQString();
00872 else
00873 error = gn_sm_functions(GN_OP_Identify, &data, &state);
00874 GNOKII_CHECK_ERROR(error);
00875
00876 GNOKII_DEBUG( TQString("Found mobile phone: %1 %2, Revision: %3, IMEI: %4\n")
00877 .arg(manufacturer, model, revision, imei) );
00878
00879 PhoneProductId = TQString("%1-%2-%3-%4").arg(APP).arg(model).arg(revision).arg(imei);
00880
00881 return TQString();
00882 }
00883
00884
00885
00886 static gn_error read_phone_memstat( const gn_memory_type memtype, gn_memory_status *memstat )
00887 {
00888 gn_error error;
00889
00890 gn_data_clear(&data);
00891 memset(memstat, 0, sizeof(*memstat));
00892 memstat->memory_type = memtype;
00893 data.memory_status = memstat;
00894 error = gn_sm_functions(GN_OP_GetMemoryStatus, &data, &state);
00895 GNOKII_CHECK_ERROR(error);
00896 if (error != GN_ERR_NONE) {
00897 switch (memtype) {
00898 case GN_MT_SM:
00899
00900 memstat->used = 0;
00901 memstat->free = 100;
00902 break;
00903 default:
00904 case GN_MT_ME:
00905
00906 memstat->used = memstat->free = 0;
00907 break;
00908 }
00909 }
00910 GNOKII_DEBUG( TQString("\n\nMobile phone memory status: Type: %1, used=%2, free=%3, total=%4\n\n")
00911 .arg(memtype).arg(memstat->used).arg(memstat->free).arg(memstat->used+memstat->free) );
00912 return error;
00913 }
00914
00915
00916
00917 static gn_error read_phone_entry( const int index, const gn_memory_type memtype, gn_phonebook_entry *entry )
00918 {
00919 gn_error error;
00920 entry->memory_type = memtype;
00921 entry->location = index;
00922 data.phonebook_entry = entry;
00923 error = gn_sm_functions(GN_OP_ReadPhonebook, &data, &state);
00924 GNOKII_CHECK_ERROR(error);
00925 return error;
00926 }
00927
00928 static bool phone_entry_empty( const int index, const gn_memory_type memtype )
00929 {
00930 gn_error error;
00931 gn_phonebook_entry entry;
00932 entry.memory_type = memtype;
00933 entry.location = index;
00934 data.phonebook_entry = &entry;
00935 error = gn_sm_functions(GN_OP_ReadPhonebook, &data, &state);
00936 if (error == GN_ERR_EMPTYLOCATION)
00937 return true;
00938 GNOKII_CHECK_ERROR(error);
00939 if (error == GN_ERR_NONE && entry.empty)
00940 return true;
00941 return false;
00942 }
00943
00944 static TQString buildPhoneInfoString( const gn_memory_status &memstat )
00945 {
00946 TQString format = TQString::fromLatin1("<tr><td><b>%1</b></td><td>%2</td></tr>");
00947
00948 return TQString::fromLatin1("<b>%1</b><br><table>%2%3%4%5%6</table><br>")
00949 .arg(i18n("Mobile Phone information:"))
00950 .arg(format.arg(i18n("Manufacturer")).arg(GN_FROM(manufacturer)))
00951 .arg(format.arg(i18n("Phone model")).arg(GN_FROM(model)))
00952 .arg(format.arg(i18n("Revision")).arg(GN_FROM(revision)))
00953 .arg(format.arg(i18n("IMEI")).arg(GN_FROM(imei)))
00954 .arg(format.arg(i18n("Phonebook status"))
00955 .arg(i18n("%1 out of %2 contacts used").arg(memstat.used).arg(memstat.used+memstat.free)));
00956 }
00957
00958 static TQString buildMemoryTypeString( gn_memory_type memtype )
00959 {
00960 switch (memtype) {
00961 case GN_MT_ME: return i18n("internal memory");
00962 case GN_MT_SM: return i18n("SIM-card memory");
00963 default: return i18n("unknown memory");
00964 }
00965 }
00966
00967
00968 static gn_error read_phone_entries( const char *memtypestr, gn_memory_type memtype,
00969 TDEABC::AddresseeList *addrList )
00970 {
00971 gn_error error;
00972
00973 if (m_progressDlg->wasCancelled())
00974 return GN_ERR_NONE;
00975
00976 KProgress* progress = (KProgress*)m_progressDlg->progressBar();
00977
00978 progress->setProgress(0);
00979 this_filter->processEvents();
00980
00981
00982 gn_memory_status memstat;
00983 error = read_phone_memstat(memtype, &memstat);
00984
00985 gn_phonebook_entry entry;
00986 TQStringList addrlist;
00987 TDEABC::Address *addr;
00988 TQString s, country;
00989
00990 progress->setTotalSteps(memstat.used);
00991 m_progressDlg->setLabel(i18n("<qt>Importing <b>%1</b> contacts from <b>%2</b> of the Mobile Phone.<br><br>%3</qt>")
00992 .arg(memstat.used)
00993 .arg(buildMemoryTypeString(memtype))
00994 .arg(buildPhoneInfoString(memstat)) );
00995
00996 int num_read = 0;
00997
00998 for (int i = 1; !m_progressDlg->wasCancelled() && i <= memstat.used + memstat.free; i++) {
00999 error = read_phone_entry( i, memtype, &entry );
01000
01001 progress->setProgress(num_read);
01002 this_filter->processEvents();
01003
01004 if (error == GN_ERR_EMPTYLOCATION)
01005 continue;
01006 if (error == GN_ERR_INVALIDLOCATION)
01007 break;
01008 if (error == GN_ERR_INVALIDMEMORYTYPE)
01009 break;
01010 if (error == GN_ERR_NONE) {
01011 GNOKII_DEBUG(TQString("%1: %2, num=%3, location=%4, group=%5, count=%6\n").arg(i).arg(GN_FROM(entry.name))
01012 .arg(GN_FROM(entry.number)).arg(entry.location).arg(entry.caller_group).arg(entry.subentries_count));
01013 TDEABC::Addressee *a = new TDEABC::Addressee();
01014
01015
01016 s = GN_FROM(entry.name).simplifyWhiteSpace();
01017 a->setFormattedName(s);
01018 if (s.find(',') == -1) {
01019
01020 addrlist = TQStringList::split(' ', s);
01021 if (addrlist.count() == 1) {
01022
01023 a->setGivenName(s);
01024 } else {
01025
01026 a->setFamilyName(addrlist.last().simplifyWhiteSpace());
01027 addrlist.remove(addrlist.last());
01028 a->setGivenName(addrlist.join(" ").simplifyWhiteSpace());
01029 }
01030 } else {
01031
01032 addrlist = TQStringList::split(',', s);
01033 a->setFamilyName(addrlist.first().simplifyWhiteSpace());
01034 addrlist.remove(addrlist.first());
01035 a->setGivenName(addrlist.join(" ").simplifyWhiteSpace());
01036 }
01037
01038 a->insertCustom(APP, "X_GSM_CALLERGROUP", s.setNum(entry.caller_group));
01039 a->insertCustom(APP, "X_GSM_STORE_AT", TQString("%1%2").arg(memtypestr).arg(entry.location));
01040
01041
01042 a->setProductId(PhoneProductId);
01043
01044
01045 TQDateTime datetime;
01046 if (entry.date.year<1998)
01047 datetime = TQDateTime::currentDateTime();
01048 else
01049 datetime = TQDateTime( TQDate(entry.date.year, entry.date.month, entry.date.day),
01050 TQTime(entry.date.hour, entry.date.minute, entry.date.second) );
01051 GNOKII_DEBUG(TQString(" date=%1\n").arg(datetime.toString()));
01052 a->setRevision(datetime);
01053
01054 if (!entry.subentries_count)
01055 a->insertPhoneNumber(TDEABC::PhoneNumber(entry.number, TDEABC::PhoneNumber::Work | TDEABC::PhoneNumber::Pref));
01056
01057
01058 if (entry.subentries_count)
01059 for (int n=0; n<entry.subentries_count; n++) {
01060 TQString s = GN_FROM(entry.subentries[n].data.number).simplifyWhiteSpace();
01061 GNOKII_DEBUG(TQString(" Subentry#%1, entry_type=%2, number_type=%3, number=%4\n")
01062 .arg(n).arg(entry.subentries[n].entry_type)
01063 .arg(entry.subentries[n].number_type).arg(s));
01064 if (s.isEmpty())
01065 continue;
01066 switch(entry.subentries[n].entry_type) {
01067 case GN_PHONEBOOK_ENTRY_Name:
01068 a->setName(s);
01069 break;
01070 case GN_PHONEBOOK_ENTRY_Email:
01071 a->insertEmail(s);
01072 break;
01073 case GN_PHONEBOOK_ENTRY_Postal:
01074 addrlist = TQStringList::split(';', s, true);
01075 addr = new TDEABC::Address(TDEABC::Address::Work);
01076 if (addrlist.count() <= 1) {
01077 addrlist = TQStringList::split(',', s, true);
01078 if (addrlist.count() > 1 ) {
01079
01080 addr->setLocality(addrlist[0]);
01081 addr->setPostalCode(addrlist[1]);
01082 if (!addrlist[2].isEmpty())
01083 addr->setCountry(i18n(GN_TO(addrlist[2])));
01084 } else {
01085
01086 addr->setLocality(s);
01087 }
01088 } else {
01089
01090 addr->setPostOfficeBox(addrlist[0]);
01091 addr->setExtended(addrlist[1]);
01092 addr->setStreet(addrlist[2]);
01093 addr->setLocality(addrlist[3]);
01094 addr->setRegion(addrlist[4]);
01095 addr->setPostalCode(addrlist[5]);
01096 country = addrlist[6];
01097 if (!country.isEmpty())
01098 addr->setCountry(i18n(GN_TO(country)));
01099 }
01100 a->insertAddress(*addr);
01101 delete addr;
01102 break;
01103 case GN_PHONEBOOK_ENTRY_Note:
01104 if (!a->note().isEmpty())
01105 s = "\n" + s;
01106 a->setNote(a->note()+s);
01107 break;
01108 case GN_PHONEBOOK_ENTRY_Number:
01109 enum TDEABC::PhoneNumber::Types phonetype;
01110 switch (entry.subentries[n].number_type) {
01111 case GN_PHONEBOOK_NUMBER_Mobile: phonetype = TDEABC::PhoneNumber::Cell; break;
01112 case GN_PHONEBOOK_NUMBER_Fax: phonetype = TDEABC::PhoneNumber::Fax; break;
01113 case GN_PHONEBOOK_NUMBER_General:
01114 case GN_PHONEBOOK_NUMBER_Work: phonetype = TDEABC::PhoneNumber::Work; break;
01115 default:
01116 case GN_PHONEBOOK_NUMBER_Home: phonetype = TDEABC::PhoneNumber::Home; break;
01117 }
01118
01119
01120 a->insertPhoneNumber(TDEABC::PhoneNumber(s, phonetype));
01121 break;
01122 case GN_PHONEBOOK_ENTRY_URL:
01123 a->setUrl(s);
01124 break;
01125 case GN_PHONEBOOK_ENTRY_Group:
01126 a->insertCategory(s);
01127 break;
01128 default:
01129 GNOKII_DEBUG(TQString(" Not handled id=%1, entry=%2\n")
01130 .arg(entry.subentries[n].entry_type).arg(s));
01131 break;
01132 }
01133 }
01134
01135
01136 if (strlen(entry.name) || strlen(entry.number) || entry.subentries_count)
01137 addrList->append(*a);
01138
01139
01140 num_read++;
01141 delete a;
01142 if (num_read >= memstat.used)
01143 break;
01144 else
01145 continue;
01146 }
01147 GNOKII_CHECK_ERROR(error);
01148 }
01149
01150 return GN_ERR_NONE;
01151 }
01152
01153
01154
01155
01156 static gn_error xxport_phone_write_entry( int phone_location, gn_memory_type memtype,
01157 const TDEABC::Addressee *addr)
01158 {
01159 gn_phonebook_entry entry;
01160 TQString s;
01161
01162 memset(&entry, 0, sizeof(entry));
01163 strncpy(entry.name, GN_TO(addr->realName()), sizeof(entry.name)-1);
01164 s = addr->phoneNumber(TDEABC::PhoneNumber::Pref).number();
01165 if (s.isEmpty())
01166 s = addr->phoneNumber(TDEABC::PhoneNumber::Work).number();
01167 if (s.isEmpty())
01168 s = addr->phoneNumber(TDEABC::PhoneNumber::Home).number();
01169 if (s.isEmpty())
01170 s = addr->phoneNumber(TDEABC::PhoneNumber::Cell).number();
01171 if (s.isEmpty() && addr->phoneNumbers().count()>0)
01172 s = (*addr->phoneNumbers().at(0)).number();
01173 s = makeValidPhone(s);
01174 strncpy(entry.number, s.ascii(), sizeof(entry.number)-1);
01175 entry.memory_type = memtype;
01176 TQString cg = addr->custom(APP, "X_GSM_CALLERGROUP");
01177 if (cg.isEmpty())
01178 entry.caller_group = 5;
01179 else
01180 entry.caller_group = cg.toInt();
01181 entry.location = phone_location;
01182
01183
01184 TQDateTime datetime = addr->revision();
01185 TQDate date(datetime.date());
01186 TQTime time(datetime.time());
01187 entry.date.year = date.year();
01188 entry.date.month = date.month();
01189 entry.date.day = date.day();
01190 entry.date.hour = time.hour();
01191 entry.date.minute = time.minute();
01192 entry.date.second = time.second();
01193
01194 GNOKII_DEBUG(TQString("Write #%1: name=%2, number=%3\n").arg(phone_location)
01195 .arg(GN_FROM(entry.name)).arg(GN_FROM(entry.number)));
01196
01197 const TDEABC::Address homeAddr = addr->address(TDEABC::Address::Home);
01198 const TDEABC::Address workAddr = addr->address(TDEABC::Address::Work);
01199
01200 entry.subentries_count = 0;
01201 gn_phonebook_subentry *subentry = &entry.subentries[0];
01202
01203 const TDEABC::PhoneNumber::List phoneList = addr->phoneNumbers();
01204 TDEABC::PhoneNumber::List::ConstIterator it;
01205 for ( it = phoneList.begin(); it != phoneList.end(); ++it ) {
01206 const TDEABC::PhoneNumber *phonenumber = &(*it);
01207 s = phonenumber->number();
01208 if (s.isEmpty()) continue;
01209 subentry->entry_type = GN_PHONEBOOK_ENTRY_Number;
01210 gn_phonebook_number_type type;
01211 int pn_type = phonenumber->type();
01212 if ((pn_type & TDEABC::PhoneNumber::Cell))
01213 type = GN_PHONEBOOK_NUMBER_Mobile;
01214 else if ((pn_type & TDEABC::PhoneNumber::Fax))
01215 type = GN_PHONEBOOK_NUMBER_Fax;
01216 else if ((pn_type & TDEABC::PhoneNumber::Home))
01217 type = GN_PHONEBOOK_NUMBER_Home;
01218 else if ((pn_type & TDEABC::PhoneNumber::Work))
01219 type = GN_PHONEBOOK_NUMBER_Work;
01220 else type = GN_PHONEBOOK_NUMBER_General;
01221 subentry->number_type = type;
01222 strncpy(subentry->data.number, makeValidPhone(s).ascii(), sizeof(subentry->data.number)-1);
01223 subentry->id = phone_location<<8+entry.subentries_count;
01224 entry.subentries_count++;
01225 subentry++;
01226 if (entry.subentries_count >= GN_PHONEBOOK_SUBENTRIES_MAX_NUMBER)
01227 break;
01228 }
01229
01230 s = addr->url().prettyURL();
01231 if (!s.isEmpty() && (entry.subentries_count<GN_PHONEBOOK_SUBENTRIES_MAX_NUMBER)) {
01232 subentry->entry_type = GN_PHONEBOOK_ENTRY_URL;
01233 strncpy(subentry->data.number, GN_TO(s), sizeof(subentry->data.number)-1);
01234 entry.subentries_count++;
01235 subentry++;
01236 }
01237
01238 TQStringList emails = addr->emails();
01239 for (unsigned int n=0; n<emails.count(); n++) {
01240 if (entry.subentries_count >= GN_PHONEBOOK_SUBENTRIES_MAX_NUMBER)
01241 break;
01242 s = emails[n].simplifyWhiteSpace();
01243 if (s.isEmpty()) continue;
01244
01245 if (n && !addr->url().isEmpty() && !addr->note().isEmpty() && addr->addresses().count()) {
01246 GNOKII_DEBUG(TQString(" DROPPED email %1 in favor of URLs, notes and addresses.\n")
01247 .arg(s));
01248 continue;
01249 }
01250 subentry->entry_type = GN_PHONEBOOK_ENTRY_Email;
01251 strncpy(subentry->data.number, GN_TO(s), sizeof(subentry->data.number)-1);
01252 entry.subentries_count++;
01253 subentry++;
01254 }
01255
01256 const TDEABC::Address::List addresses = addr->addresses();
01257 TDEABC::Address::List::ConstIterator it2;
01258 for ( it2 = addresses.begin(); it2 != addresses.end(); ++it2 ) {
01259 if (entry.subentries_count >= GN_PHONEBOOK_SUBENTRIES_MAX_NUMBER)
01260 break;
01261 const TDEABC::Address *Addr = &(*it2);
01262 if (Addr->isEmpty()) continue;
01263 subentry->entry_type = GN_PHONEBOOK_ENTRY_Postal;
01264 TQStringList a;
01265 TQChar sem(';');
01266 TQString sem_repl(TQString::fromLatin1(","));
01267 a.append( Addr->postOfficeBox().replace( sem, sem_repl ) );
01268 a.append( Addr->extended() .replace( sem, sem_repl ) );
01269 a.append( Addr->street() .replace( sem, sem_repl ) );
01270 a.append( Addr->locality() .replace( sem, sem_repl ) );
01271 a.append( Addr->region() .replace( sem, sem_repl ) );
01272 a.append( Addr->postalCode() .replace( sem, sem_repl ) );
01273 a.append( Addr->country() .replace( sem, sem_repl ) );
01274 s = a.join(sem);
01275 strncpy(subentry->data.number, GN_TO(s), sizeof(subentry->data.number)-1);
01276 entry.subentries_count++;
01277 subentry++;
01278 }
01279
01280 s = addr->note().simplifyWhiteSpace();
01281 if (!s.isEmpty() && (entry.subentries_count<GN_PHONEBOOK_SUBENTRIES_MAX_NUMBER)) {
01282 subentry->entry_type = GN_PHONEBOOK_ENTRY_Note;
01283 strncpy(subentry->data.number, GN_TO(s), sizeof(subentry->data.number)-1);
01284 entry.subentries_count++;
01285 subentry++;
01286 }
01287
01288
01289 for (int st=0; st<entry.subentries_count; st++) {
01290 gn_phonebook_subentry *subentry = &entry.subentries[st];
01291 GNOKII_DEBUG(TQString(" SubTel #%1: entry_type=%2, number_type=%3, number=%4\n")
01292 .arg(st).arg(subentry->entry_type)
01293 .arg(subentry->number_type).arg(GN_FROM(subentry->data.number)));
01294 }
01295
01296 data.phonebook_entry = &entry;
01297 gn_error error = gn_sm_functions(GN_OP_WritePhonebook, &data, &state);
01298 GNOKII_CHECK_ERROR(error);
01299
01300 return error;
01301 }
01302
01303
01304 static gn_error xxport_phone_delete_entry( int phone_location, gn_memory_type memtype )
01305 {
01306 gn_phonebook_entry entry;
01307 memset(&entry, 0, sizeof(entry));
01308 entry.empty = 1;
01309 entry.memory_type = memtype;
01310 entry.location = phone_location;
01311 data.phonebook_entry = &entry;
01312 GNOKII_DEBUG(TQString("Deleting entry %1\n").arg(phone_location));
01313 gn_error error = gn_sm_functions(GN_OP_WritePhonebook, &data, &state);
01314 GNOKII_CHECK_ERROR(error);
01315 return error;
01316 }
01317
01318 TDEABC::AddresseeList GNOKIIXXPort::importContacts( const TQString& ) const
01319 {
01320 TDEABC::AddresseeList addrList;
01321
01322 if (KMessageBox::Continue != KMessageBox::warningContinueCancel(parentWidget(),
01323 i18n("<qt>Please connect your Mobile Phone to your computer and press "
01324 "<b>Continue</b> to start importing the personal contacts.<br><br>"
01325 "Please note that if your Mobile Phone is not properly connected "
01326 "the following detection phase might take up to two minutes, during which "
01327 "KAddressbook will behave unresponsively.</qt>") ))
01328 return addrList;
01329
01330 m_progressDlg = new KProgressDialog( parentWidget(), "importwidget",
01331 i18n("Mobile Phone Import"),
01332 i18n("<qt><center>Establishing connection to the Mobile Phone.<br><br>"
01333 "Please wait...</center></qt>") );
01334 m_progressDlg->setAllowCancel(true);
01335 m_progressDlg->progressBar()->setProgress(0);
01336 m_progressDlg->progressBar()->setCenterIndicator(true);
01337 m_progressDlg->setModal(true);
01338 m_progressDlg->setInitialSize(TQSize(450,350));
01339 m_progressDlg->show();
01340 processEvents();
01341
01342 m_progressDlg->setCursor( TQt::BusyCursor );
01343 TQString errStr = businit();
01344 m_progressDlg->unsetCursor();
01345
01346 if (!errStr.isEmpty()) {
01347 KMessageBox::error(parentWidget(), errStr);
01348 delete m_progressDlg;
01349 return addrList;
01350 }
01351
01352 GNOKII_DEBUG("GNOKII import filter started.\n");
01353 m_progressDlg->setButtonText(i18n("&Stop Import"));
01354
01355 read_phone_entries("ME", GN_MT_ME, &addrList);
01356 read_phone_entries("SM", GN_MT_SM, &addrList);
01357
01358 GNOKII_DEBUG("GNOKII import filter finished.\n");
01359
01360 busterminate();
01361 delete m_progressDlg;
01362
01363 return addrList;
01364 }
01365
01366
01367 bool GNOKIIXXPort::exportContacts( const TDEABC::AddresseeList &list, const TQString & )
01368 {
01369 if (KMessageBox::Continue != KMessageBox::warningContinueCancel(parentWidget(),
01370 i18n("<qt>Please connect your Mobile Phone to your computer and press "
01371 "<b>Continue</b> to start exporting the selected personal contacts.<br><br>"
01372 "Please note that if your Mobile Phone is not properly connected "
01373 "the following detection phase might take up to two minutes, during which "
01374 "KAddressbook will behave unresponsively.</qt>") ))
01375 return false;
01376
01377 m_progressDlg = new KProgressDialog( parentWidget(), "importwidget",
01378 i18n("Mobile Phone Export"),
01379 i18n("<qt><center>Establishing connection to the Mobile Phone.<br><br>"
01380 "Please wait...</center></qt>") );
01381 m_progressDlg->setAllowCancel(true);
01382 m_progressDlg->progressBar()->setProgress(0);
01383 m_progressDlg->progressBar()->setCenterIndicator(true);
01384 m_progressDlg->setModal(true);
01385 m_progressDlg->setInitialSize(TQSize(450,350));
01386 m_progressDlg->show();
01387 processEvents();
01388
01389 KProgress* progress = (KProgress*)m_progressDlg->progressBar();
01390
01391 TDEABC::AddresseeList::ConstIterator it;
01392 TQStringList failedList;
01393
01394 gn_error error;
01395 bool deleteLabelInitialized = false;
01396
01397 m_progressDlg->setCursor( TQt::BusyCursor );
01398 TQString errStr = businit();
01399 m_progressDlg->unsetCursor();
01400
01401 if (!errStr.isEmpty()) {
01402 KMessageBox::error(parentWidget(), errStr);
01403 delete m_progressDlg;
01404 return false;
01405 }
01406
01407 GNOKII_DEBUG("GNOKII export filter started.\n");
01408
01409 gn_memory_type memtype = GN_MT_ME;
01410
01411 int phone_count;
01412 bool overwrite_phone_entries = false;
01413 int phone_entry_no, entries_written;
01414 bool entry_empty;
01415
01416
01417 gn_memory_status memstat;
01418 error = read_phone_memstat(memtype, &memstat);
01419 if (error == GN_ERR_NONE) {
01420 GNOKII_DEBUG("Writing to internal phone memory.\n");
01421 } else {
01422 memtype = GN_MT_SM;
01423 error = read_phone_memstat(memtype, &memstat);
01424 if (error != GN_ERR_NONE)
01425 goto finish;
01426 GNOKII_DEBUG("Writing to SIM card memory.\n");
01427 }
01428 phone_count = memstat.used;
01429
01430 if (memstat.free >= (int) list.count()) {
01431 if (KMessageBox::No == KMessageBox::questionYesNo(parentWidget(),
01432 i18n("<qt>Do you want the selected contacts to be <b>appended</b> to "
01433 "the current mobile phonebook or should they <b>replace</b> all "
01434 "currently existing phonebook entries ?<br><br>"
01435 "Please note, that in case you choose to replace the phonebook "
01436 "entries, every contact in your phone will be deleted and only "
01437 "the newly exported contacts will be available from inside your phone.</qt>"),
01438 i18n("Export to Mobile Phone"),
01439 KGuiItem(i18n("&Append to Current Phonebook")),
01440 KGuiItem(i18n("&Replace Current Phonebook with New Contacts")) ) )
01441 overwrite_phone_entries = true;
01442 }
01443
01444 progress->setTotalSteps(list.count());
01445 entries_written = 0;
01446 progress->setProgress(entries_written);
01447 m_progressDlg->setButtonText(i18n("&Stop Export"));
01448 m_progressDlg->setLabel(i18n("<qt>Exporting <b>%1</b> contacts to the <b>%2</b> "
01449 "of the Mobile Phone.<br><br>%3</qt>")
01450 .arg(list.count())
01451 .arg(buildMemoryTypeString(memtype))
01452 .arg(buildPhoneInfoString(memstat)) );
01453
01454
01455 phone_entry_no = 1;
01456 for ( it = list.begin(); it != list.end(); ++it ) {
01457 const TDEABC::Addressee *addr = &(*it);
01458 if (addr->isEmpty())
01459 continue;
01460
01461 if (addr->custom(APP, "X_GSM_STORE_AT").startsWith("SM"))
01462 continue;
01463
01464 progress->setProgress(entries_written++);
01465
01466 try_next_phone_entry:
01467 this_filter->processEvents();
01468 if (m_progressDlg->wasCancelled())
01469 break;
01470
01471
01472 if (phone_entry_no > (memstat.used + memstat.free))
01473 break;
01474
01475 GNOKII_DEBUG(TQString("Try to write entry '%1' at phone_entry_no=%2, phone_count=%3\n")
01476 .arg(addr->realName()).arg(phone_entry_no).arg(phone_count));
01477
01478 error = GN_ERR_NONE;
01479
01480
01481 entry_empty = phone_entry_empty(phone_entry_no, memtype);
01482 if (overwrite_phone_entries) {
01483
01484 if (!entry_empty)
01485 phone_count--;
01486 error = xxport_phone_write_entry( phone_entry_no, memtype, addr);
01487 phone_entry_no++;
01488 } else {
01489
01490 if (entry_empty) {
01491 error = xxport_phone_write_entry( phone_entry_no, memtype, addr);
01492 phone_entry_no++;
01493 } else {
01494 phone_entry_no++;
01495 goto try_next_phone_entry;
01496 }
01497 }
01498
01499 if (error != GN_ERR_NONE)
01500 failedList.append(addr->realName());
01501
01502
01503 if (error != GN_ERR_NONE && it==list.begin())
01504 break;
01505
01506 }
01507
01508
01509
01510 while (overwrite_phone_entries && error==GN_ERR_NONE && phone_count>0) {
01511 if (m_progressDlg->wasCancelled())
01512 break;
01513 if (!deleteLabelInitialized) {
01514 m_progressDlg->setLabel(
01515 i18n("<qt><center>"
01516 "All selected contacts have been sucessfully copied to "
01517 "the Mobile Phone.<br><br>"
01518 "Please wait until all remaining orphaned contacts from "
01519 "the Mobile Phone have been deleted.</center></qt>") );
01520 m_progressDlg->setButtonText(i18n("&Stop Delete"));
01521 deleteLabelInitialized = true;
01522 progress->setTotalSteps(phone_count);
01523 entries_written = 0;
01524 progress->setProgress(entries_written);
01525 this_filter->processEvents();
01526 }
01527 if (phone_entry_no > (memstat.used + memstat.free))
01528 break;
01529 entry_empty = phone_entry_empty(phone_entry_no, memtype);
01530 if (!entry_empty) {
01531 error = xxport_phone_delete_entry(phone_entry_no, memtype);
01532 phone_count--;
01533 progress->setProgress(++entries_written);
01534 this_filter->processEvents();
01535 }
01536 phone_entry_no++;
01537 }
01538
01539 finish:
01540 m_progressDlg->setLabel(i18n("Export to phone finished."));
01541 this_filter->processEvents();
01542
01543 GNOKII_DEBUG("GNOKII export filter finished.\n");
01544
01545 busterminate();
01546 delete m_progressDlg;
01547
01548 if (!failedList.isEmpty()) {
01549 GNOKII_DEBUG(TQString("Failed to export: %1\n").arg(failedList.join(", ")));
01550 KMessageBox::informationList(parentWidget(),
01551 i18n("<qt>The following contacts could not be exported to the Mobile Phone. "
01552 "Possible Reasons for this problem could be:<br><ul>"
01553 "<li>The contacts contain more information per entry than the phone can store.</li>"
01554 "<li>Your phone does not allow to store multiple addresses, emails, homepages, ...</li>"
01555 "<li>other storage size related problems.</li>"
01556 "</ul>"
01557 "To avoid those kind of problems in the future please reduce the amount of different "
01558 "fields in the above contacts.</qt>"),
01559 failedList,
01560 i18n("Mobile Phone Export") );
01561 }
01562
01563 return true;
01564 }
01565
01566
01567
01568
01569
01570
01571
01572
01573 #else
01574
01575 TDEABC::AddresseeList GNOKIIXXPort::importContacts( const TQString& ) const
01576 {
01577 TDEABC::AddresseeList addrList;
01578 KMessageBox::error(parentWidget(), i18n("Gnokii interface is not available.\n"
01579 "Please ask your distributor to add gnokii at compile time."));
01580 return addrList;
01581 }
01582
01583 bool GNOKIIXXPort::exportContacts( const TDEABC::AddresseeList &list, const TQString & )
01584 {
01585 Q_UNUSED(list);
01586 KMessageBox::error(parentWidget(), i18n("Gnokii interface is not available.\n"
01587 "Please ask your distributor to add gnokii at compile time."));
01588 return true;
01589 }
01590
01591 #endif
01592
01593
01594
01595
01596
01597
01598
01599 #include "gnokii_xxport.moc"
01600
01601