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
00034
#include "config.h"
00035
00036
#include <qcursor.h>
00037
00038
#include <kdebug.h>
00039
#include <klocale.h>
00040
#include <kmessagebox.h>
00041
#include <kprogress.h>
00042
#include <kguiitem.h>
00043
00044
#ifdef HAVE_GNOKII_H
00045
extern "C" {
00046
#include <gnokii.h>
00047 }
00048
#else
00049
#ifdef __GNUC__
00050
# warning "Please install the gnokii development headers and libraries !"
00051
#endif
00052
#endif
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() << QString("ERROR %1: %2\n").arg(error).arg(gn_error_print(error));\
00067
} while (0)
00068
00069
00070
00071
#define GN_FROM(x) QString::fromLocal8Bit(x)
00072
#define GN_TO(x) (x).local8Bit()
00073
00074
00075
static GNOKIIXXPort *this_filter;
00076
static KProgressDialog *m_progressDlg;
00077
00078
class GNOKIIXXPortFactory :
public KAB::XXPortFactory
00079 {
00080
public:
00081 KAB::XXPort *xxportObject( KABC::AddressBook *ab,
QWidget *parent,
const char *name )
00082 {
00083
return new GNOKIIXXPort( ab, parent, name );
00084 }
00085 };
00086
00087
extern "C"
00088 {
00089
void *init_libkaddrbk_gnokii_xxport()
00090 {
00091
return (
new GNOKIIXXPortFactory() );
00092 }
00093 }
00094
00095
00096 GNOKIIXXPort::GNOKIIXXPort( KABC::AddressBook *ab,
QWidget *parent,
const char *name )
00097 : KAB::XXPort( ab, parent, name )
00098 {
00099 this_filter =
this;
00100 m_progressDlg = NULL;
00101 createImportAction( i18n(
"Import From Nokia Mobile Phone..." ) );
00102 createExportAction( i18n(
"Export to Nokia Mobile Phone..." ) );
00103 }
00104
00105
00106
00107
#ifdef HAVE_GNOKII_H
00108
static char *lockfile = NULL;
00109
static char manufacturer[64], model[GN_MODEL_MAX_LENGTH+1],
00110 revision[GN_REVISION_MAX_LENGTH+1], imei[GN_IMEI_MAX_LENGTH+1];
00111
static QString PhoneProductId;
00112
00113
static struct gn_statemachine state;
00114
static gn_data data;
00115
00116
static void busterminate(
void)
00117 {
00118 gn_sm_functions(GN_OP_Terminate, NULL, &state);
00119
if (lockfile) gn_device_unlock(lockfile);
00120 }
00121
00122
static QString businit(
void)
00123 {
00124 gn_error error;
00125
char *aux;
00126
00127
#if defined(LIBGNOKII_VERSION)
00128
if (gn_cfg_read_default()<0)
00129
#else
00130
static char *BinDir;
00131
if (gn_cfg_read(&BinDir)<0)
00132
#endif
00133
return i18n(
"Failed to initialize the gnokii library.");
00134
00135
if (!gn_cfg_phone_load(
"", &state))
00136
return i18n(
"Gnokii is not yet configured.");
00137
00138
00139
00140
00141 gn_data_clear(&data);
00142
00143 aux = gn_cfg_get(gn_cfg_info,
"global",
"use_locking");
00144
00145
if (aux && !strcmp(aux,
"yes")) {
00146 lockfile = gn_device_lock(state.config.port_device);
00147
if (lockfile == NULL) {
00148
return i18n(
"Gnokii reports a 'Lock File Error'.\n "
00149
"Please exit all other running instances of gnokii, check if you have "
00150
"write permissions in the /var/lock directory and try again.");
00151 }
00152 }
00153
00154
00155
int old_dcd = state.config.require_dcd;
00156 state.config.require_dcd =
false;
00157 error = gn_gsm_initialise(&state);
00158 GNOKII_CHECK_ERROR(error);
00159 state.config.require_dcd = old_dcd;
00160
if (error != GN_ERR_NONE) {
00161 busterminate();
00162
return i18n(
"<qt><center>Mobile Phone interface initialization failed.<br><br>"
00163
"The returned error message was:<br><b>%1</b><br><br>"
00164
"You might try to run \"gnokii --identify\" on the command line to "
00165
"check any cable/transport issues and to verify if your gnokii "
00166
"configuration is correct.</center></qt>")
00167 .arg(gn_error_print(error));
00168 }
00169
00170
00171 gn_data_clear(&data);
00172 data.manufacturer = manufacturer;
00173 data.model = model;
00174 data.revision = revision;
00175 data.imei = imei;
00176
00177
QCString unknown(GN_TO(i18n(
"Unknown")));
00178 qstrncpy(manufacturer, unknown,
sizeof(manufacturer)-1);
00179 qstrncpy(model, unknown,
sizeof(model)-1);
00180 qstrncpy(revision, unknown,
sizeof(revision)-1);
00181 qstrncpy(imei, unknown,
sizeof(imei)-1);
00182
00183
if (m_progressDlg->wasCancelled())
00184
return QString::null;
00185
else
00186 error = gn_sm_functions(GN_OP_Identify, &data, &state);
00187 GNOKII_CHECK_ERROR(error);
00188
00189 GNOKII_DEBUG(
QString(
"Found mobile phone: %1 %2, Revision: %3, IMEI: %4\n")
00190 .arg(manufacturer, model, revision, imei) );
00191
00192 PhoneProductId =
QString(
"%1-%2-%3-%4").arg(APP).arg(model).arg(revision).arg(imei);
00193
00194
return QString::null;
00195 }
00196
00197
00198
00199
static gn_error read_phone_memstat(
const gn_memory_type memtype, gn_memory_status *memstat )
00200 {
00201 gn_error error;
00202
00203 gn_data_clear(&data);
00204 memset(memstat, 0,
sizeof(*memstat));
00205 memstat->memory_type = memtype;
00206 data.memory_status = memstat;
00207 error = gn_sm_functions(GN_OP_GetMemoryStatus, &data, &state);
00208 GNOKII_CHECK_ERROR(error);
00209
if (error != GN_ERR_NONE) {
00210
switch (memtype) {
00211
case GN_MT_SM:
00212
00213 memstat->used = 0;
00214 memstat->free = 100;
00215
break;
00216
default:
00217
case GN_MT_ME:
00218
00219 memstat->used = memstat->free = 0;
00220
break;
00221 }
00222 }
00223 GNOKII_DEBUG(
QString(
"\n\nMobile phone memory status: Type: %1, used=%2, free=%3, total=%4\n\n")
00224 .arg(memtype).arg(memstat->used).arg(memstat->free).arg(memstat->used+memstat->free) );
00225
return error;
00226 }
00227
00228
00229
00230
static gn_error read_phone_entry(
const int index,
const gn_memory_type memtype, gn_phonebook_entry *entry )
00231 {
00232 gn_error error;
00233 entry->memory_type = memtype;
00234 entry->location = index;
00235 data.phonebook_entry = entry;
00236 error = gn_sm_functions(GN_OP_ReadPhonebook, &data, &state);
00237 GNOKII_CHECK_ERROR(error);
00238
return error;
00239 }
00240
00241
static bool phone_entry_empty(
const int index,
const gn_memory_type memtype )
00242 {
00243 gn_error error;
00244 gn_phonebook_entry entry;
00245 entry.memory_type = memtype;
00246 entry.location = index;
00247 data.phonebook_entry = &entry;
00248 error = gn_sm_functions(GN_OP_ReadPhonebook, &data, &state);
00249
if (error == GN_ERR_EMPTYLOCATION)
00250
return true;
00251 GNOKII_CHECK_ERROR(error);
00252
if (error == GN_ERR_NONE && entry.empty)
00253
return true;
00254
return false;
00255 }
00256
00257
static QString buildPhoneInfoString(
const gn_memory_status &memstat )
00258 {
00259
QString format = QString::fromLatin1(
"<tr><td><b>%1</b></td><td>%2</td></tr>");
00260
00261
return QString::fromLatin1(
"<b>%1</b><br><table>%2%3%4%5%6</table><br>")
00262 .arg(i18n(
"Mobile Phone information:"))
00263 .arg(format.arg(i18n(
"Manufacturer")).arg(GN_FROM(manufacturer)))
00264 .arg(format.arg(i18n(
"Phone model")).arg(GN_FROM(model)))
00265 .arg(format.arg(i18n(
"Revision")).arg(GN_FROM(revision)))
00266 .arg(format.arg(i18n(
"IMEI")).arg(GN_FROM(imei)))
00267 .arg(format.arg(i18n(
"Phonebook status"))
00268 .arg(i18n(
"%1 out of %2 contacts used").arg(memstat.used).arg(memstat.used+memstat.free)));
00269 }
00270
00271
static QString buildMemoryTypeString( gn_memory_type memtype )
00272 {
00273
switch (memtype) {
00274
case GN_MT_ME:
return i18n(
"internal memory");
00275
case GN_MT_SM:
return i18n(
"SIM-card memory");
00276
default:
return i18n(
"unknown memory");
00277 }
00278 }
00279
00280
00281
static gn_error read_phone_entries(
const char *memtypestr, gn_memory_type memtype,
00282 KABC::AddresseeList *addrList )
00283 {
00284 gn_error error;
00285
00286
if (m_progressDlg->wasCancelled())
00287
return GN_ERR_NONE;
00288
00289 KProgress* progress = (KProgress*)m_progressDlg->progressBar();
00290
00291 progress->setProgress(0);
00292 this_filter->processEvents();
00293
00294
00295 gn_memory_status memstat;
00296 error = read_phone_memstat(memtype, &memstat);
00297
00298 gn_phonebook_entry entry;
00299
QStringList addrlist;
00300 KABC::Address *addr;
00301
QString s, country;
00302
00303 progress->setTotalSteps(memstat.used);
00304 m_progressDlg->setLabel(i18n(
"<qt>Importing <b>%1</b> contacts from <b>%2</b> of the Mobile Phone.<br><br>%3</qt>")
00305 .arg(memstat.used)
00306 .arg(buildMemoryTypeString(memtype))
00307 .arg(buildPhoneInfoString(memstat)) );
00308
00309
int num_read = 0;
00310
00311
for (
int i = 1; !m_progressDlg->wasCancelled() && i <= memstat.used + memstat.free; i++) {
00312 error = read_phone_entry( i, memtype, &entry );
00313
00314 progress->setProgress(num_read);
00315 this_filter->processEvents();
00316
00317
if (error == GN_ERR_EMPTYLOCATION)
00318
continue;
00319
if (error == GN_ERR_INVALIDLOCATION)
00320
break;
00321
if (error == GN_ERR_INVALIDMEMORYTYPE)
00322
break;
00323
if (error == GN_ERR_NONE) {
00324 GNOKII_DEBUG(
QString(
"%1: %2, num=%3, location=%4, group=%5, count=%6\n").arg(i).arg(GN_FROM(entry.name))
00325 .arg(GN_FROM(entry.number)).arg(entry.location).arg(entry.caller_group).arg(entry.subentries_count));
00326 KABC::Addressee *a =
new KABC::Addressee();
00327
00328
00329 s = GN_FROM(entry.name).simplifyWhiteSpace();
00330 a->setFormattedName(s);
00331
if (s.find(
',') == -1) {
00332
00333 addrlist = QStringList::split(
' ', s);
00334
if (addrlist.count() == 1) {
00335
00336 a->setGivenName(s);
00337 }
else {
00338
00339 a->setFamilyName(addrlist.last().simplifyWhiteSpace());
00340 addrlist.remove(addrlist.last());
00341 a->setGivenName(addrlist.join(
" ").simplifyWhiteSpace());
00342 }
00343 }
else {
00344
00345 addrlist = QStringList::split(
',', s);
00346 a->setFamilyName(addrlist.first().simplifyWhiteSpace());
00347 addrlist.remove(addrlist.first());
00348 a->setGivenName(addrlist.join(
" ").simplifyWhiteSpace());
00349 }
00350
00351 a->insertCustom(APP,
"X_GSM_CALLERGROUP", s.setNum(entry.caller_group));
00352 a->insertCustom(APP,
"X_GSM_STORE_AT",
QString(
"%1%2").arg(memtypestr).arg(entry.location));
00353
00354
00355 a->setProductId(PhoneProductId);
00356
00357
00358
QDateTime datetime;
00359
if (entry.date.year<1998)
00360 datetime = QDateTime::currentDateTime();
00361
else
00362 datetime =
QDateTime(
QDate(entry.date.year, entry.date.month, entry.date.day),
00363
QTime(entry.date.hour, entry.date.minute, entry.date.second) );
00364 GNOKII_DEBUG(
QString(
" date=%1\n").arg(datetime.toString()));
00365 a->setRevision(datetime);
00366
00367
if (!entry.subentries_count)
00368 a->insertPhoneNumber(KABC::PhoneNumber(entry.number, KABC::PhoneNumber::Work | KABC::PhoneNumber::Pref));
00369
00370
00371
if (entry.subentries_count)
00372
for (
int n=0; n<entry.subentries_count; n++) {
00373
QString s = GN_FROM(entry.subentries[n].data.number).simplifyWhiteSpace();
00374 GNOKII_DEBUG(
QString(
" Subentry#%1, entry_type=%2, number_type=%3, number=%4\n")
00375 .arg(n).arg(entry.subentries[n].entry_type)
00376 .arg(entry.subentries[n].number_type).arg(s));
00377
if (s.isEmpty())
00378
continue;
00379
switch(entry.subentries[n].entry_type) {
00380
case GN_PHONEBOOK_ENTRY_Name:
00381 a->setName(s);
00382
break;
00383
case GN_PHONEBOOK_ENTRY_Email:
00384 a->insertEmail(s);
00385
break;
00386
case GN_PHONEBOOK_ENTRY_Postal:
00387 addrlist = QStringList::split(
';', s,
true);
00388 addr =
new KABC::Address(KABC::Address::Work);
00389
if (addrlist.count() <= 1) {
00390 addrlist = QStringList::split(
',', s,
true);
00391
if (addrlist.count() > 1 ) {
00392
00393 addr->setLocality(addrlist[0]);
00394 addr->setPostalCode(addrlist[1]);
00395
if (!addrlist[2].isEmpty())
00396 addr->setCountry(i18n(GN_TO(addrlist[2])));
00397 }
else {
00398
00399 addr->setLocality(s);
00400 }
00401 }
else {
00402
00403 addr->setPostOfficeBox(addrlist[0]);
00404 addr->setExtended(addrlist[1]);
00405 addr->setStreet(addrlist[2]);
00406 addr->setLocality(addrlist[3]);
00407 addr->setRegion(addrlist[4]);
00408 addr->setPostalCode(addrlist[5]);
00409 country = addrlist[6];
00410
if (!country.isEmpty())
00411 addr->setCountry(i18n(GN_TO(country)));
00412 }
00413 a->insertAddress(*addr);
00414
delete addr;
00415
break;
00416
case GN_PHONEBOOK_ENTRY_Note:
00417
if (!a->note().isEmpty())
00418 s =
"\n" + s;
00419 a->setNote(a->note()+s);
00420
break;
00421
case GN_PHONEBOOK_ENTRY_Number:
00422
enum KABC::PhoneNumber::Types phonetype;
00423
switch (entry.subentries[n].number_type) {
00424
case GN_PHONEBOOK_NUMBER_Mobile: phonetype = KABC::PhoneNumber::Cell;
break;
00425
case GN_PHONEBOOK_NUMBER_Fax: phonetype = KABC::PhoneNumber::Fax;
break;
00426
case GN_PHONEBOOK_NUMBER_General:
00427
case GN_PHONEBOOK_NUMBER_Work: phonetype = KABC::PhoneNumber::Work;
break;
00428
default:
00429
case GN_PHONEBOOK_NUMBER_Home: phonetype = KABC::PhoneNumber::Home;
break;
00430 }
00431
00432
00433 a->insertPhoneNumber(KABC::PhoneNumber(s, phonetype));
00434
break;
00435
case GN_PHONEBOOK_ENTRY_URL:
00436 a->setUrl(s);
00437
break;
00438
case GN_PHONEBOOK_ENTRY_Group:
00439 a->insertCategory(s);
00440
break;
00441
default:
00442 GNOKII_DEBUG(
QString(
" Not handled id=%1, entry=%2\n")
00443 .arg(entry.subentries[n].entry_type).arg(s));
00444
break;
00445 }
00446 }
00447
00448
00449
if (strlen(entry.name) || strlen(entry.number) || entry.subentries_count)
00450 addrList->append(*a);
00451
00452
00453 num_read++;
00454
delete a;
00455
if (num_read >= memstat.used)
00456
break;
00457
else
00458
continue;
00459 }
00460 GNOKII_CHECK_ERROR(error);
00461 }
00462
00463
return GN_ERR_NONE;
00464 }
00465
#endif
00466
00467
00468
00469 KABC::AddresseeList GNOKIIXXPort::importContacts(
const QString& )
const
00470
{
00471 KABC::AddresseeList addrList;
00472
00473
#ifndef HAVE_GNOKII_H
00474
00475 KMessageBox::error(parentWidget(), i18n(
"Gnokii interface is not available.\n"
00476
"Please ask your distributor to add gnokii at compile time."));
00477
00478
#else
00479
00480
if (KMessageBox::Continue != KMessageBox::warningContinueCancel(parentWidget(),
00481 i18n(
"<qt>Please connect your Mobile Phone to your computer and press "
00482
"<b>Continue</b> to start importing the personal contacts.<br><br>"
00483
"Please note that if your mobile phone is not properly connected "
00484
"the following detection phase might take up to two minutes, during which "
00485
"KAddressbook will behave unresponsively.</qt>") ))
00486
return addrList;
00487
00488 m_progressDlg =
new KProgressDialog( parentWidget(),
"importwidget",
00489 i18n(
"Mobile Phone Import"),
00490 i18n(
"<qt><center>Establishing connection to the Mobile Phone.<br><br>"
00491
"Please wait...</center></qt>") );
00492 m_progressDlg->setAllowCancel(
true);
00493 m_progressDlg->progressBar()->setProgress(0);
00494 m_progressDlg->progressBar()->setCenterIndicator(
true);
00495 m_progressDlg->setModal(
true);
00496 m_progressDlg->setMinimumSize(450,350);
00497 m_progressDlg->show();
00498 processEvents();
00499
00500
#if (QT_VERSION >= 0x030300)
00501
m_progressDlg->setCursor( Qt::BusyCursor );
00502
#endif
00503
QString errStr = businit();
00504 m_progressDlg->unsetCursor();
00505
00506
if (!errStr.isEmpty()) {
00507 KMessageBox::error(parentWidget(), errStr);
00508
delete m_progressDlg;
00509
return addrList;
00510 }
00511
00512 GNOKII_DEBUG(
"GNOKII import filter started.\n");
00513 m_progressDlg->setButtonText(i18n(
"&Stop Import"));
00514
00515 read_phone_entries(
"ME", GN_MT_ME, &addrList);
00516 read_phone_entries(
"SM", GN_MT_SM, &addrList);
00517
00518 GNOKII_DEBUG(
"GNOKII import filter finished.\n");
00519
00520 busterminate();
00521
delete m_progressDlg;
00522
00523
#endif
00524
00525
return addrList;
00526 }
00527
00528
00529
00530
00531
#ifdef HAVE_GNOKII_H
00532
00533
static QString makeValidPhone(
const QString &number )
00534 {
00535
00536
QString num = number.simplifyWhiteSpace();
00537
QString allowed(
"0123456789*+#pw");
00538
for (
unsigned int i=num.length(); i>=1; i--)
00539
if (allowed.find(num[i-1])==-1)
00540 num.remove(i-1,1);
00541
if (num.isEmpty())
00542 num =
"0";
00543
return num;
00544 }
00545
00546
static gn_error xxport_phone_write_entry(
int phone_location, gn_memory_type memtype,
00547
const KABC::Addressee *addr)
00548 {
00549 gn_phonebook_entry entry;
00550
QString s;
00551
00552 memset(&entry, 0,
sizeof(entry));
00553 strncpy(entry.name, GN_TO(addr->realName()),
sizeof(entry.name)-1);
00554 s = addr->phoneNumber(KABC::PhoneNumber::Pref).number();
00555
if (s.isEmpty())
00556 s = addr->phoneNumber(KABC::PhoneNumber::Work).number();
00557
if (s.isEmpty())
00558 s = addr->phoneNumber(KABC::PhoneNumber::Home).number();
00559
if (s.isEmpty())
00560 s = addr->phoneNumber(KABC::PhoneNumber::Cell).number();
00561
if (s.isEmpty() && addr->phoneNumbers().count()>0)
00562 s = (*addr->phoneNumbers().at(0)).number();
00563 s = makeValidPhone(s);
00564 strncpy(entry.number, s.ascii(),
sizeof(entry.number)-1);
00565 entry.memory_type = memtype;
00566
QString cg = addr->custom(APP,
"X_GSM_CALLERGROUP");
00567
if (cg.isEmpty())
00568 entry.caller_group = 5;
00569
else
00570 entry.caller_group = cg.toInt();
00571 entry.location = phone_location;
00572
00573
00574 QDateTime datetime = addr->revision();
00575
QDate date(datetime.date());
00576
QTime time(datetime.time());
00577 entry.date.year = date.year();
00578 entry.date.month = date.month();
00579 entry.date.day = date.day();
00580 entry.date.hour = time.hour();
00581 entry.date.minute = time.minute();
00582 entry.date.second = time.second();
00583
00584 GNOKII_DEBUG(
QString(
"Write #%1: name=%2, number=%3\n").arg(phone_location)
00585 .arg(GN_FROM(entry.name)).arg(GN_FROM(entry.number)));
00586
00587
const KABC::Address homeAddr = addr->address(KABC::Address::Home);
00588
const KABC::Address workAddr = addr->address(KABC::Address::Work);
00589
00590 entry.subentries_count = 0;
00591 gn_phonebook_subentry *subentry = &entry.subentries[0];
00592
00593
const KABC::PhoneNumber::List phoneList = addr->phoneNumbers();
00594 KABC::PhoneNumber::List::ConstIterator it;
00595
for ( it = phoneList.begin(); it != phoneList.end(); ++it ) {
00596
const KABC::PhoneNumber *phonenumber = &(*it);
00597 s = phonenumber->number();
00598
if (s.isEmpty())
continue;
00599 subentry->entry_type = GN_PHONEBOOK_ENTRY_Number;
00600 gn_phonebook_number_type type;
00601
switch (phonenumber->type() & ~KABC::PhoneNumber::Pref) {
00602
case KABC::PhoneNumber::Home: type = GN_PHONEBOOK_NUMBER_Home;
break;
00603
case KABC::PhoneNumber::Voice:
00604
case KABC::PhoneNumber::Work: type = GN_PHONEBOOK_NUMBER_Work;
break;
00605
case KABC::PhoneNumber::Pager:
00606
case KABC::PhoneNumber::Cell: type = GN_PHONEBOOK_NUMBER_Mobile;
break;
00607
case KABC::PhoneNumber::Fax: type = GN_PHONEBOOK_NUMBER_Fax;
break;
00608
default: type = GN_PHONEBOOK_NUMBER_General;
break;
00609 }
00610 subentry->number_type = type;
00611 strncpy(subentry->data.number, makeValidPhone(s).ascii(),
sizeof(subentry->data.number)-1);
00612 subentry->id = phone_location<<8+entry.subentries_count;
00613 entry.subentries_count++;
00614 subentry++;
00615
if (entry.subentries_count >= GN_PHONEBOOK_SUBENTRIES_MAX_NUMBER)
00616
break;
00617 }
00618
00619 s = addr->url().prettyURL();
00620
if (!s.isEmpty() && (entry.subentries_count<GN_PHONEBOOK_SUBENTRIES_MAX_NUMBER)) {
00621 subentry->entry_type = GN_PHONEBOOK_ENTRY_URL;
00622 strncpy(subentry->data.number, GN_TO(s),
sizeof(subentry->data.number)-1);
00623 entry.subentries_count++;
00624 subentry++;
00625 }
00626
00627
QStringList emails = addr->emails();
00628
for (
unsigned int n=0; n<emails.count(); n++) {
00629
if (entry.subentries_count >= GN_PHONEBOOK_SUBENTRIES_MAX_NUMBER)
00630
break;
00631 s = emails[n].simplifyWhiteSpace();
00632
if (s.isEmpty())
continue;
00633
00634
if (n && !addr->url().isEmpty() && !addr->note().isEmpty() && addr->addresses().count()) {
00635 GNOKII_DEBUG(
QString(
" DROPPED email %1 in favor of URLs, notes and addresses.\n")
00636 .arg(s));
00637
continue;
00638 }
00639 subentry->entry_type = GN_PHONEBOOK_ENTRY_Email;
00640 strncpy(subentry->data.number, GN_TO(s),
sizeof(subentry->data.number)-1);
00641 entry.subentries_count++;
00642 subentry++;
00643 }
00644
00645
const KABC::Address::List addresses = addr->addresses();
00646 KABC::Address::List::ConstIterator it2;
00647
for ( it2 = addresses.begin(); it2 != addresses.end(); ++it2 ) {
00648
if (entry.subentries_count >= GN_PHONEBOOK_SUBENTRIES_MAX_NUMBER)
00649
break;
00650
const KABC::Address *Addr = &(*it2);
00651
if (Addr->isEmpty())
continue;
00652 subentry->entry_type = GN_PHONEBOOK_ENTRY_Postal;
00653
QStringList a;
00654
QChar sem(
';');
00655
QString sem_repl(QString::fromLatin1(
","));
00656 a.append( Addr->postOfficeBox().replace( sem, sem_repl ) );
00657 a.append( Addr->extended() .replace( sem, sem_repl ) );
00658 a.append( Addr->street() .replace( sem, sem_repl ) );
00659 a.append( Addr->locality() .replace( sem, sem_repl ) );
00660 a.append( Addr->region() .replace( sem, sem_repl ) );
00661 a.append( Addr->postalCode() .replace( sem, sem_repl ) );
00662 a.append( Addr->country() .replace( sem, sem_repl ) );
00663 s = a.join(sem);
00664 strncpy(subentry->data.number, GN_TO(s),
sizeof(subentry->data.number)-1);
00665 entry.subentries_count++;
00666 subentry++;
00667 }
00668
00669 s = addr->note().simplifyWhiteSpace();
00670
if (!s.isEmpty() && (entry.subentries_count<GN_PHONEBOOK_SUBENTRIES_MAX_NUMBER)) {
00671 subentry->entry_type = GN_PHONEBOOK_ENTRY_Note;
00672 strncpy(subentry->data.number, GN_TO(s),
sizeof(subentry->data.number)-1);
00673 entry.subentries_count++;
00674 subentry++;
00675 }
00676
00677
00678
for (
int st=0; st<entry.subentries_count; st++) {
00679 gn_phonebook_subentry *subentry = &entry.subentries[st];
00680 GNOKII_DEBUG(
QString(
" SubTel #%1: entry_type=%2, number_type=%3, number=%4\n")
00681 .arg(st).arg(subentry->entry_type)
00682 .arg(subentry->number_type).arg(GN_FROM(subentry->data.number)));
00683 }
00684
00685 data.phonebook_entry = &entry;
00686 gn_error error = gn_sm_functions(GN_OP_WritePhonebook, &data, &state);
00687 GNOKII_CHECK_ERROR(error);
00688
00689
return error;
00690 }
00691
00692
00693
static gn_error xxport_phone_delete_entry(
int phone_location, gn_memory_type memtype )
00694 {
00695 gn_phonebook_entry entry;
00696 memset(&entry, 0,
sizeof(entry));
00697 entry.empty = 1;
00698 entry.memory_type = memtype;
00699 entry.location = phone_location;
00700 data.phonebook_entry = &entry;
00701 GNOKII_DEBUG(
QString(
"Deleting entry %1\n").arg(phone_location));
00702 gn_error error = gn_sm_functions(GN_OP_WritePhonebook, &data, &state);
00703 GNOKII_CHECK_ERROR(error);
00704
return error;
00705 }
00706
00707
#endif
00708
00709
bool GNOKIIXXPort::exportContacts(
const KABC::AddresseeList &list,
const QString & )
00710 {
00711
#ifndef HAVE_GNOKII_H
00712
00713 Q_UNUSED(list);
00714 KMessageBox::error(parentWidget(), i18n(
"Gnokii interface is not available.\n"
00715
"Please ask your distributor to add gnokii at compile time."));
00716
00717
#else
00718
if (KMessageBox::Continue != KMessageBox::warningContinueCancel(parentWidget(),
00719 i18n(
"<qt>Please connect your Mobile Phone to your computer and press "
00720
"<b>Continue</b> to start exporting the selected personal contacts.<br><br>"
00721
"Please note that if your Mobile Phone is not properly connected "
00722
"the following detection phase might take up to two minutes, during which "
00723
"KAddressbook will behave unresponsively.</qt>") ))
00724
return false;
00725
00726 m_progressDlg =
new KProgressDialog( parentWidget(),
"importwidget",
00727 i18n(
"Mobile Phone Export"),
00728 i18n(
"<qt><center>Establishing connection to the Mobile Phone.<br><br>"
00729
"Please wait...</center></qt>") );
00730 m_progressDlg->setAllowCancel(
true);
00731 m_progressDlg->progressBar()->setProgress(0);
00732 m_progressDlg->progressBar()->setCenterIndicator(
true);
00733 m_progressDlg->setModal(
true);
00734 m_progressDlg->setMinimumSize(450,350);
00735 m_progressDlg->show();
00736 processEvents();
00737
00738 KProgress* progress = (KProgress*)m_progressDlg->progressBar();
00739
00740 KABC::AddresseeList::ConstIterator it;
00741
QStringList failedList;
00742
00743 gn_error error;
00744
bool deleteLabelInitialized =
false;
00745
00746
#if (QT_VERSION >= 0x030300)
00747
m_progressDlg->setCursor( Qt::BusyCursor );
00748
#endif
00749
QString errStr = businit();
00750 m_progressDlg->unsetCursor();
00751
00752
if (!errStr.isEmpty()) {
00753 KMessageBox::error(parentWidget(), errStr);
00754
delete m_progressDlg;
00755
return false;
00756 }
00757
00758 GNOKII_DEBUG(
"GNOKII export filter started.\n");
00759
00760 gn_memory_type memtype = GN_MT_ME;
00761
00762
int phone_count;
00763
bool overwrite_phone_entries =
false;
00764
int phone_entry_no, entries_written;
00765
bool entry_empty;
00766
00767
00768 gn_memory_status memstat;
00769 error = read_phone_memstat(memtype, &memstat);
00770
if (error == GN_ERR_NONE) {
00771 GNOKII_DEBUG(
"Writing to internal phone memory.\n");
00772 }
else {
00773 memtype = GN_MT_SM;
00774 error = read_phone_memstat(memtype, &memstat);
00775
if (error != GN_ERR_NONE)
00776
goto finish;
00777 GNOKII_DEBUG(
"Writing to SIM card memory.\n");
00778 }
00779 phone_count = memstat.used;
00780
00781
if (memstat.free >= (
int) list.count()) {
00782
if (KMessageBox::No == KMessageBox::questionYesNo(parentWidget(),
00783 i18n(
"<qt>Do you want the selected contacts to be <b>appended</b> to "
00784
"the current mobile phonebook or should they <b>replace</b> all "
00785
"currently existing phonebook entries ?<br><br>"
00786
"Please note, that in case you choose to replace the phonebook "
00787
"entries, every contact in your phone will be deleted and only "
00788
"the newly exported contacts will be available from inside your phone.</qt>"),
00789 i18n(
"Export to Mobile Phone"),
00790 KGuiItem(i18n(
"&Append to Current Phonebook")),
00791 KGuiItem(i18n(
"&Replace Current Phonebook with New Contacts")) ) )
00792 overwrite_phone_entries =
true;
00793 }
00794
00795 progress->setTotalSteps(list.count());
00796 entries_written = 0;
00797 progress->setProgress(entries_written);
00798 m_progressDlg->setButtonText(i18n(
"&Stop Export"));
00799 m_progressDlg->setLabel(i18n(
"<qt>Exporting <b>%1</b> contacts to the <b>%2</b> "
00800
"of the Mobile Phone.<br><br>%3</qt>")
00801 .arg(list.count())
00802 .arg(buildMemoryTypeString(memtype))
00803 .arg(buildPhoneInfoString(memstat)) );
00804
00805
00806 phone_entry_no = 1;
00807
for ( it = list.begin(); it != list.end(); ++it ) {
00808
const KABC::Addressee *addr = &(*it);
00809
if (addr->isEmpty())
00810
continue;
00811
00812
if (addr->custom(APP,
"X_GSM_STORE_AT").startsWith(
"SM"))
00813
continue;
00814
00815 progress->setProgress(entries_written++);
00816
00817 try_next_phone_entry:
00818 this_filter->processEvents();
00819
if (m_progressDlg->wasCancelled())
00820
break;
00821
00822
00823
if (phone_entry_no > (memstat.used + memstat.free))
00824
break;
00825
00826 GNOKII_DEBUG(
QString(
"Try to write entry '%1' at phone_entry_no=%2, phone_count=%3\n")
00827 .arg(addr->realName()).arg(phone_entry_no).arg(phone_count));
00828
00829 error = GN_ERR_NONE;
00830
00831
00832 entry_empty = phone_entry_empty(phone_entry_no, memtype);
00833
if (overwrite_phone_entries) {
00834
00835
if (!entry_empty)
00836 phone_count--;
00837 error = xxport_phone_write_entry( phone_entry_no, memtype, addr);
00838 phone_entry_no++;
00839 }
else {
00840
00841
if (entry_empty) {
00842 error = xxport_phone_write_entry( phone_entry_no, memtype, addr);
00843 phone_entry_no++;
00844 }
else {
00845 phone_entry_no++;
00846
goto try_next_phone_entry;
00847 }
00848 }
00849
00850
if (error != GN_ERR_NONE)
00851 failedList.append(addr->realName());
00852
00853
00854
if (error != GN_ERR_NONE && it==list.begin())
00855
break;
00856
00857 }
00858
00859
00860
00861
while (overwrite_phone_entries && error==GN_ERR_NONE && phone_count>0) {
00862
if (m_progressDlg->wasCancelled())
00863
break;
00864
if (!deleteLabelInitialized) {
00865 m_progressDlg->setLabel(
00866 i18n(
"<qt><center>"
00867
"All selected contacts have been sucessfully copied to "
00868
"the Mobile Phone.<br><br>"
00869
"Please wait until all remaining orphaned contacts from "
00870
"the Mobile Phone have been deleted.</center></qt>") );
00871 m_progressDlg->setButtonText(i18n(
"&Stop Delete"));
00872 deleteLabelInitialized =
true;
00873 progress->setTotalSteps(phone_count);
00874 entries_written = 0;
00875 progress->setProgress(entries_written);
00876 this_filter->processEvents();
00877 }
00878
if (phone_entry_no > (memstat.used + memstat.free))
00879
break;
00880 entry_empty = phone_entry_empty(phone_entry_no, memtype);
00881
if (!entry_empty) {
00882 error = xxport_phone_delete_entry(phone_entry_no, memtype);
00883 phone_count--;
00884 progress->setProgress(++entries_written);
00885 this_filter->processEvents();
00886 }
00887 phone_entry_no++;
00888 }
00889
00890 finish:
00891 m_progressDlg->setLabel(i18n(
"Export to phone finished."));
00892 this_filter->processEvents();
00893
00894 GNOKII_DEBUG(
"GNOKII export filter finished.\n");
00895
00896 busterminate();
00897
delete m_progressDlg;
00898
00899
if (!failedList.isEmpty()) {
00900 GNOKII_DEBUG(
QString(
"Failed to export: %1\n").arg(failedList.join(
", ")));
00901 KMessageBox::informationList(parentWidget(),
00902 i18n(
"<qt>The following contacts could not be exported to the Mobile Phone. "
00903
"Possible Reasons for this problem could be:<br><ul>"
00904
"<li>The contacts contain more information per entry than the phone can store.</li>"
00905
"<li>Your phone does not allow to store multiple addresses, emails, homepages, ...</li>"
00906
"<li>other storage size related problems.</li>"
00907
"</ul>"
00908
"To avoid those kind of problems in the future please reduce the amount of different "
00909
"fields in the above contacts.</qt>"),
00910 failedList,
00911 i18n(
"Mobile Phone Export") );
00912 }
00913
00914
#endif
00915
00916
return true;
00917 }
00918
00919
#include "gnokii_xxport.moc"
00920
00921