|
|
|
/*
|
|
|
|
This file is part of KAddressbook.
|
|
|
|
Copyright (c) 2003-2006 Helge Deller <deller@kde.org>
|
|
|
|
|
|
|
|
This program is free software; you can redistribute it and/or modify
|
|
|
|
it under the terms of the GNU General Public License version 2 as
|
|
|
|
published by the Free Software Foundation.
|
|
|
|
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
GNU General Public License for more details.
|
|
|
|
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
|
|
along with this program; if not, write to the Free Software
|
|
|
|
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|
|
|
|
|
|
|
As a special exception, permission is given to link this program
|
|
|
|
with any edition of TQt, and distribute the resulting executable,
|
|
|
|
without including the source code for TQt in the source distribution.
|
|
|
|
*/
|
|
|
|
/*
|
|
|
|
Description:
|
|
|
|
This filter allows you to import and export the TDE addressbook entries
|
|
|
|
to/from a mobile phone, which is accessible via gnokii.
|
|
|
|
Gnokii homepage: http://www.gnokii.org
|
|
|
|
|
|
|
|
TODO:
|
|
|
|
- create a log file and give user possibility to see it afterwards
|
|
|
|
- handle callergroup value (Friend, VIP, Family, ...) better
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include "config.h"
|
|
|
|
|
|
|
|
#ifdef HAVE_GNOKII_H
|
|
|
|
extern "C" {
|
|
|
|
#include <gnokii.h>
|
|
|
|
}
|
|
|
|
#else
|
|
|
|
#ifdef __GNUC__
|
|
|
|
# warning "Please install gnokii (http://www.gnokii.org) development headers and libraries !"
|
|
|
|
# warning "Please use at least version 0.6.13 or later of gnokii."
|
|
|
|
#endif
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#include <tqcursor.h>
|
|
|
|
|
|
|
|
#include <kdebug.h>
|
|
|
|
#include <tdelocale.h>
|
|
|
|
#include <tdemessagebox.h>
|
|
|
|
#include <kprogress.h>
|
|
|
|
#include <kguiitem.h>
|
|
|
|
|
|
|
|
#include "gnokii_xxport.h"
|
|
|
|
|
|
|
|
#define APP "GNOKII_XXPORT"
|
|
|
|
|
|
|
|
#if 1 // !defined(NDEBUG)
|
|
|
|
#define GNOKII_DEBUG(x) do { kdWarning() << (x); } while (0)
|
|
|
|
#else
|
|
|
|
#define GNOKII_DEBUG(x) do { } while (0)
|
|
|
|
#endif
|
|
|
|
#define GNOKII_CHECK_ERROR(error) \
|
|
|
|
do { \
|
|
|
|
if (error) \
|
|
|
|
kdError() << TQString("ERROR %1: %2\n").arg(error).arg(gn_error_print(error));\
|
|
|
|
} while (0)
|
|
|
|
|
|
|
|
// Locale conversion routines:
|
|
|
|
// Gnokii uses the local 8 Bit encoding (based on LC_ALL), kaddressbook uses Unicode
|
|
|
|
#define GN_FROM(x) TQString::fromLocal8Bit(x)
|
|
|
|
#define GN_TO(x) (x).local8Bit()
|
|
|
|
|
|
|
|
// static variables for GUI updates
|
|
|
|
static GNOKIIXXPort *this_filter;
|
|
|
|
static KProgressDialog *m_progressDlg;
|
|
|
|
|
|
|
|
K_EXPORT_KADDRESSBOOK_XXFILTER( libkaddrbk_gnokii_xxport, GNOKIIXXPort )
|
|
|
|
|
|
|
|
GNOKIIXXPort::GNOKIIXXPort( TDEABC::AddressBook *ab, TQWidget *parent, const char *name )
|
|
|
|
: KAB::XXPort( ab, parent, name )
|
|
|
|
{
|
|
|
|
this_filter = this;
|
|
|
|
m_progressDlg = NULL;
|
|
|
|
createImportAction( i18n( "Import From Mobile Phone..." ) );
|
|
|
|
createExportAction( i18n( "Export to Mobile Phone..." ) );
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#ifdef HAVE_GNOKII_H
|
|
|
|
static TQString makeValidPhone( const TQString &number )
|
|
|
|
{
|
|
|
|
// allowed chars: 0-9, *, #, p, w, +
|
|
|
|
TQString num = number.simplifyWhiteSpace();
|
|
|
|
TQString allowed("0123456789*+#pw");
|
|
|
|
for (unsigned int i=num.length(); i>=1; i--)
|
|
|
|
if (allowed.find(num[i-1])==-1)
|
|
|
|
num.remove(i-1,1);
|
|
|
|
if (num.isEmpty())
|
|
|
|
num = "0";
|
|
|
|
return num;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
/******************************************************************************
|
|
|
|
******************************************************************************
|
|
|
|
******************************************************************************
|
|
|
|
******************************************************************************
|
|
|
|
******************************************************************************/
|
|
|
|
|
|
|
|
#if defined(HAVE_GNOKII_H) && defined(LIBGNOKII_VERSION_MAJOR) && (LIBGNOKII_VERSION_MAJOR >= 3)
|
|
|
|
|
|
|
|
/* NEW GNOKII LIBRARIES (>= 0.6.13) */
|
|
|
|
|
|
|
|
static const char *manufacturer, *model, *revision, *imei;
|
|
|
|
static struct gn_statemachine *state;
|
|
|
|
|
|
|
|
static void busterminate(void)
|
|
|
|
{
|
|
|
|
gn_lib_phone_close(state);
|
|
|
|
gn_lib_phoneprofile_free(&state);
|
|
|
|
gn_lib_library_free();
|
|
|
|
}
|
|
|
|
|
|
|
|
static TQString businit(void)
|
|
|
|
{
|
|
|
|
GNOKII_DEBUG( "Using new gnokii version." );
|
|
|
|
|
|
|
|
GNOKII_DEBUG( TQString("Compiled with libgnokii version 0x%1\n").arg(TQString::number(LIBGNOKII_VERSION,16)) );
|
|
|
|
GNOKII_DEBUG( TQString("Using libgnokii runtime version 0x%1\n").arg(TQString::number(gn_lib_version(),16)) );
|
|
|
|
|
|
|
|
gn_error error = gn_lib_phoneprofile_load(NULL, &state);
|
|
|
|
if (error)
|
|
|
|
return i18n("Failed to initialize the gnokii library.");
|
|
|
|
|
|
|
|
error = gn_lib_phone_open( state );
|
|
|
|
GNOKII_CHECK_ERROR(error);
|
|
|
|
if (error != GN_ERR_NONE) {
|
|
|
|
busterminate();
|
|
|
|
return i18n("<qt><center>Mobile Phone interface initialization failed.<br><br>"
|
|
|
|
"The returned error message was:<br><b>%1</b><br><br>"
|
|
|
|
"You might try to run \"gnokii --identify\" on the command line to "
|
|
|
|
"check any cable/transport issues and to verify if your gnokii "
|
|
|
|
"configuration is correct.</center></qt>")
|
|
|
|
.arg(gn_error_print(error));
|
|
|
|
}
|
|
|
|
|
|
|
|
// identify phone
|
|
|
|
manufacturer = gn_lib_get_phone_manufacturer(state);
|
|
|
|
model = gn_lib_get_phone_model(state);
|
|
|
|
revision = gn_lib_get_phone_revision(state);
|
|
|
|
imei = gn_lib_get_phone_imei(state);
|
|
|
|
|
|
|
|
GNOKII_DEBUG( TQString("Found mobile phone: %1 %2, Revision: %3, IMEI: %4\n")
|
|
|
|
.arg(manufacturer, model, revision, imei) );
|
|
|
|
|
|
|
|
return TQString();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// get number of entries in this phone memory type (internal/SIM-card)
|
|
|
|
static gn_error read_phone_memstat( const gn_memory_type memtype, gn_memory_status *memstat )
|
|
|
|
{
|
|
|
|
gn_error error;
|
|
|
|
|
|
|
|
error = gn_lib_addressbook_memstat(state, memtype, &memstat->used, &memstat->free);
|
|
|
|
|
|
|
|
GNOKII_DEBUG( TQString("\n\nMobile phone memory status: Type: %1, used=%2, free=%3, total=%4\n\n")
|
|
|
|
.arg(memtype).arg(memstat->used).arg(memstat->free).arg(memstat->used+memstat->free) );
|
|
|
|
return error;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static TQString buildPhoneInfoString( const gn_memory_status &memstat )
|
|
|
|
{
|
|
|
|
TQString format = TQString::fromLatin1("<tr><td><b>%1</b></td><td>%2</td></tr>");
|
|
|
|
|
|
|
|
return TQString::fromLatin1("<b>%1</b><br><table>%2%3%4%5%6</table><br>")
|
|
|
|
.arg(i18n("Mobile Phone information:"))
|
|
|
|
.arg(format.arg(i18n("Manufacturer")).arg(GN_FROM(manufacturer)))
|
|
|
|
.arg(format.arg(i18n("Phone model")).arg(GN_FROM(model)))
|
|
|
|
.arg(format.arg(i18n("Revision")).arg(GN_FROM(revision)))
|
|
|
|
.arg(format.arg(i18n("IMEI")).arg(GN_FROM(imei)))
|
|
|
|
.arg(format.arg(i18n("Phonebook status"))
|
|
|
|
.arg(i18n("%1 out of %2 contacts used").arg(memstat.used).arg(memstat.used+memstat.free)));
|
|
|
|
}
|
|
|
|
|
|
|
|
// read and evaluate all phone entries
|
|
|
|
static gn_error read_phone_entries( const char *memtypestr, gn_memory_type memtype,
|
|
|
|
TDEABC::AddresseeList *addrList )
|
|
|
|
{
|
|
|
|
gn_error error;
|
|
|
|
|
|
|
|
if (m_progressDlg->wasCancelled())
|
|
|
|
return GN_ERR_NONE;
|
|
|
|
|
|
|
|
KProgress* progress = (KProgress*)m_progressDlg->progressBar();
|
|
|
|
|
|
|
|
progress->setProgress(0);
|
|
|
|
this_filter->processEvents();
|
|
|
|
|
|
|
|
// get number of entries in this phone memory type (internal/SIM-card)
|
|
|
|
gn_memory_status memstat;
|
|
|
|
error = read_phone_memstat(memtype, &memstat);
|
|
|
|
|
|
|
|
TQStringList addrlist;
|
|
|
|
TDEABC::Address *addr;
|
|
|
|
TQString s, country;
|
|
|
|
|
|
|
|
progress->setTotalSteps(memstat.used);
|
|
|
|
m_progressDlg->setLabel(i18n("<qt>Importing <b>%1</b> contacts from <b>%2</b> of the Mobile Phone.<br><br>%3</qt>")
|
|
|
|
.arg(memstat.used)
|
|
|
|
.arg(gn_memory_type2str(memtype))
|
|
|
|
.arg(buildPhoneInfoString(memstat)) );
|
|
|
|
|
|
|
|
int num_read = 0;
|
|
|
|
|
|
|
|
for (int i = 1; !m_progressDlg->wasCancelled() && i <= memstat.used + memstat.free; i++) {
|
|
|
|
error = gn_lib_phonebook_read_entry(state, memtype, i);
|
|
|
|
GNOKII_CHECK_ERROR(error);
|
|
|
|
|
|
|
|
progress->setProgress(num_read);
|
|
|
|
this_filter->processEvents();
|
|
|
|
|
|
|
|
if (error == GN_ERR_EMPTYLOCATION)
|
|
|
|
continue;
|
|
|
|
if (error == GN_ERR_INVALIDLOCATION)
|
|
|
|
break;
|
|
|
|
if (error == GN_ERR_INVALIDMEMORYTYPE)
|
|
|
|
break;
|
|
|
|
if (error == GN_ERR_NONE) {
|
|
|
|
const int subentries_count = gn_lib_get_pb_num_subentries(state);
|
|
|
|
const char *name = gn_lib_get_pb_name(state);
|
|
|
|
const char *number = gn_lib_get_pb_number(state);
|
|
|
|
|
|
|
|
GNOKII_DEBUG(TQString("%1: %2, num=%3, location=%4, group=%5, count=%6\n").arg(i)
|
|
|
|
.arg(GN_FROM(name)).arg(GN_FROM(number))
|
|
|
|
.arg(gn_lib_get_pb_location(state)).arg(gn_lib_get_pb_caller_group(state))
|
|
|
|
.arg(subentries_count));
|
|
|
|
TDEABC::Addressee *a = new TDEABC::Addressee();
|
|
|
|
|
|
|
|
// try to split Name into FamilyName and GivenName
|
|
|
|
s = GN_FROM(name).simplifyWhiteSpace();
|
|
|
|
a->setFormattedName(s); // set formatted name as in Phone
|
|
|
|
if (s.find(',') == -1) {
|
|
|
|
// assumed format: "givenname [... familyname]"
|
|
|
|
addrlist = TQStringList::split(' ', s);
|
|
|
|
if (addrlist.count() == 1) {
|
|
|
|
// only one string -> put it in the GivenName
|
|
|
|
a->setGivenName(s);
|
|
|
|
} else {
|
|
|
|
// multiple strings -> split them.
|
|
|
|
a->setFamilyName(addrlist.last().simplifyWhiteSpace());
|
|
|
|
addrlist.remove(addrlist.last());
|
|
|
|
a->setGivenName(addrlist.join(" ").simplifyWhiteSpace());
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
// assumed format: "familyname, ... givenname"
|
|
|
|
addrlist = TQStringList::split(',', s);
|
|
|
|
a->setFamilyName(addrlist.first().simplifyWhiteSpace());
|
|
|
|
addrlist.remove(addrlist.first());
|
|
|
|
a->setGivenName(addrlist.join(" ").simplifyWhiteSpace());
|
|
|
|
}
|
|
|
|
|
|
|
|
a->insertCustom(APP, "X_GSM_CALLERGROUP", s.setNum(gn_lib_get_pb_caller_group(state)));
|
|
|
|
a->insertCustom(APP, "X_GSM_STORE_AT", TQString("%1%2").arg(memtypestr).arg(gn_lib_get_pb_location(state)));
|
|
|
|
|
|
|
|
// set ProductId
|
|
|
|
a->setProductId(TQString("%1-%2-%3-%4").arg(APP).arg(model).arg(revision).arg(imei));
|
|
|
|
|
|
|
|
// evaluate timestamp (ignore timezone)
|
|
|
|
TQDateTime datetime;
|
|
|
|
gn_timestamp ts = gn_lib_get_pb_date(state);
|
|
|
|
if (ts.year<1998)
|
|
|
|
datetime = TQDateTime::currentDateTime();
|
|
|
|
else
|
|
|
|
datetime = TQDateTime( TQDate(ts.year, ts.month, ts.day),
|
|
|
|
TQTime(ts.hour, ts.minute, ts.second) );
|
|
|
|
GNOKII_DEBUG(TQString(" date=%1\n").arg(datetime.toString()));
|
|
|
|
a->setRevision(datetime);
|
|
|
|
|
|
|
|
if (!subentries_count)
|
|
|
|
a->insertPhoneNumber(TDEABC::PhoneNumber(number,
|
|
|
|
TDEABC::PhoneNumber::Work | TDEABC::PhoneNumber::Pref));
|
|
|
|
|
|
|
|
/* scan sub-entries */
|
|
|
|
if (subentries_count)
|
|
|
|
for (int n=0; n<subentries_count; n++) {
|
|
|
|
gn_phonebook_entry_type entry_type;
|
|
|
|
gn_phonebook_number_type number_type;
|
|
|
|
const char *number;
|
|
|
|
|
|
|
|
error = gn_lib_get_pb_subentry(state, n, &entry_type, &number_type, &number);
|
|
|
|
GNOKII_CHECK_ERROR(error);
|
|
|
|
|
|
|
|
TQString s = GN_FROM(number).simplifyWhiteSpace();
|
|
|
|
GNOKII_DEBUG(TQString(" Subentry#%1, entry_type=%2, number_type=%3, number=%4\n")
|
|
|
|
.arg(n).arg(entry_type).arg(number_type).arg(s));
|
|
|
|
if (s.isEmpty())
|
|
|
|
continue;
|
|
|
|
switch(entry_type) {
|
|
|
|
case GN_PHONEBOOK_ENTRY_Name:
|
|
|
|
a->setName(s);
|
|
|
|
break;
|
|
|
|
case GN_PHONEBOOK_ENTRY_Email:
|
|
|
|
a->insertEmail(s);
|
|
|
|
break;
|
|
|
|
case GN_PHONEBOOK_ENTRY_Postal:
|
|
|
|
addrlist = TQStringList::split(';', s, true);
|
|
|
|
addr = new TDEABC::Address(TDEABC::Address::Work);
|
|
|
|
if (addrlist.count() <= 1) {
|
|
|
|
addrlist = TQStringList::split(',', s, true);
|
|
|
|
if (addrlist.count() > 1 ) {
|
|
|
|
// assumed format: "Locality, ZIP, Country"
|
|
|
|
addr->setLocality(addrlist[0]);
|
|
|
|
addr->setPostalCode(addrlist[1]);
|
|
|
|
if (!addrlist[2].isEmpty())
|
|
|
|
addr->setCountry(i18n(GN_TO(addrlist[2])));
|
|
|
|
} else {
|
|
|
|
// no idea about the format, just store it.
|
|
|
|
addr->setLocality(s);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
// assumed format: "POBox; Extended; Street; Locality; Region; ZIP [;Country]
|
|
|
|
addr->setPostOfficeBox(addrlist[0]);
|
|
|
|
addr->setExtended(addrlist[1]);
|
|
|
|
addr->setStreet(addrlist[2]);
|
|
|
|
addr->setLocality(addrlist[3]);
|
|
|
|
addr->setRegion(addrlist[4]);
|
|
|
|
addr->setPostalCode(addrlist[5]);
|
|
|
|
country = addrlist[6];
|
|
|
|
if (!country.isEmpty())
|
|
|
|
addr->setCountry(i18n(GN_TO(country)));
|
|
|
|
}
|
|
|
|
a->insertAddress(*addr);
|
|
|
|
delete addr;
|
|
|
|
break;
|
|
|
|
case GN_PHONEBOOK_ENTRY_Note:
|
|
|
|
if (!a->note().isEmpty())
|
|
|
|
s = "\n" + s;
|
|
|
|
a->setNote(a->note()+s);
|
|
|
|
break;
|
|
|
|
case GN_PHONEBOOK_ENTRY_Number:
|
|
|
|
enum TDEABC::PhoneNumber::Types phonetype;
|
|
|
|
switch (number_type) {
|
|
|
|
case GN_PHONEBOOK_NUMBER_Mobile: phonetype = TDEABC::PhoneNumber::Cell; break;
|
|
|
|
case GN_PHONEBOOK_NUMBER_Fax: phonetype = TDEABC::PhoneNumber::Fax; break;
|
|
|
|
case GN_PHONEBOOK_NUMBER_General:
|
|
|
|
case GN_PHONEBOOK_NUMBER_Work: phonetype = TDEABC::PhoneNumber::Work; break;
|
|
|
|
default:
|
|
|
|
case GN_PHONEBOOK_NUMBER_Home: phonetype = TDEABC::PhoneNumber::Home; break;
|
|
|
|
}
|
|
|
|
//if (s == entry.number)
|
|
|
|
// type = (TDEABC::PhoneNumber::Types) (phonetype | TDEABC::PhoneNumber::Pref);
|
|
|
|
a->insertPhoneNumber(TDEABC::PhoneNumber(s, phonetype));
|
|
|
|
break;
|
|
|
|
case GN_PHONEBOOK_ENTRY_URL:
|
|
|
|
a->setUrl(s);
|
|
|
|
break;
|
|
|
|
case GN_PHONEBOOK_ENTRY_Group:
|
|
|
|
a->insertCategory(s);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
GNOKII_DEBUG(TQString(" Not handled id=%1, entry=%2\n")
|
|
|
|
.arg(entry_type).arg(s));
|
|
|
|
break;
|
|
|
|
} // switch()
|
|
|
|
} // if(subentry)
|
|
|
|
|
|
|
|
// add only if entry was valid
|
|
|
|
if (strlen(name) || strlen(number) || subentries_count)
|
|
|
|
addrList->append(*a);
|
|
|
|
|
|
|
|
// did we read all valid phonebook-entries ?
|
|
|
|
num_read++;
|
|
|
|
delete a;
|
|
|
|
if (num_read >= memstat.used)
|
|
|
|
break; // yes, all were read
|
|
|
|
else
|
|
|
|
continue; // no, we are still missing some.
|
|
|
|
}
|
|
|
|
GNOKII_CHECK_ERROR(error);
|
|
|
|
}
|
|
|
|
|
|
|
|
return GN_ERR_NONE;
|
|
|
|
}
|
|
|
|
|
|
|
|
// export to phone
|
|
|
|
|
|
|
|
static gn_error xxport_phone_write_entry( int phone_location, gn_memory_type memtype,
|
|
|
|
const TDEABC::Addressee *addr)
|
|
|
|
{
|
|
|
|
TQString s;
|
|
|
|
|
|
|
|
/* initialize the phonebook entry values to zero */
|
|
|
|
gn_lib_phonebook_prepare_write_entry(state);
|
|
|
|
|
|
|
|
gn_lib_set_pb_location(state, phone_location);
|
|
|
|
|
|
|
|
gn_lib_set_pb_name(state, GN_TO(addr->realName()));
|
|
|
|
s = addr->phoneNumber(TDEABC::PhoneNumber::Pref).number();
|
|
|
|
if (s.isEmpty())
|
|
|
|
s = addr->phoneNumber(TDEABC::PhoneNumber::Work).number();
|
|
|
|
if (s.isEmpty())
|
|
|
|
s = addr->phoneNumber(TDEABC::PhoneNumber::Home).number();
|
|
|
|
if (s.isEmpty())
|
|
|
|
s = addr->phoneNumber(TDEABC::PhoneNumber::Cell).number();
|
|
|
|
if (s.isEmpty() && addr->phoneNumbers().count()>0)
|
|
|
|
s = (*addr->phoneNumbers().at(0)).number();
|
|
|
|
s = makeValidPhone(s);
|
|
|
|
gn_lib_set_pb_number(state, s.ascii());
|
|
|
|
gn_lib_set_pb_memtype(state, memtype);
|
|
|
|
TQString cg = addr->custom(APP, "X_GSM_CALLERGROUP");
|
|
|
|
if (cg.isEmpty())
|
|
|
|
gn_lib_set_pb_caller_group(state, GN_PHONEBOOK_GROUP_None); // default group
|
|
|
|
else
|
|
|
|
gn_lib_set_pb_caller_group(state, (gn_phonebook_group_type) cg.toInt());
|
|
|
|
|
|
|
|
// set date/revision
|
|
|
|
TQDateTime datetime = addr->revision();
|
|
|
|
TQDate date(datetime.date());
|
|
|
|
TQTime time(datetime.time());
|
|
|
|
gn_timestamp ts;
|
|
|
|
gn_timestamp_set( &ts, date.year(), date.month(), date.day(),
|
|
|
|
time.hour(), time.minute(), time.second(), 0 );
|
|
|
|
gn_lib_set_pb_date(state, ts);
|
|
|
|
|
|
|
|
GNOKII_DEBUG(TQString("Write #%1: name=%2, number=%3\n").arg(phone_location)
|
|
|
|
.arg(GN_FROM(gn_lib_get_pb_name(state))).arg(GN_FROM(gn_lib_get_pb_number(state))));
|
|
|
|
|
|
|
|
const TDEABC::Address homeAddr = addr->address(TDEABC::Address::Home);
|
|
|
|
const TDEABC::Address workAddr = addr->address(TDEABC::Address::Work);
|
|
|
|
|
|
|
|
// add all phone numbers
|
|
|
|
const TDEABC::PhoneNumber::List phoneList = addr->phoneNumbers();
|
|
|
|
TDEABC::PhoneNumber::List::ConstIterator it;
|
|
|
|
for ( it = phoneList.begin(); it != phoneList.end(); ++it ) {
|
|
|
|
const TDEABC::PhoneNumber *phonenumber = &(*it);
|
|
|
|
s = phonenumber->number();
|
|
|
|
if (s.isEmpty()) continue;
|
|
|
|
gn_phonebook_number_type type;
|
|
|
|
int pn_type = phonenumber->type();
|
|
|
|
if ((pn_type & TDEABC::PhoneNumber::Cell))
|
|
|
|
type = GN_PHONEBOOK_NUMBER_Mobile;
|
|
|
|
else if ((pn_type & TDEABC::PhoneNumber::Fax))
|
|
|
|
type = GN_PHONEBOOK_NUMBER_Fax;
|
|
|
|
else if ((pn_type & TDEABC::PhoneNumber::Home))
|
|
|
|
type = GN_PHONEBOOK_NUMBER_Home;
|
|
|
|
else if ((pn_type & TDEABC::PhoneNumber::Work))
|
|
|
|
type = GN_PHONEBOOK_NUMBER_Work;
|
|
|
|
else type = GN_PHONEBOOK_NUMBER_General;
|
|
|
|
gn_lib_set_pb_subentry(state, -1 /* index to append entry */,
|
|
|
|
GN_PHONEBOOK_ENTRY_Number, type, makeValidPhone(s).ascii());
|
|
|
|
/*subentry->id = phone_location<<8+entry.subentries_count;*/
|
|
|
|
}
|
|
|
|
// add URL
|
|
|
|
s = addr->url().prettyURL();
|
|
|
|
if (!s.isEmpty()) {
|
|
|
|
gn_lib_set_pb_subentry(state, -1 /* index to append entry */,
|
|
|
|
GN_PHONEBOOK_ENTRY_URL, GN_PHONEBOOK_NUMBER_General, GN_TO(s));
|
|
|
|
}
|
|
|
|
// add E-Mails
|
|
|
|
TQStringList emails = addr->emails();
|
|
|
|
for (unsigned int n=0; n<emails.count(); n++) {
|
|
|
|
s = emails[n].simplifyWhiteSpace();
|
|
|
|
if (s.isEmpty()) continue;
|
|
|
|
// only one email allowed if we have URLS, notes, addresses (to avoid phone limitations)
|
|
|
|
if (n && !addr->url().isEmpty() && !addr->note().isEmpty() && addr->addresses().count()) {
|
|
|
|
GNOKII_DEBUG(TQString(" DROPPED email %1 in favor of URLs, notes and addresses.\n")
|
|
|
|
.arg(s));
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
gn_lib_set_pb_subentry(state, -1 /* index to append entry */,
|
|
|
|
GN_PHONEBOOK_ENTRY_Email, GN_PHONEBOOK_NUMBER_General, GN_TO(s));
|
|
|
|
}
|
|
|
|
// add Adresses
|
|
|
|
const TDEABC::Address::List addresses = addr->addresses();
|
|
|
|
TDEABC::Address::List::ConstIterator it2;
|
|
|
|
for ( it2 = addresses.begin(); it2 != addresses.end(); ++it2 ) {
|
|
|
|
const TDEABC::Address *Addr = &(*it2);
|
|
|
|
if (Addr->isEmpty()) continue;
|
|
|
|
TQStringList a;
|
|
|
|
TQChar sem(';');
|
|
|
|
TQString sem_repl(TQString::fromLatin1(","));
|
|
|
|
a.append( Addr->postOfficeBox().replace( sem, sem_repl ) );
|
|
|
|
a.append( Addr->extended() .replace( sem, sem_repl ) );
|
|
|
|
a.append( Addr->street() .replace( sem, sem_repl ) );
|
|
|
|
a.append( Addr->locality() .replace( sem, sem_repl ) );
|
|
|
|
a.append( Addr->region() .replace( sem, sem_repl ) );
|
|
|
|
a.append( Addr->postalCode() .replace( sem, sem_repl ) );
|
|
|
|
a.append( Addr->country() .replace( sem, sem_repl ) );
|
|
|
|
s = a.join(sem);
|
|
|
|
gn_lib_set_pb_subentry(state, -1 /* index to append entry */,
|
|
|
|
GN_PHONEBOOK_ENTRY_Postal, GN_PHONEBOOK_NUMBER_General, GN_TO(s));
|
|
|
|
}
|
|
|
|
// add Note
|
|
|
|
s = addr->note().simplifyWhiteSpace();
|
|
|
|
if (!s.isEmpty()) {
|
|
|
|
gn_lib_set_pb_subentry(state, -1 /* index to append entry */,
|
|
|
|
GN_PHONEBOOK_ENTRY_Note, GN_PHONEBOOK_NUMBER_General, GN_TO(s));
|
|
|
|
}
|
|
|
|
|
|
|
|
// debug output
|
|
|
|
for (int st=0; st<gn_lib_get_pb_num_subentries(state); st++) {
|
|
|
|
gn_phonebook_entry_type entry_type;
|
|
|
|
gn_phonebook_number_type number_type;
|
|
|
|
const char *number;
|
|
|
|
gn_lib_get_pb_subentry(state, st, &entry_type, &number_type, &number);
|
|
|
|
GNOKII_DEBUG(TQString(" SubTel #%1: entry_type=%2, number_type=%3, number=%4\n")
|
|
|
|
.arg(st).arg(entry_type)
|
|
|
|
.arg(number_type).arg(GN_FROM(number)));
|
|
|
|
}
|
|
|
|
|
|
|
|
gn_error error = gn_lib_phonebook_write_entry(state, memtype, phone_location);
|
|
|
|
GNOKII_CHECK_ERROR(error);
|
|
|
|
|
|
|
|
return error;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static gn_error xxport_phone_delete_entry( int phone_location, gn_memory_type memtype )
|
|
|
|
{
|
|
|
|
return gn_lib_phonebook_entry_delete(state, memtype, phone_location);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
TDEABC::AddresseeList GNOKIIXXPort::importContacts( const TQString& ) const
|
|
|
|
{
|
|
|
|
TDEABC::AddresseeList addrList;
|
|
|
|
|
|
|
|
if (KMessageBox::Continue != KMessageBox::warningContinueCancel(parentWidget(),
|
|
|
|
i18n("<qt>Please connect your Mobile Phone to your computer and press "
|
|
|
|
"<b>Continue</b> to start importing the personal contacts.<br><br>"
|
|
|
|
"Please note that if your Mobile Phone is not properly connected "
|
|
|
|
"the following detection phase might take up to two minutes, during which "
|
|
|
|
"KAddressbook will behave unresponsively.</qt>") ))
|
|
|
|
return addrList;
|
|
|
|
|
|
|
|
m_progressDlg = new KProgressDialog( parentWidget(), "importwidget",
|
|
|
|
i18n("Mobile Phone Import"),
|
|
|
|
i18n("<qt><center>Establishing connection to the Mobile Phone.<br><br>"
|
|
|
|
"Please wait...</center></qt>") );
|
|
|
|
m_progressDlg->setAllowCancel(true);
|
|
|
|
m_progressDlg->progressBar()->setProgress(0);
|
|
|
|
m_progressDlg->progressBar()->setCenterIndicator(true);
|
|
|
|
m_progressDlg->setModal(true);
|
|
|
|
m_progressDlg->setInitialSize(TQSize(450,350));
|
|
|
|
m_progressDlg->show();
|
|
|
|
processEvents();
|
|
|
|
|
|
|
|
m_progressDlg->setCursor( TQt::BusyCursor );
|
|
|
|
TQString errStr = businit();
|
|
|
|
m_progressDlg->unsetCursor();
|
|
|
|
|
|
|
|
if (!errStr.isEmpty()) {
|
|
|
|
KMessageBox::error(parentWidget(), errStr);
|
|
|
|
delete m_progressDlg;
|
|
|
|
return addrList;
|
|
|
|
}
|
|
|
|
|
|
|
|
GNOKII_DEBUG("GNOKII import filter started.\n");
|
|
|
|
m_progressDlg->setButtonText(i18n("&Stop Import"));
|
|
|
|
|
|
|
|
read_phone_entries("ME", GN_MT_ME, &addrList); // internal phone memory
|
|
|
|
read_phone_entries("SM", GN_MT_SM, &addrList); // SIM card
|
|
|
|
|
|
|
|
GNOKII_DEBUG("GNOKII import filter finished.\n");
|
|
|
|
|
|
|
|
busterminate();
|
|
|
|
delete m_progressDlg;
|
|
|
|
|
|
|
|
return addrList;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
bool GNOKIIXXPort::exportContacts( const TDEABC::AddresseeList &list, const TQString & )
|
|
|
|
{
|
|
|
|
if (KMessageBox::Continue != KMessageBox::warningContinueCancel(parentWidget(),
|
|
|
|
i18n("<qt>Please connect your Mobile Phone to your computer and press "
|
|
|
|
"<b>Continue</b> to start exporting the selected personal contacts.<br><br>"
|
|
|
|
"Please note that if your Mobile Phone is not properly connected "
|
|
|
|
"the following detection phase might take up to two minutes, during which "
|
|
|
|
"KAddressbook will behave unresponsively.</qt>") ))
|
|
|
|
return false;
|
|
|
|
|
|
|
|
m_progressDlg = new KProgressDialog( parentWidget(), "importwidget",
|
|
|
|
i18n("Mobile Phone Export"),
|
|
|
|
i18n("<qt><center>Establishing connection to the Mobile Phone.<br><br>"
|
|
|
|
"Please wait...</center></qt>") );
|
|
|
|
m_progressDlg->setAllowCancel(true);
|
|
|
|
m_progressDlg->progressBar()->setProgress(0);
|
|
|
|
m_progressDlg->progressBar()->setCenterIndicator(true);
|
|
|
|
m_progressDlg->setModal(true);
|
|
|
|
m_progressDlg->setInitialSize(TQSize(450,350));
|
|
|
|
m_progressDlg->show();
|
|
|
|
processEvents();
|
|
|
|
|
|
|
|
KProgress* progress = (KProgress*)m_progressDlg->progressBar();
|
|
|
|
|
|
|
|
TDEABC::AddresseeList::ConstIterator it;
|
|
|
|
TQStringList failedList;
|
|
|
|
|
|
|
|
gn_error error;
|
|
|
|
bool deleteLabelInitialized = false;
|
|
|
|
|
|
|
|
m_progressDlg->setCursor( TQt::BusyCursor );
|
|
|
|
TQString errStr = businit();
|
|
|
|
m_progressDlg->unsetCursor();
|
|
|
|
|
|
|
|
if (!errStr.isEmpty()) {
|
|
|
|
KMessageBox::error(parentWidget(), errStr);
|
|
|
|
delete m_progressDlg;
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
GNOKII_DEBUG("GNOKII export filter started.\n");
|
|
|
|
|
|
|
|
gn_memory_type memtype = GN_MT_ME; // internal phone memory
|
|
|
|
|
|
|
|
int phone_count; // num entries in phone
|
|
|
|
bool overwrite_phone_entries = false;
|
|
|
|
int phone_entry_no, entries_written;
|
|
|
|
bool entry_empty;
|
|
|
|
|
|
|
|
// get number of entries in this phone memory
|
|
|
|
gn_memory_status memstat;
|
|
|
|
error = read_phone_memstat(memtype, &memstat);
|
|
|
|
if (error == GN_ERR_NONE) {
|
|
|
|
GNOKII_DEBUG("Writing to internal phone memory.\n");
|
|
|
|
} else {
|
|
|
|
memtype = GN_MT_SM; // try SIM card instead
|
|
|
|
error = read_phone_memstat(memtype, &memstat);
|
|
|
|
if (error != GN_ERR_NONE)
|
|
|
|
goto finish;
|
|
|
|
GNOKII_DEBUG("Writing to SIM card memory.\n");
|
|
|
|
}
|
|
|
|
phone_count = memstat.used;
|
|
|
|
|
|
|
|
if (memstat.free >= (int) list.count()) {
|
|
|
|
if (KMessageBox::No == KMessageBox::questionYesNo(parentWidget(),
|
|
|
|
i18n("<qt>Do you want the selected contacts to be <b>appended</b> to "
|
|
|
|
"the current mobile phonebook or should they <b>replace</b> all "
|
|
|
|
"currently existing phonebook entries ?<br><br>"
|
|
|
|
"Please note, that in case you choose to replace the phonebook "
|
|
|
|
"entries, every contact in your phone will be deleted and only "
|
|
|
|
"the newly exported contacts will be available from inside your phone.</qt>"),
|
|
|
|
i18n("Export to Mobile Phone"),
|
|
|
|
KGuiItem(i18n("&Append to Current Phonebook")),
|
|
|
|
KGuiItem(i18n("&Replace Current Phonebook with New Contacts")) ) )
|
|
|
|
overwrite_phone_entries = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
progress->setTotalSteps(list.count());
|
|
|
|
entries_written = 0;
|
|
|
|
progress->setProgress(entries_written);
|
|
|
|
m_progressDlg->setButtonText(i18n("&Stop Export"));
|
|
|
|
m_progressDlg->setLabel(i18n("<qt>Exporting <b>%1</b> contacts to the <b>%2</b> "
|
|
|
|
"of the Mobile Phone.<br><br>%3</qt>")
|
|
|
|
.arg(list.count())
|
|
|
|
.arg(gn_memory_type2str(memtype))
|
|
|
|
.arg(buildPhoneInfoString(memstat)) );
|
|
|
|
|
|
|
|
// Now run the loop...
|
|
|
|
phone_entry_no = 1;
|
|
|
|
for ( it = list.begin(); it != list.end(); ++it ) {
|
|
|
|
const TDEABC::Addressee *addr = &(*it);
|
|
|
|
if (addr->isEmpty())
|
|
|
|
continue;
|
|
|
|
// don't write back SIM-card entries !
|
|
|
|
if (addr->custom(APP, "X_GSM_STORE_AT").startsWith("SM"))
|
|
|
|
continue;
|
|
|
|
|
|
|
|
progress->setProgress(entries_written++);
|
|
|
|
|
|
|
|
try_next_phone_entry:
|
|
|
|
this_filter->processEvents();
|
|
|
|
if (m_progressDlg->wasCancelled())
|
|
|
|
break;
|
|
|
|
|
|
|
|
// End of phone memory reached ?
|
|
|
|
if (phone_entry_no > (memstat.used + memstat.free))
|
|
|
|
break;
|
|
|
|
|
|
|
|
GNOKII_DEBUG(TQString("Try to write entry '%1' at phone_entry_no=%2, phone_count=%3\n")
|
|
|
|
.arg(addr->realName()).arg(phone_entry_no).arg(phone_count));
|
|
|
|
|
|
|
|
error = GN_ERR_NONE;
|
|
|
|
|
|
|
|
// is this phone entry empty ?
|
|
|
|
entry_empty = gn_lib_phonebook_entry_isempty(state, memtype, phone_entry_no);
|
|
|
|
if (overwrite_phone_entries) {
|
|
|
|
// overwrite this phonebook entry ...
|
|
|
|
if (!entry_empty)
|
|
|
|
phone_count--;
|
|
|
|
error = xxport_phone_write_entry( phone_entry_no, memtype, addr);
|
|
|
|
phone_entry_no++;
|
|
|
|
} else {
|
|
|
|
// add this phonebook entry if possible ...
|
|
|
|
if (entry_empty) {
|
|
|
|
error = xxport_phone_write_entry( phone_entry_no, memtype, addr);
|
|
|
|
phone_entry_no++;
|
|
|
|
} else {
|
|
|
|
phone_entry_no++;
|
|
|
|
goto try_next_phone_entry;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (error != GN_ERR_NONE)
|
|
|
|
failedList.append(addr->realName());
|
|
|
|
|
|
|
|
// break if we got an error on the first entry
|
|
|
|
if (error != GN_ERR_NONE && it==list.begin())
|
|
|
|
break;
|
|
|
|
|
|
|
|
} // for()
|
|
|
|
|
|
|
|
// if we wanted to overwrite all entries, make sure, that we also
|
|
|
|
// delete all remaining entries in the mobile phone.
|
|
|
|
while (overwrite_phone_entries && error==GN_ERR_NONE && phone_count>0) {
|
|
|
|
if (m_progressDlg->wasCancelled())
|
|
|
|
break;
|
|
|
|
if (!deleteLabelInitialized) {
|
|
|
|
m_progressDlg->setLabel(
|
|
|
|
i18n("<qt><center>"
|
|
|
|
"All selected contacts have been sucessfully copied to "
|
|
|
|
"the Mobile Phone.<br><br>"
|
|
|
|
"Please wait until all remaining orphaned contacts from "
|
|
|
|
"the Mobile Phone have been deleted.</center></qt>") );
|
|
|
|
m_progressDlg->setButtonText(i18n("&Stop Delete"));
|
|
|
|
deleteLabelInitialized = true;
|
|
|
|
progress->setTotalSteps(phone_count);
|
|
|
|
entries_written = 0;
|
|
|
|
progress->setProgress(entries_written);
|
|
|
|
this_filter->processEvents();
|
|
|
|
}
|
|
|
|
if (phone_entry_no > (memstat.used + memstat.free))
|
|
|
|
break;
|
|
|
|
entry_empty = gn_lib_phonebook_entry_isempty(state, memtype, phone_entry_no);
|
|
|
|
if (!entry_empty) {
|
|
|
|
error = xxport_phone_delete_entry(phone_entry_no, memtype);
|
|
|
|
phone_count--;
|
|
|
|
progress->setProgress(++entries_written);
|
|
|
|
this_filter->processEvents();
|
|
|
|
}
|
|
|
|
phone_entry_no++;
|
|
|
|
}
|
|
|
|
|
|
|
|
finish:
|
|
|
|
m_progressDlg->setLabel(i18n("Export to phone finished."));
|
|
|
|
this_filter->processEvents();
|
|
|
|
|
|
|
|
GNOKII_DEBUG("GNOKII export filter finished.\n");
|
|
|
|
|
|
|
|
busterminate();
|
|
|
|
delete m_progressDlg;
|
|
|
|
|
|
|
|
if (!failedList.isEmpty()) {
|
|
|
|
GNOKII_DEBUG(TQString("Failed to export: %1\n").arg(failedList.join(", ")));
|
|
|
|
KMessageBox::informationList(parentWidget(),
|
|
|
|
i18n("<qt>The following contacts could not be exported to the Mobile Phone. "
|
|
|
|
"Possible Reasons for this problem could be:<br><ul>"
|
|
|
|
"<li>The contacts contain more information per entry than the phone can store.</li>"
|
|
|
|
"<li>Your phone does not allow to store multiple addresses, emails, homepages, ...</li>"
|
|
|
|
"<li>other storage size related problems.</li>"
|
|
|
|
"</ul>"
|
|
|
|
"To avoid those kind of problems in the future please reduce the amount of different "
|
|
|
|
"fields in the above contacts.</qt>"),
|
|
|
|
failedList,
|
|
|
|
i18n("Mobile Phone Export") );
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
/******************************************************************************
|
|
|
|
******************************************************************************
|
|
|
|
******************************************************************************
|
|
|
|
******************************************************************************
|
|
|
|
******************************************************************************/
|
|
|
|
|
|
|
|
#elif defined(HAVE_GNOKII_H)
|
|
|
|
|
|
|
|
#ifdef __GNUC__
|
|
|
|
# warning "Please upgrade your gnokii installation to at least version 0.6.13"
|
|
|
|
# warning "Older gnokii versions below 0.6.13 are not binary compatible and"
|
|
|
|
# warning "prevents TDE users to upgrade gnokii to newer versions later."
|
|
|
|
#endif
|
|
|
|
|
|
|
|
/* OLD GNOKII LIBRARIES (< 0.6.13) */
|
|
|
|
|
|
|
|
/* import */
|
|
|
|
static char *lockfile = NULL;
|
|
|
|
static char manufacturer[64], model[GN_MODEL_MAX_LENGTH+1],
|
|
|
|
revision[GN_REVISION_MAX_LENGTH+1], imei[GN_IMEI_MAX_LENGTH+1];
|
|
|
|
static TQString PhoneProductId;
|
|
|
|
|
|
|
|
static struct gn_statemachine state;
|
|
|
|
static gn_data data;
|
|
|
|
|
|
|
|
static void busterminate(void)
|
|
|
|
{
|
|
|
|
gn_sm_functions(GN_OP_Terminate, NULL, &state);
|
|
|
|
if (lockfile) gn_device_unlock(lockfile);
|
|
|
|
}
|
|
|
|
|
|
|
|
static TQString businit(void)
|
|
|
|
{
|
|
|
|
gn_error error;
|
|
|
|
char *aux;
|
|
|
|
|
|
|
|
GNOKII_DEBUG( "Using old gnokii version." );
|
|
|
|
|
|
|
|
#if defined(LIBGNOKII_VERSION)
|
|
|
|
if (gn_cfg_read_default()<0)
|
|
|
|
#else
|
|
|
|
static char *BinDir;
|
|
|
|
if (gn_cfg_read(&BinDir)<0)
|
|
|
|
#endif
|
|
|
|
return i18n("Failed to initialize the gnokii library.");
|
|
|
|
|
|
|
|
if (!gn_cfg_phone_load("", &state))
|
|
|
|
return i18n("Gnokii is not yet configured.");
|
|
|
|
|
|
|
|
// uncomment to debug all gnokii communication on stderr.
|
|
|
|
// gn_log_debug_mask = GN_LOG_T_STDERR;
|
|
|
|
|
|
|
|
gn_data_clear(&data);
|
|
|
|
|
|
|
|
aux = gn_cfg_get(gn_cfg_info, "global", "use_locking");
|
|
|
|
// Defaults to 'no'
|
|
|
|
if (aux && !strcmp(aux, "yes")) {
|
|
|
|
lockfile = gn_device_lock(state.config.port_device);
|
|
|
|
if (lockfile == NULL) {
|
|
|
|
return i18n("Gnokii reports a 'Lock File Error'.\n "
|
|
|
|
"Please exit all other running instances of gnokii, check if you have "
|
|
|
|
"write permissions in the /var/lock directory and try again.");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Initialise the code for the GSM interface.
|
|
|
|
int old_dcd = state.config.require_dcd; // work-around for older gnokii versions
|
|
|
|
state.config.require_dcd = false;
|
|
|
|
error = gn_gsm_initialise(&state);
|
|
|
|
GNOKII_CHECK_ERROR(error);
|
|
|
|
state.config.require_dcd = old_dcd;
|
|
|
|
if (error != GN_ERR_NONE) {
|
|
|
|
busterminate();
|
|
|
|
return i18n("<qt><center>Mobile Phone interface initialization failed.<br><br>"
|
|
|
|
"The returned error message was:<br><b>%1</b><br><br>"
|
|
|
|
"You might try to run \"gnokii --identify\" on the command line to "
|
|
|
|
"check any cable/transport issues and to verify if your gnokii "
|
|
|
|
"configuration is correct.</center></qt>")
|
|
|
|
.arg(gn_error_print(error));
|
|
|
|
}
|
|
|
|
|
|
|
|
// identify phone
|
|
|
|
gn_data_clear(&data);
|
|
|
|
data.manufacturer = manufacturer;
|
|
|
|
data.model = model;
|
|
|
|
data.revision = revision;
|
|
|
|
data.imei = imei;
|
|
|
|
|
|
|
|
TQCString unknown(GN_TO(i18n("Unknown")));
|
|
|
|
tqstrncpy(manufacturer, unknown, sizeof(manufacturer)-1);
|
|
|
|
tqstrncpy(model, unknown, sizeof(model)-1);
|
|
|
|
tqstrncpy(revision, unknown, sizeof(revision)-1);
|
|
|
|
tqstrncpy(imei, unknown, sizeof(imei)-1);
|
|
|
|
|
|
|
|
if (m_progressDlg->wasCancelled())
|
|
|
|
return TQString();
|
|
|
|
else
|
|
|
|
error = gn_sm_functions(GN_OP_Identify, &data, &state);
|
|
|
|
GNOKII_CHECK_ERROR(error);
|
|
|
|
|
|
|
|
GNOKII_DEBUG( TQString("Found mobile phone: %1 %2, Revision: %3, IMEI: %4\n")
|
|
|
|
.arg(manufacturer, model, revision, imei) );
|
|
|
|
|
|
|
|
PhoneProductId = TQString("%1-%2-%3-%4").arg(APP).arg(model).arg(revision).arg(imei);
|
|
|
|
|
|
|
|
return TQString();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// get number of entries in this phone memory type (internal/SIM-card)
|
|
|
|
static gn_error read_phone_memstat( const gn_memory_type memtype, gn_memory_status *memstat )
|
|
|
|
{
|
|
|
|
gn_error error;
|
|
|
|
|
|
|
|
gn_data_clear(&data);
|
|
|
|
memset(memstat, 0, sizeof(*memstat));
|
|
|
|
memstat->memory_type = memtype;
|
|
|
|
data.memory_status = memstat;
|
|
|
|
error = gn_sm_functions(GN_OP_GetMemoryStatus, &data, &state);
|
|
|
|
GNOKII_CHECK_ERROR(error);
|
|
|
|
if (error != GN_ERR_NONE) {
|
|
|
|
switch (memtype) {
|
|
|
|
case GN_MT_SM:
|
|
|
|
// use at least 100 entries
|
|
|
|
memstat->used = 0;
|
|
|
|
memstat->free = 100;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
case GN_MT_ME:
|
|
|
|
// Phone doesn't support ME (5110)
|
|
|
|
memstat->used = memstat->free = 0;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
GNOKII_DEBUG( TQString("\n\nMobile phone memory status: Type: %1, used=%2, free=%3, total=%4\n\n")
|
|
|
|
.arg(memtype).arg(memstat->used).arg(memstat->free).arg(memstat->used+memstat->free) );
|
|
|
|
return error;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// read phone entry #index from memory #memtype
|
|
|
|
static gn_error read_phone_entry( const int index, const gn_memory_type memtype, gn_phonebook_entry *entry )
|
|
|
|
{
|
|
|
|
gn_error error;
|
|
|
|
entry->memory_type = memtype;
|
|
|
|
entry->location = index;
|
|
|
|
data.phonebook_entry = entry;
|
|
|
|
error = gn_sm_functions(GN_OP_ReadPhonebook, &data, &state);
|
|
|
|
GNOKII_CHECK_ERROR(error);
|
|
|
|
return error;
|
|
|
|
}
|
|
|
|
|
|
|
|
static bool phone_entry_empty( const int index, const gn_memory_type memtype )
|
|
|
|
{
|
|
|
|
gn_error error;
|
|
|
|
gn_phonebook_entry entry;
|
|
|
|
entry.memory_type = memtype;
|
|
|
|
entry.location = index;
|
|
|
|
data.phonebook_entry = &entry;
|
|
|
|
error = gn_sm_functions(GN_OP_ReadPhonebook, &data, &state);
|
|
|
|
if (error == GN_ERR_EMPTYLOCATION)
|
|
|
|
return true;
|
|
|
|
GNOKII_CHECK_ERROR(error);
|
|
|
|
if (error == GN_ERR_NONE && entry.empty)
|
|
|
|
return true;
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
static TQString buildPhoneInfoString( const gn_memory_status &memstat )
|
|
|
|
{
|
|
|
|
TQString format = TQString::fromLatin1("<tr><td><b>%1</b></td><td>%2</td></tr>");
|
|
|
|
|
|
|
|
return TQString::fromLatin1("<b>%1</b><br><table>%2%3%4%5%6</table><br>")
|
|
|
|
.arg(i18n("Mobile Phone information:"))
|
|
|
|
.arg(format.arg(i18n("Manufacturer")).arg(GN_FROM(manufacturer)))
|
|
|
|
.arg(format.arg(i18n("Phone model")).arg(GN_FROM(model)))
|
|
|
|
.arg(format.arg(i18n("Revision")).arg(GN_FROM(revision)))
|
|
|
|
.arg(format.arg(i18n("IMEI")).arg(GN_FROM(imei)))
|
|
|
|
.arg(format.arg(i18n("Phonebook status"))
|
|
|
|
.arg(i18n("%1 out of %2 contacts used").arg(memstat.used).arg(memstat.used+memstat.free)));
|
|
|
|
}
|
|
|
|
|
|
|
|
static TQString buildMemoryTypeString( gn_memory_type memtype )
|
|
|
|
{
|
|
|
|
switch (memtype) {
|
|
|
|
case GN_MT_ME: return i18n("internal memory");
|
|
|
|
case GN_MT_SM: return i18n("SIM-card memory");
|
|
|
|
default: return i18n("unknown memory");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// read and evaluate all phone entries
|
|
|
|
static gn_error read_phone_entries( const char *memtypestr, gn_memory_type memtype,
|
|
|
|
TDEABC::AddresseeList *addrList )
|
|
|
|
{
|
|
|
|
gn_error error;
|
|
|
|
|
|
|
|
if (m_progressDlg->wasCancelled())
|
|
|
|
return GN_ERR_NONE;
|
|
|
|
|
|
|
|
KProgress* progress = (KProgress*)m_progressDlg->progressBar();
|
|
|
|
|
|
|
|
progress->setProgress(0);
|
|
|
|
this_filter->processEvents();
|
|
|
|
|
|
|
|
// get number of entries in this phone memory type (internal/SIM-card)
|
|
|
|
gn_memory_status memstat;
|
|
|
|
error = read_phone_memstat(memtype, &memstat);
|
|
|
|
|
|
|
|
gn_phonebook_entry entry;
|
|
|
|
TQStringList addrlist;
|
|
|
|
TDEABC::Address *addr;
|
|
|
|
TQString s, country;
|
|
|
|
|
|
|
|
progress->setTotalSteps(memstat.used);
|
|
|
|
m_progressDlg->setLabel(i18n("<qt>Importing <b>%1</b> contacts from <b>%2</b> of the Mobile Phone.<br><br>%3</qt>")
|
|
|
|
.arg(memstat.used)
|
|
|
|
.arg(buildMemoryTypeString(memtype))
|
|
|
|
.arg(buildPhoneInfoString(memstat)) );
|
|
|
|
|
|
|
|
int num_read = 0;
|
|
|
|
|
|
|
|
for (int i = 1; !m_progressDlg->wasCancelled() && i <= memstat.used + memstat.free; i++) {
|
|
|
|
error = read_phone_entry( i, memtype, &entry );
|
|
|
|
|
|
|
|
progress->setProgress(num_read);
|
|
|
|
this_filter->processEvents();
|
|
|
|
|
|
|
|
if (error == GN_ERR_EMPTYLOCATION)
|
|
|
|
continue;
|
|
|
|
if (error == GN_ERR_INVALIDLOCATION)
|
|
|
|
break;
|
|
|
|
if (error == GN_ERR_INVALIDMEMORYTYPE)
|
|
|
|
break;
|
|
|
|
if (error == GN_ERR_NONE) {
|
|
|
|
GNOKII_DEBUG(TQString("%1: %2, num=%3, location=%4, group=%5, count=%6\n").arg(i).arg(GN_FROM(entry.name))
|
|
|
|
.arg(GN_FROM(entry.number)).arg(entry.location).arg(entry.caller_group).arg(entry.subentries_count));
|
|
|
|
TDEABC::Addressee *a = new TDEABC::Addressee();
|
|
|
|
|
|
|
|
// try to split Name into FamilyName and GivenName
|
|
|
|
s = GN_FROM(entry.name).simplifyWhiteSpace();
|
|
|
|
a->setFormattedName(s); // set formatted name as in Phone
|
|
|
|
if (s.find(',') == -1) {
|
|
|
|
// assumed format: "givenname [... familyname]"
|
|
|
|
addrlist = TQStringList::split(' ', s);
|
|
|
|
if (addrlist.count() == 1) {
|
|
|
|
// only one string -> put it in the GivenName
|
|
|
|
a->setGivenName(s);
|
|
|
|
} else {
|
|
|
|
// multiple strings -> split them.
|
|
|
|
a->setFamilyName(addrlist.last().simplifyWhiteSpace());
|
|
|
|
addrlist.remove(addrlist.last());
|
|
|
|
a->setGivenName(addrlist.join(" ").simplifyWhiteSpace());
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
// assumed format: "familyname, ... givenname"
|
|
|
|
addrlist = TQStringList::split(',', s);
|
|
|
|
a->setFamilyName(addrlist.first().simplifyWhiteSpace());
|
|
|
|
addrlist.remove(addrlist.first());
|
|
|
|
a->setGivenName(addrlist.join(" ").simplifyWhiteSpace());
|
|
|
|
}
|
|
|
|
|
|
|
|
a->insertCustom(APP, "X_GSM_CALLERGROUP", s.setNum(entry.caller_group));
|
|
|
|
a->insertCustom(APP, "X_GSM_STORE_AT", TQString("%1%2").arg(memtypestr).arg(entry.location));
|
|
|
|
|
|
|
|
// set ProductId
|
|
|
|
a->setProductId(PhoneProductId);
|
|
|
|
|
|
|
|
// evaluate timestamp (ignore timezone)
|
|
|
|
TQDateTime datetime;
|
|
|
|
if (entry.date.year<1998)
|
|
|
|
datetime = TQDateTime::currentDateTime();
|
|
|
|
else
|
|
|
|
datetime = TQDateTime( TQDate(entry.date.year, entry.date.month, entry.date.day),
|
|
|
|
TQTime(entry.date.hour, entry.date.minute, entry.date.second) );
|
|
|
|
GNOKII_DEBUG(TQString(" date=%1\n").arg(datetime.toString()));
|
|
|
|
a->setRevision(datetime);
|
|
|
|
|
|
|
|
if (!entry.subentries_count)
|
|
|
|
a->insertPhoneNumber(TDEABC::PhoneNumber(entry.number, TDEABC::PhoneNumber::Work | TDEABC::PhoneNumber::Pref));
|
|
|
|
|
|
|
|
/* scan sub-entries */
|
|
|
|
if (entry.subentries_count)
|
|
|
|
for (int n=0; n<entry.subentries_count; n++) {
|
|
|
|
TQString s = GN_FROM(entry.subentries[n].data.number).simplifyWhiteSpace();
|
|
|
|
GNOKII_DEBUG(TQString(" Subentry#%1, entry_type=%2, number_type=%3, number=%4\n")
|
|
|
|
.arg(n).arg(entry.subentries[n].entry_type)
|
|
|
|
.arg(entry.subentries[n].number_type).arg(s));
|
|
|
|
if (s.isEmpty())
|
|
|
|
continue;
|
|
|
|
switch(entry.subentries[n].entry_type) {
|
|
|
|
case GN_PHONEBOOK_ENTRY_Name:
|
|
|
|
a->setName(s);
|
|
|
|
break;
|
|
|
|
case GN_PHONEBOOK_ENTRY_Email:
|
|
|
|
a->insertEmail(s);
|
|
|
|
break;
|
|
|
|
case GN_PHONEBOOK_ENTRY_Postal:
|
|
|
|
addrlist = TQStringList::split(';', s, true);
|
|
|
|
addr = new TDEABC::Address(TDEABC::Address::Work);
|
|
|
|
if (addrlist.count() <= 1) {
|
|
|
|
addrlist = TQStringList::split(',', s, true);
|
|
|
|
if (addrlist.count() > 1 ) {
|
|
|
|
// assumed format: "Locality, ZIP, Country"
|
|
|
|
addr->setLocality(addrlist[0]);
|
|
|
|
addr->setPostalCode(addrlist[1]);
|
|
|
|
if (!addrlist[2].isEmpty())
|
|
|
|
addr->setCountry(i18n(GN_TO(addrlist[2])));
|
|
|
|
} else {
|
|
|
|
// no idea about the format, just store it.
|
|
|
|
addr->setLocality(s);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
// assumed format: "POBox; Extended; Street; Locality; Region; ZIP [;Country]
|
|
|
|
addr->setPostOfficeBox(addrlist[0]);
|
|
|
|
addr->setExtended(addrlist[1]);
|
|
|
|
addr->setStreet(addrlist[2]);
|
|
|
|
addr->setLocality(addrlist[3]);
|
|
|
|
addr->setRegion(addrlist[4]);
|
|
|
|
addr->setPostalCode(addrlist[5]);
|
|
|
|
country = addrlist[6];
|
|
|
|
if (!country.isEmpty())
|
|
|
|
addr->setCountry(i18n(GN_TO(country)));
|
|
|
|
}
|
|
|
|
a->insertAddress(*addr);
|
|
|
|
delete addr;
|
|
|
|
break;
|
|
|
|
case GN_PHONEBOOK_ENTRY_Note:
|
|
|
|
if (!a->note().isEmpty())
|
|
|
|
s = "\n" + s;
|
|
|
|
a->setNote(a->note()+s);
|
|
|
|
break;
|
|
|
|
case GN_PHONEBOOK_ENTRY_Number:
|
|
|
|
enum TDEABC::PhoneNumber::Types phonetype;
|
|
|
|
switch (entry.subentries[n].number_type) {
|
|
|
|
case GN_PHONEBOOK_NUMBER_Mobile: phonetype = TDEABC::PhoneNumber::Cell; break;
|
|
|
|
case GN_PHONEBOOK_NUMBER_Fax: phonetype = TDEABC::PhoneNumber::Fax; break;
|
|
|
|
case GN_PHONEBOOK_NUMBER_General:
|
|
|
|
case GN_PHONEBOOK_NUMBER_Work: phonetype = TDEABC::PhoneNumber::Work; break;
|
|
|
|
default:
|
|
|
|
case GN_PHONEBOOK_NUMBER_Home: phonetype = TDEABC::PhoneNumber::Home; break;
|
|
|
|
}
|
|
|
|
//if (s == entry.number)
|
|
|
|
// type = (TDEABC::PhoneNumber::Types) (phonetype | TDEABC::PhoneNumber::Pref);
|
|
|
|
a->insertPhoneNumber(TDEABC::PhoneNumber(s, phonetype));
|
|
|
|
break;
|
|
|
|
case GN_PHONEBOOK_ENTRY_URL:
|
|
|
|
a->setUrl(s);
|
|
|
|
break;
|
|
|
|
case GN_PHONEBOOK_ENTRY_Group:
|
|
|
|
a->insertCategory(s);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
GNOKII_DEBUG(TQString(" Not handled id=%1, entry=%2\n")
|
|
|
|
.arg(entry.subentries[n].entry_type).arg(s));
|
|
|
|
break;
|
|
|
|
} // switch()
|
|
|
|
} // if(subentry)
|
|
|
|
|
|
|
|
// add only if entry was valid
|
|
|
|
if (strlen(entry.name) || strlen(entry.number) || entry.subentries_count)
|
|
|
|
addrList->append(*a);
|
|
|
|
|
|
|
|
// did we read all valid phonebook-entries ?
|
|
|
|
num_read++;
|
|
|
|
delete a;
|
|
|
|
if (num_read >= memstat.used)
|
|
|
|
break; // yes, all were read
|
|
|
|
else
|
|
|
|
continue; // no, we are still missing some.
|
|
|
|
}
|
|
|
|
GNOKII_CHECK_ERROR(error);
|
|
|
|
}
|
|
|
|
|
|
|
|
return GN_ERR_NONE;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// export to phone
|
|
|
|
|
|
|
|
static gn_error xxport_phone_write_entry( int phone_location, gn_memory_type memtype,
|
|
|
|
const TDEABC::Addressee *addr)
|
|
|
|
{
|
|
|
|
gn_phonebook_entry entry;
|
|
|
|
TQString s;
|
|
|
|
|
|
|
|
memset(&entry, 0, sizeof(entry));
|
|
|
|
strncpy(entry.name, GN_TO(addr->realName()), sizeof(entry.name)-1);
|
|
|
|
s = addr->phoneNumber(TDEABC::PhoneNumber::Pref).number();
|
|
|
|
if (s.isEmpty())
|
|
|
|
s = addr->phoneNumber(TDEABC::PhoneNumber::Work).number();
|
|
|
|
if (s.isEmpty())
|
|
|
|
s = addr->phoneNumber(TDEABC::PhoneNumber::Home).number();
|
|
|
|
if (s.isEmpty())
|
|
|
|
s = addr->phoneNumber(TDEABC::PhoneNumber::Cell).number();
|
|
|
|
if (s.isEmpty() && addr->phoneNumbers().count()>0)
|
|
|
|
s = (*addr->phoneNumbers().at(0)).number();
|
|
|
|
s = makeValidPhone(s);
|
|
|
|
strncpy(entry.number, s.ascii(), sizeof(entry.number)-1);
|
|
|
|
entry.memory_type = memtype;
|
|
|
|
TQString cg = addr->custom(APP, "X_GSM_CALLERGROUP");
|
|
|
|
if (cg.isEmpty())
|
|
|
|
entry.caller_group = 5; // default group
|
|
|
|
else
|
|
|
|
entry.caller_group = cg.toInt();
|
|
|
|
entry.location = phone_location;
|
|
|
|
|
|
|
|
// set date/revision
|
|
|
|
TQDateTime datetime = addr->revision();
|
|
|
|
TQDate date(datetime.date());
|
|
|
|
TQTime time(datetime.time());
|
|
|
|
entry.date.year = date.year();
|
|
|
|
entry.date.month = date.month();
|
|
|
|
entry.date.day = date.day();
|
|
|
|
entry.date.hour = time.hour();
|
|
|
|
entry.date.minute = time.minute();
|
|
|
|
entry.date.second = time.second();
|
|
|
|
|
|
|
|
GNOKII_DEBUG(TQString("Write #%1: name=%2, number=%3\n").arg(phone_location)
|
|
|
|
.arg(GN_FROM(entry.name)).arg(GN_FROM(entry.number)));
|
|
|
|
|
|
|
|
const TDEABC::Address homeAddr = addr->address(TDEABC::Address::Home);
|
|
|
|
const TDEABC::Address workAddr = addr->address(TDEABC::Address::Work);
|
|
|
|
|
|
|
|
entry.subentries_count = 0;
|
|
|
|
gn_phonebook_subentry *subentry = &entry.subentries[0];
|
|
|
|
// add all phone numbers
|
|
|
|
const TDEABC::PhoneNumber::List phoneList = addr->phoneNumbers();
|
|
|
|
TDEABC::PhoneNumber::List::ConstIterator it;
|
|
|
|
for ( it = phoneList.begin(); it != phoneList.end(); ++it ) {
|
|
|
|
const TDEABC::PhoneNumber *phonenumber = &(*it);
|
|
|
|
s = phonenumber->number();
|
|
|
|
if (s.isEmpty()) continue;
|
|
|
|
subentry->entry_type = GN_PHONEBOOK_ENTRY_Number;
|
|
|
|
gn_phonebook_number_type type;
|
|
|
|
int pn_type = phonenumber->type();
|
|
|
|
if ((pn_type & TDEABC::PhoneNumber::Cell))
|
|
|
|
type = GN_PHONEBOOK_NUMBER_Mobile;
|
|
|
|
else if ((pn_type & TDEABC::PhoneNumber::Fax))
|
|
|
|
type = GN_PHONEBOOK_NUMBER_Fax;
|
|
|
|
else if ((pn_type & TDEABC::PhoneNumber::Home))
|
|
|
|
type = GN_PHONEBOOK_NUMBER_Home;
|
|
|
|
else if ((pn_type & TDEABC::PhoneNumber::Work))
|
|
|
|
type = GN_PHONEBOOK_NUMBER_Work;
|
|
|
|
else type = GN_PHONEBOOK_NUMBER_General;
|
|
|
|
subentry->number_type = type;
|
|
|
|
strncpy(subentry->data.number, makeValidPhone(s).ascii(), sizeof(subentry->data.number)-1);
|
|
|
|
subentry->id = phone_location<<8+entry.subentries_count;
|
|
|
|
entry.subentries_count++;
|
|
|
|
subentry++;
|
|
|
|
if (entry.subentries_count >= GN_PHONEBOOK_SUBENTRIES_MAX_NUMBER)
|
|
|
|
break; // Phonebook full
|
|
|
|
}
|
|
|
|
// add URL
|
|
|
|
s = addr->url().prettyURL();
|
|
|
|
if (!s.isEmpty() && (entry.subentries_count<GN_PHONEBOOK_SUBENTRIES_MAX_NUMBER)) {
|
|
|
|
subentry->entry_type = GN_PHONEBOOK_ENTRY_URL;
|
|
|
|
strncpy(subentry->data.number, GN_TO(s), sizeof(subentry->data.number)-1);
|
|
|
|
entry.subentries_count++;
|
|
|
|
subentry++;
|
|
|
|
}
|
|
|
|
// add E-Mails
|
|
|
|
TQStringList emails = addr->emails();
|
|
|
|
for (unsigned int n=0; n<emails.count(); n++) {
|
|
|
|
if (entry.subentries_count >= GN_PHONEBOOK_SUBENTRIES_MAX_NUMBER)
|
|
|
|
break; // Phonebook full
|
|
|
|
s = emails[n].simplifyWhiteSpace();
|
|
|
|
if (s.isEmpty()) continue;
|
|
|
|
// only one email allowed if we have URLS, notes, addresses (to avoid phone limitations)
|
|
|
|
if (n && !addr->url().isEmpty() && !addr->note().isEmpty() && addr->addresses().count()) {
|
|
|
|
GNOKII_DEBUG(TQString(" DROPPED email %1 in favor of URLs, notes and addresses.\n")
|
|
|
|
.arg(s));
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
subentry->entry_type = GN_PHONEBOOK_ENTRY_Email;
|
|
|
|
strncpy(subentry->data.number, GN_TO(s), sizeof(subentry->data.number)-1);
|
|
|
|
entry.subentries_count++;
|
|
|
|
subentry++;
|
|
|
|
}
|
|
|
|
// add Adresses
|
|
|
|
const TDEABC::Address::List addresses = addr->addresses();
|
|
|
|
TDEABC::Address::List::ConstIterator it2;
|
|
|
|
for ( it2 = addresses.begin(); it2 != addresses.end(); ++it2 ) {
|
|
|
|
if (entry.subentries_count >= GN_PHONEBOOK_SUBENTRIES_MAX_NUMBER)
|
|
|
|
break; // Phonebook full
|
|
|
|
const TDEABC::Address *Addr = &(*it2);
|
|
|
|
if (Addr->isEmpty()) continue;
|
|
|
|
subentry->entry_type = GN_PHONEBOOK_ENTRY_Postal;
|
|
|
|
TQStringList a;
|
|
|
|
TQChar sem(';');
|
|
|
|
TQString sem_repl(TQString::fromLatin1(","));
|
|
|
|
a.append( Addr->postOfficeBox().replace( sem, sem_repl ) );
|
|
|
|
a.append( Addr->extended() .replace( sem, sem_repl ) );
|
|
|
|
a.append( Addr->street() .replace( sem, sem_repl ) );
|
|
|
|
a.append( Addr->locality() .replace( sem, sem_repl ) );
|
|
|
|
a.append( Addr->region() .replace( sem, sem_repl ) );
|
|
|
|
a.append( Addr->postalCode() .replace( sem, sem_repl ) );
|
|
|
|
a.append( Addr->country() .replace( sem, sem_repl ) );
|
|
|
|
s = a.join(sem);
|
|
|
|
strncpy(subentry->data.number, GN_TO(s), sizeof(subentry->data.number)-1);
|
|
|
|
entry.subentries_count++;
|
|
|
|
subentry++;
|
|
|
|
}
|
|
|
|
// add Note
|
|
|
|
s = addr->note().simplifyWhiteSpace();
|
|
|
|
if (!s.isEmpty() && (entry.subentries_count<GN_PHONEBOOK_SUBENTRIES_MAX_NUMBER)) {
|
|
|
|
subentry->entry_type = GN_PHONEBOOK_ENTRY_Note;
|
|
|
|
strncpy(subentry->data.number, GN_TO(s), sizeof(subentry->data.number)-1);
|
|
|
|
entry.subentries_count++;
|
|
|
|
subentry++;
|
|
|
|
}
|
|
|
|
|
|
|
|
// debug output
|
|
|
|
for (int st=0; st<entry.subentries_count; st++) {
|
|
|
|
gn_phonebook_subentry *subentry = &entry.subentries[st];
|
|
|
|
GNOKII_DEBUG(TQString(" SubTel #%1: entry_type=%2, number_type=%3, number=%4\n")
|
|
|
|
.arg(st).arg(subentry->entry_type)
|
|
|
|
.arg(subentry->number_type).arg(GN_FROM(subentry->data.number)));
|
|
|
|
}
|
|
|
|
|
|
|
|
data.phonebook_entry = &entry;
|
|
|
|
gn_error error = gn_sm_functions(GN_OP_WritePhonebook, &data, &state);
|
|
|
|
GNOKII_CHECK_ERROR(error);
|
|
|
|
|
|
|
|
return error;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static gn_error xxport_phone_delete_entry( int phone_location, gn_memory_type memtype )
|
|
|
|
{
|
|
|
|
gn_phonebook_entry entry;
|
|
|
|
memset(&entry, 0, sizeof(entry));
|
|
|
|
entry.empty = 1;
|
|
|
|
entry.memory_type = memtype;
|
|
|
|
entry.location = phone_location;
|
|
|
|
data.phonebook_entry = &entry;
|
|
|
|
GNOKII_DEBUG(TQString("Deleting entry %1\n").arg(phone_location));
|
|
|
|
gn_error error = gn_sm_functions(GN_OP_WritePhonebook, &data, &state);
|
|
|
|
GNOKII_CHECK_ERROR(error);
|
|
|
|
return error;
|
|
|
|
}
|
|
|
|
|
|
|
|
TDEABC::AddresseeList GNOKIIXXPort::importContacts( const TQString& ) const
|
|
|
|
{
|
|
|
|
TDEABC::AddresseeList addrList;
|
|
|
|
|
|
|
|
if (KMessageBox::Continue != KMessageBox::warningContinueCancel(parentWidget(),
|
|
|
|
i18n("<qt>Please connect your Mobile Phone to your computer and press "
|
|
|
|
"<b>Continue</b> to start importing the personal contacts.<br><br>"
|
|
|
|
"Please note that if your Mobile Phone is not properly connected "
|
|
|
|
"the following detection phase might take up to two minutes, during which "
|
|
|
|
"KAddressbook will behave unresponsively.</qt>") ))
|
|
|
|
return addrList;
|
|
|
|
|
|
|
|
m_progressDlg = new KProgressDialog( parentWidget(), "importwidget",
|
|
|
|
i18n("Mobile Phone Import"),
|
|
|
|
i18n("<qt><center>Establishing connection to the Mobile Phone.<br><br>"
|
|
|
|
"Please wait...</center></qt>") );
|
|
|
|
m_progressDlg->setAllowCancel(true);
|
|
|
|
m_progressDlg->progressBar()->setProgress(0);
|
|
|
|
m_progressDlg->progressBar()->setCenterIndicator(true);
|
|
|
|
m_progressDlg->setModal(true);
|
|
|
|
m_progressDlg->setInitialSize(TQSize(450,350));
|
|
|
|
m_progressDlg->show();
|
|
|
|
processEvents();
|
|
|
|
|
|
|
|
m_progressDlg->setCursor( TQt::BusyCursor );
|
|
|
|
TQString errStr = businit();
|
|
|
|
m_progressDlg->unsetCursor();
|
|
|
|
|
|
|
|
if (!errStr.isEmpty()) {
|
|
|
|
KMessageBox::error(parentWidget(), errStr);
|
|
|
|
delete m_progressDlg;
|
|
|
|
return addrList;
|
|
|
|
}
|
|
|
|
|
|
|
|
GNOKII_DEBUG("GNOKII import filter started.\n");
|
|
|
|
m_progressDlg->setButtonText(i18n("&Stop Import"));
|
|
|
|
|
|
|
|
read_phone_entries("ME", GN_MT_ME, &addrList); // internal phone memory
|
|
|
|
read_phone_entries("SM", GN_MT_SM, &addrList); // SIM card
|
|
|
|
|
|
|
|
GNOKII_DEBUG("GNOKII import filter finished.\n");
|
|
|
|
|
|
|
|
busterminate();
|
|
|
|
delete m_progressDlg;
|
|
|
|
|
|
|
|
return addrList;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
bool GNOKIIXXPort::exportContacts( const TDEABC::AddresseeList &list, const TQString & )
|
|
|
|
{
|
|
|
|
if (KMessageBox::Continue != KMessageBox::warningContinueCancel(parentWidget(),
|
|
|
|
i18n("<qt>Please connect your Mobile Phone to your computer and press "
|
|
|
|
"<b>Continue</b> to start exporting the selected personal contacts.<br><br>"
|
|
|
|
"Please note that if your Mobile Phone is not properly connected "
|
|
|
|
"the following detection phase might take up to two minutes, during which "
|
|
|
|
"KAddressbook will behave unresponsively.</qt>") ))
|
|
|
|
return false;
|
|
|
|
|
|
|
|
m_progressDlg = new KProgressDialog( parentWidget(), "importwidget",
|
|
|
|
i18n("Mobile Phone Export"),
|
|
|
|
i18n("<qt><center>Establishing connection to the Mobile Phone.<br><br>"
|
|
|
|
"Please wait...</center></qt>") );
|
|
|
|
m_progressDlg->setAllowCancel(true);
|
|
|
|
m_progressDlg->progressBar()->setProgress(0);
|
|
|
|
m_progressDlg->progressBar()->setCenterIndicator(true);
|
|
|
|
m_progressDlg->setModal(true);
|
|
|
|
m_progressDlg->setInitialSize(TQSize(450,350));
|
|
|
|
m_progressDlg->show();
|
|
|
|
processEvents();
|
|
|
|
|
|
|
|
KProgress* progress = (KProgress*)m_progressDlg->progressBar();
|
|
|
|
|
|
|
|
TDEABC::AddresseeList::ConstIterator it;
|
|
|
|
TQStringList failedList;
|
|
|
|
|
|
|
|
gn_error error;
|
|
|
|
bool deleteLabelInitialized = false;
|
|
|
|
|
|
|
|
m_progressDlg->setCursor( TQt::BusyCursor );
|
|
|
|
TQString errStr = businit();
|
|
|
|
m_progressDlg->unsetCursor();
|
|
|
|
|
|
|
|
if (!errStr.isEmpty()) {
|
|
|
|
KMessageBox::error(parentWidget(), errStr);
|
|
|
|
delete m_progressDlg;
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
GNOKII_DEBUG("GNOKII export filter started.\n");
|
|
|
|
|
|
|
|
gn_memory_type memtype = GN_MT_ME; // internal phone memory
|
|
|
|
|
|
|
|
int phone_count; // num entries in phone
|
|
|
|
bool overwrite_phone_entries = false;
|
|
|
|
int phone_entry_no, entries_written;
|
|
|
|
bool entry_empty;
|
|
|
|
|
|
|
|
// get number of entries in this phone memory
|
|
|
|
gn_memory_status memstat;
|
|
|
|
error = read_phone_memstat(memtype, &memstat);
|
|
|
|
if (error == GN_ERR_NONE) {
|
|
|
|
GNOKII_DEBUG("Writing to internal phone memory.\n");
|
|
|
|
} else {
|
|
|
|
memtype = GN_MT_SM; // try SIM card instead
|
|
|
|
error = read_phone_memstat(memtype, &memstat);
|
|
|
|
if (error != GN_ERR_NONE)
|
|
|
|
goto finish;
|
|
|
|
GNOKII_DEBUG("Writing to SIM card memory.\n");
|
|
|
|
}
|
|
|
|
phone_count = memstat.used;
|
|
|
|
|
|
|
|
if (memstat.free >= (int) list.count()) {
|
|
|
|
if (KMessageBox::No == KMessageBox::questionYesNo(parentWidget(),
|
|
|
|
i18n("<qt>Do you want the selected contacts to be <b>appended</b> to "
|
|
|
|
"the current mobile phonebook or should they <b>replace</b> all "
|
|
|
|
"currently existing phonebook entries ?<br><br>"
|
|
|
|
"Please note, that in case you choose to replace the phonebook "
|
|
|
|
"entries, every contact in your phone will be deleted and only "
|
|
|
|
"the newly exported contacts will be available from inside your phone.</qt>"),
|
|
|
|
i18n("Export to Mobile Phone"),
|
|
|
|
KGuiItem(i18n("&Append to Current Phonebook")),
|
|
|
|
KGuiItem(i18n("&Replace Current Phonebook with New Contacts")) ) )
|
|
|
|
overwrite_phone_entries = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
progress->setTotalSteps(list.count());
|
|
|
|
entries_written = 0;
|
|
|
|
progress->setProgress(entries_written);
|
|
|
|
m_progressDlg->setButtonText(i18n("&Stop Export"));
|
|
|
|
m_progressDlg->setLabel(i18n("<qt>Exporting <b>%1</b> contacts to the <b>%2</b> "
|
|
|
|
"of the Mobile Phone.<br><br>%3</qt>")
|
|
|
|
.arg(list.count())
|
|
|
|
.arg(buildMemoryTypeString(memtype))
|
|
|
|
.arg(buildPhoneInfoString(memstat)) );
|
|
|
|
|
|
|
|
// Now run the loop...
|
|
|
|
phone_entry_no = 1;
|
|
|
|
for ( it = list.begin(); it != list.end(); ++it ) {
|
|
|
|
const TDEABC::Addressee *addr = &(*it);
|
|
|
|
if (addr->isEmpty())
|
|
|
|
continue;
|
|
|
|
// don't write back SIM-card entries !
|
|
|
|
if (addr->custom(APP, "X_GSM_STORE_AT").startsWith("SM"))
|
|
|
|
continue;
|
|
|
|
|
|
|
|
progress->setProgress(entries_written++);
|
|
|
|
|
|
|
|
try_next_phone_entry:
|
|
|
|
this_filter->processEvents();
|
|
|
|
if (m_progressDlg->wasCancelled())
|
|
|
|
break;
|
|
|
|
|
|
|
|
// End of phone memory reached ?
|
|
|
|
if (phone_entry_no > (memstat.used + memstat.free))
|
|
|
|
break;
|
|
|
|
|
|
|
|
GNOKII_DEBUG(TQString("Try to write entry '%1' at phone_entry_no=%2, phone_count=%3\n")
|
|
|
|
.arg(addr->realName()).arg(phone_entry_no).arg(phone_count));
|
|
|
|
|
|
|
|
error = GN_ERR_NONE;
|
|
|
|
|
|
|
|
// is this phone entry empty ?
|
|
|
|
entry_empty = phone_entry_empty(phone_entry_no, memtype);
|
|
|
|
if (overwrite_phone_entries) {
|
|
|
|
// overwrite this phonebook entry ...
|
|
|
|
if (!entry_empty)
|
|
|
|
phone_count--;
|
|
|
|
error = xxport_phone_write_entry( phone_entry_no, memtype, addr);
|
|
|
|
phone_entry_no++;
|
|
|
|
} else {
|
|
|
|
// add this phonebook entry if possible ...
|
|
|
|
if (entry_empty) {
|
|
|
|
error = xxport_phone_write_entry( phone_entry_no, memtype, addr);
|
|
|
|
phone_entry_no++;
|
|
|
|
} else {
|
|
|
|
phone_entry_no++;
|
|
|
|
goto try_next_phone_entry;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (error != GN_ERR_NONE)
|
|
|
|
failedList.append(addr->realName());
|
|
|
|
|
|
|
|
// break if we got an error on the first entry
|
|
|
|
if (error != GN_ERR_NONE && it==list.begin())
|
|
|
|
break;
|
|
|
|
|
|
|
|
} // for()
|
|
|
|
|
|
|
|
// if we wanted to overwrite all entries, make sure, that we also
|
|
|
|
// delete all remaining entries in the mobile phone.
|
|
|
|
while (overwrite_phone_entries && error==GN_ERR_NONE && phone_count>0) {
|
|
|
|
if (m_progressDlg->wasCancelled())
|
|
|
|
break;
|
|
|
|
if (!deleteLabelInitialized) {
|
|
|
|
m_progressDlg->setLabel(
|
|
|
|
i18n("<qt><center>"
|
|
|
|
"All selected contacts have been sucessfully copied to "
|
|
|
|
"the Mobile Phone.<br><br>"
|
|
|
|
"Please wait until all remaining orphaned contacts from "
|
|
|
|
"the Mobile Phone have been deleted.</center></qt>") );
|
|
|
|
m_progressDlg->setButtonText(i18n("&Stop Delete"));
|
|
|
|
deleteLabelInitialized = true;
|
|
|
|
progress->setTotalSteps(phone_count);
|
|
|
|
entries_written = 0;
|
|
|
|
progress->setProgress(entries_written);
|
|
|
|
this_filter->processEvents();
|
|
|
|
}
|
|
|
|
if (phone_entry_no > (memstat.used + memstat.free))
|
|
|
|
break;
|
|
|
|
entry_empty = phone_entry_empty(phone_entry_no, memtype);
|
|
|
|
if (!entry_empty) {
|
|
|
|
error = xxport_phone_delete_entry(phone_entry_no, memtype);
|
|
|
|
phone_count--;
|
|
|
|
progress->setProgress(++entries_written);
|
|
|
|
this_filter->processEvents();
|
|
|
|
}
|
|
|
|
phone_entry_no++;
|
|
|
|
}
|
|
|
|
|
|
|
|
finish:
|
|
|
|
m_progressDlg->setLabel(i18n("Export to phone finished."));
|
|
|
|
this_filter->processEvents();
|
|
|
|
|
|
|
|
GNOKII_DEBUG("GNOKII export filter finished.\n");
|
|
|
|
|
|
|
|
busterminate();
|
|
|
|
delete m_progressDlg;
|
|
|
|
|
|
|
|
if (!failedList.isEmpty()) {
|
|
|
|
GNOKII_DEBUG(TQString("Failed to export: %1\n").arg(failedList.join(", ")));
|
|
|
|
KMessageBox::informationList(parentWidget(),
|
|
|
|
i18n("<qt>The following contacts could not be exported to the Mobile Phone. "
|
|
|
|
"Possible Reasons for this problem could be:<br><ul>"
|
|
|
|
"<li>The contacts contain more information per entry than the phone can store.</li>"
|
|
|
|
"<li>Your phone does not allow to store multiple addresses, emails, homepages, ...</li>"
|
|
|
|
"<li>other storage size related problems.</li>"
|
|
|
|
"</ul>"
|
|
|
|
"To avoid those kind of problems in the future please reduce the amount of different "
|
|
|
|
"fields in the above contacts.</qt>"),
|
|
|
|
failedList,
|
|
|
|
i18n("Mobile Phone Export") );
|
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/******************************************************************************
|
|
|
|
******************************************************************************
|
|
|
|
******************************************************************************
|
|
|
|
******************************************************************************
|
|
|
|
******************************************************************************/
|
|
|
|
|
|
|
|
#else /* no gnokii installed */
|
|
|
|
|
|
|
|
TDEABC::AddresseeList GNOKIIXXPort::importContacts( const TQString& ) const
|
|
|
|
{
|
|
|
|
TDEABC::AddresseeList addrList;
|
|
|
|
KMessageBox::error(parentWidget(), i18n("Gnokii interface is not available.\n"
|
|
|
|
"Please ask your distributor to add gnokii at compile time."));
|
|
|
|
return addrList;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool GNOKIIXXPort::exportContacts( const TDEABC::AddresseeList &list, const TQString & )
|
|
|
|
{
|
|
|
|
Q_UNUSED(list);
|
|
|
|
KMessageBox::error(parentWidget(), i18n("Gnokii interface is not available.\n"
|
|
|
|
"Please ask your distributor to add gnokii at compile time."));
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
#endif /* END OF GNOKII LIB SWITCH */
|
|
|
|
|
|
|
|
/******************************************************************************
|
|
|
|
******************************************************************************
|
|
|
|
******************************************************************************
|
|
|
|
******************************************************************************
|
|
|
|
******************************************************************************/
|
|
|
|
|
|
|
|
#include "gnokii_xxport.moc"
|