summaryrefslogtreecommitdiffstats
path: root/kaddressbook/xxport
diff options
context:
space:
mode:
Diffstat (limited to 'kaddressbook/xxport')
-rw-r--r--kaddressbook/xxport/HACKING38
-rw-r--r--kaddressbook/xxport/Makefile.am64
-rw-r--r--kaddressbook/xxport/bookmark_xxport.cpp72
-rw-r--r--kaddressbook/xxport/bookmark_xxport.desktop103
-rw-r--r--kaddressbook/xxport/bookmark_xxport.h53
-rw-r--r--kaddressbook/xxport/bookmark_xxportui.rc11
-rw-r--r--kaddressbook/xxport/configure.in.bot7
-rw-r--r--kaddressbook/xxport/configure.in.in2
-rw-r--r--kaddressbook/xxport/csv_xxport.cpp129
-rw-r--r--kaddressbook/xxport/csv_xxport.desktop102
-rw-r--r--kaddressbook/xxport/csv_xxport.h46
-rw-r--r--kaddressbook/xxport/csv_xxportui.rc14
-rw-r--r--kaddressbook/xxport/csvimportdialog.cpp962
-rw-r--r--kaddressbook/xxport/csvimportdialog.h124
-rw-r--r--kaddressbook/xxport/dateparser.cpp112
-rw-r--r--kaddressbook/xxport/dateparser.h51
-rw-r--r--kaddressbook/xxport/eudora_xxport.cpp213
-rw-r--r--kaddressbook/xxport/eudora_xxport.desktop104
-rw-r--r--kaddressbook/xxport/eudora_xxport.h49
-rw-r--r--kaddressbook/xxport/eudora_xxportui.rc11
-rw-r--r--kaddressbook/xxport/gnokii_xxport.cpp1609
-rw-r--r--kaddressbook/xxport/gnokii_xxport.desktop103
-rw-r--r--kaddressbook/xxport/gnokii_xxport.h43
-rw-r--r--kaddressbook/xxport/gnokii_xxportui.rc14
-rw-r--r--kaddressbook/xxport/kde2_xxport.cpp79
-rw-r--r--kaddressbook/xxport/kde2_xxport.desktop106
-rw-r--r--kaddressbook/xxport/kde2_xxport.h42
-rw-r--r--kaddressbook/xxport/kde2_xxportui.rc11
-rw-r--r--kaddressbook/xxport/ldif_xxport.cpp140
-rw-r--r--kaddressbook/xxport/ldif_xxport.desktop105
-rw-r--r--kaddressbook/xxport/ldif_xxport.h47
-rw-r--r--kaddressbook/xxport/ldif_xxportui.rc14
-rw-r--r--kaddressbook/xxport/opera_xxport.cpp126
-rw-r--r--kaddressbook/xxport/opera_xxport.desktop103
-rw-r--r--kaddressbook/xxport/opera_xxport.h43
-rw-r--r--kaddressbook/xxport/opera_xxportui.rc11
-rw-r--r--kaddressbook/xxport/pab_mapihd.cpp396
-rw-r--r--kaddressbook/xxport/pab_mapihd.h117
-rw-r--r--kaddressbook/xxport/pab_pablib.cpp333
-rw-r--r--kaddressbook/xxport/pab_pablib.h77
-rw-r--r--kaddressbook/xxport/pab_xxport.cpp71
-rw-r--r--kaddressbook/xxport/pab_xxport.desktop103
-rw-r--r--kaddressbook/xxport/pab_xxport.h217
-rw-r--r--kaddressbook/xxport/pab_xxportui.rc11
-rw-r--r--kaddressbook/xxport/samples/PAB_format.pdfbin0 -> 36137 bytes
-rw-r--r--kaddressbook/xxport/samples/ecdancers.txt193
-rw-r--r--kaddressbook/xxport/samples/netscape.ldif38
-rw-r--r--kaddressbook/xxport/samples/rfc2849.txt1
-rw-r--r--kaddressbook/xxport/vcard_xxport.cpp537
-rw-r--r--kaddressbook/xxport/vcard_xxport.desktop105
-rw-r--r--kaddressbook/xxport/vcard_xxport.h50
-rw-r--r--kaddressbook/xxport/vcard_xxportui.rc15
52 files changed, 7127 insertions, 0 deletions
diff --git a/kaddressbook/xxport/HACKING b/kaddressbook/xxport/HACKING
new file mode 100644
index 000000000..fb02930cd
--- /dev/null
+++ b/kaddressbook/xxport/HACKING
@@ -0,0 +1,38 @@
+Coding Style
+=============
+
+Please use the coding style conventions from kdepim/kaddressbook/HACKING
+if you want to commit your xxport plugin into the cvs.
+
+
+
+Programming a XXPort Plugins
+=============================
+
+Implementing a new xxport plugin is quite easy. But for better understanding
+you should know what happens during the import or export.
+
+At first the modules are loaded by kaddressbook (or better said by the
+xxportmanager class) and an instance of every modul is created.
+In the constructor of a module, the methods createImportAction() and/or
+createExportAction() should be called to register the import and/or
+export gui items in the GUI menu.
+
+Now if the user selects one of the items, the xxportmanager searchs the proper
+plugin.
+
+If the item was a export item, the manager do the following 2 steps:
+ 1) check if the modul requires a sorted list of addresses
+ 2) show a dialog where the user can select, which contacts shall be exported
+ and, if requested, which order the contacts shall have
+Afterwards the exportContacts() method of the module is called with the
+list of all contacts, the user filtered via the dialog.
+
+If the item was an import item, the importContacts() method of the proper
+module is called directly.
+
+To implement your own module you just need to call the createXXportAction()s
+in the constructor and reimplement the importContacts() and/or exportContacts()
+method... thats all :)
+
+<will continue>
diff --git a/kaddressbook/xxport/Makefile.am b/kaddressbook/xxport/Makefile.am
new file mode 100644
index 000000000..5aebc23f2
--- /dev/null
+++ b/kaddressbook/xxport/Makefile.am
@@ -0,0 +1,64 @@
+INCLUDES = -I$(top_srcdir) \
+ -I$(top_srcdir)/kaddressbook/interfaces \
+ -I$(top_srcdir)/kaddressbook \
+ -I$(top_srcdir)/libkdenetwork \
+ $(GPGME_CFLAGS) \
+ $(all_includes)
+
+if compile_GNOKIIXXPORT
+ gnokii_MODULE = libkaddrbk_gnokii_xxport.la
+ gnokii_RCFILE = gnokii_xxportui.rc
+endif
+
+kde_module_LTLIBRARIES = libkaddrbk_csv_xxport.la libkaddrbk_vcard_xxport.la \
+ libkaddrbk_kde2_xxport.la libkaddrbk_bookmark_xxport.la \
+ libkaddrbk_eudora_xxport.la libkaddrbk_ldif_xxport.la \
+ libkaddrbk_opera_xxport.la libkaddrbk_pab_xxport.la $(gnokii_MODULE)
+
+AM_LDFLAGS = -module $(KDE_PLUGIN) $(KDE_RPATH) $(all_libraries) -no-undefined
+
+XXLIBS = $(top_builddir)/kaddressbook/interfaces/libkabinterfaces.la \
+ $(top_builddir)/libkdepim/libkdepim.la
+
+libkaddrbk_csv_xxport_la_SOURCES = csv_xxport.cpp csvimportdialog.cpp dateparser.cpp
+libkaddrbk_csv_xxport_la_LIBADD = $(XXLIBS)
+
+libkaddrbk_vcard_xxport_la_SOURCES = vcard_xxport.cpp
+libkaddrbk_vcard_xxport_la_LIBADD = $(XXLIBS) \
+ $(top_builddir)/kaddressbook/libkaddressbook.la \
+ $(top_builddir)/libkdenetwork/qgpgme/libqgpgme.la
+
+libkaddrbk_kde2_xxport_la_SOURCES = kde2_xxport.cpp
+libkaddrbk_kde2_xxport_la_LIBADD = $(XXLIBS)
+
+libkaddrbk_bookmark_xxport_la_SOURCES = bookmark_xxport.cpp
+libkaddrbk_bookmark_xxport_la_LIBADD = $(XXLIBS)
+
+libkaddrbk_eudora_xxport_la_SOURCES = eudora_xxport.cpp
+libkaddrbk_eudora_xxport_la_LIBADD = $(XXLIBS)
+
+libkaddrbk_ldif_xxport_la_SOURCES = ldif_xxport.cpp
+libkaddrbk_ldif_xxport_la_LIBADD = $(XXLIBS)
+
+libkaddrbk_gnokii_xxport_la_SOURCES = gnokii_xxport.cpp
+libkaddrbk_gnokii_xxport_la_LIBADD = $(XPMLIB) $(LIB_GNOKII) $(XXLIBS)
+
+libkaddrbk_opera_xxport_la_SOURCES = opera_xxport.cpp
+libkaddrbk_opera_xxport_la_LIBADD = $(XXLIBS)
+
+libkaddrbk_pab_xxport_la_SOURCES = pab_xxport.cpp pab_mapihd.cpp pab_pablib.cpp
+libkaddrbk_pab_xxport_la_LIBADD = $(XXLIBS)
+
+noinst_HEADERS = csvimportdialog.h
+
+METASOURCES = AUTO
+
+servicedir = $(kde_servicesdir)/kaddressbook
+service_DATA = csv_xxport.desktop vcard_xxport.desktop kde2_xxport.desktop \
+ bookmark_xxport.desktop eudora_xxport.desktop ldif_xxport.desktop \
+ gnokii_xxport.desktop opera_xxport.desktop pab_xxport.desktop
+
+rcdir = $(kde_datadir)/kaddressbook
+rc_DATA = csv_xxportui.rc vcard_xxportui.rc kde2_xxportui.rc \
+ bookmark_xxportui.rc eudora_xxportui.rc ldif_xxportui.rc \
+ opera_xxportui.rc pab_xxportui.rc $(gnokii_RCFILE)
diff --git a/kaddressbook/xxport/bookmark_xxport.cpp b/kaddressbook/xxport/bookmark_xxport.cpp
new file mode 100644
index 000000000..0a8d71bef
--- /dev/null
+++ b/kaddressbook/xxport/bookmark_xxport.cpp
@@ -0,0 +1,72 @@
+/*
+ This file is part of KAddressbook.
+ Copyright (c) 2003 Alexander Kellett <lypanov@kde.org>
+ Tobias Koenig <tokoe@kde.org>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ 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 Qt, and distribute the resulting executable,
+ without including the source code for Qt in the source distribution.
+*/
+
+#include <kbookmark.h>
+#include <kbookmarkmanager.h>
+#include <kbookmarkmenu.h>
+#include <kbookmarkdombuilder.h>
+#include <klocale.h>
+#include <kstandarddirs.h>
+
+#include "bookmark_xxport.h"
+
+K_EXPORT_KADDRESSBOOK_XXFILTER( libkaddrbk_bookmark_xxport, BookmarkXXPort )
+
+BookmarkXXPort::BookmarkXXPort( KABC::AddressBook *ab, QWidget *parent, const char *name )
+ : KAB::XXPort( ab, parent, name )
+{
+ createExportAction( i18n( "Export Bookmarks Menu..." ) );
+}
+
+bool BookmarkXXPort::exportContacts( const KABC::AddresseeList &list, const QString& )
+{
+ QString fileName = locateLocal( "data", "kabc/bookmarks.xml" );
+
+ KBookmarkManager *mgr = KBookmarkManager::managerForFile( fileName );
+ KBookmarkDomBuilder *builder = new KBookmarkDomBuilder( mgr->root(), mgr );
+ builder->connectImporter( this );
+
+ KABC::AddresseeList::ConstIterator it;
+ emit newFolder( i18n( "AddressBook" ), false, "" );
+ for ( it = list.begin(); it != list.end(); ++it ) {
+ if ( !(*it).url().isEmpty() ) {
+ QString name = (*it).givenName() + " " + (*it).familyName();
+ emit newBookmark( name, (*it).url().url().latin1(), QString( "" ) );
+ }
+ }
+ emit endFolder();
+ delete builder;
+ mgr->save();
+
+ KBookmarkMenu::DynMenuInfo menu;
+ menu.name = i18n( "Addressbook Bookmarks" );
+ menu.location = fileName;
+ menu.type = "xbel";
+ menu.show = true;
+ KBookmarkMenu::setDynamicBookmarks( "kabc", menu );
+
+ return true;
+}
+
+#include "bookmark_xxport.moc"
diff --git a/kaddressbook/xxport/bookmark_xxport.desktop b/kaddressbook/xxport/bookmark_xxport.desktop
new file mode 100644
index 000000000..54d337162
--- /dev/null
+++ b/kaddressbook/xxport/bookmark_xxport.desktop
@@ -0,0 +1,103 @@
+[Desktop Entry]
+X-KDE-Library=libkaddrbk_bookmark_xxport
+Name=KAB Bookmark XXPort Plugin
+Name[af]=KAB boekmerk XXPort inprop module
+Name[be]=Дапаўненне KAB "Экспарт у закладкі"
+Name[bg]=Приставка за XXPort отметки в KAB
+Name[br]=Lugent XXPorzh sined KAB
+Name[bs]=KAB dodatak za XXPort zabilješki
+Name[ca]=Endollable d'importació/exportació de punts per al KAB
+Name[cs]=Exportní modul záložek
+Name[cy]=Ategyn XXPort Tudnodau KAB
+Name[da]=KAB Bogmærke XXPort-plugin
+Name[de]=Lesezeichen-XXPort-Modul für Adressbuch
+Name[el]=Πρόσθετο εξαγωγής σελιδοδεικτών του KAB
+Name[es]=Plugin de KAB para {im,ex}portar marcadores
+Name[et]=KAB järjehoidjate eksportplugin
+Name[eu]=KAB-en laster-marka in/esportazio plugin-a
+Name[fa]=وصلۀ XXPort چوب الف KAB
+Name[fi]=KAB-kirjanmerkkiliitännäinen
+Name[fr]=Module d'import / export de signets pour KAB
+Name[fy]=KAB Blêdwizer XXPort-plugin
+Name[gl]=Extensión XXPort de Marcadores para KAB
+Name[hi]=केएबी पसंदीदा XXपोर्ट प्लगइन
+Name[hu]=KAB könyvjelzőkezelő XXPort bővítőmodul
+Name[is]=Íforrit fyrir KAB XXPort bókarmerki
+Name[ja]=KAB ブックマーク インポート/エクスポートプラグイン
+Name[ka]=KAB სანიშნეების ექსპორტის მოდული
+Name[kk]=Бетбелгіні экспорт ету
+Name[km]=កម្មវិធី​ជំនួយ KAB Bookmark XXPort
+Name[lt]=KAB žymelių XXPort priedas
+Name[ms]=Plug masuk KAB Tanda Laman XXPort
+Name[nb]=KAB-programtillegg for bokmerkeeksport
+Name[nds]=Leesteken-Exportmoduul för KAdressbook
+Name[ne]=KAB पुस्तकचिनो XXPort प्लगइन
+Name[nl]=KAB Bladwijzer XXPort-plugin
+Name[nn]=KAB-bokmerke XXPort-programtillegg
+Name[pl]=Wtyczka KAB do eksportu zakładek
+Name[pt]='Plugin' de Exportação XXPort de Favoritos do KAB
+Name[pt_BR]=Plug-in de Exportação de Marcadores do KAB
+Name[ru]=Экспорт закладок
+Name[sk]=KAB modul pre xxport záložiek
+Name[sl]=Vstavek KAB Bookmark XXPort
+Name[sr]=XXPort прикључак KAB-а за маркере
+Name[sr@Latn]=XXPort priključak KAB-a za markere
+Name[sv]=Adressbokens överföringsinsticksprogram för bokmärken
+Name[ta]=KAB புக்மார்க் ஏற்றுமதி சொருகுப்பொருள்
+Name[tg]=Содироти поягузор
+Name[tr]=KAB Yer imleri XXPort Eklentisi
+Name[uk]=Втулок обміну закладками KAB
+Name[zh_CN]=KAB 书签 XXPort 插件
+Name[zh_TW]=KAB Bookmark XXPort 外掛程式
+Comment=Plugin to export the web addresses of the contacts as bookmarks
+Comment[af]=Inprop module wat die web adresse van kontakte as boekmerke uitvoer
+Comment[bg]=Приставка за експортиране на уеб адресите на контактите, като отметки
+Comment[bs]=Dodatak za izvoz web adresa kontakata u formi zabilješki
+Comment[ca]=Endollable per a exportar les adreces web dels contactes com a punts
+Comment[cs]=Modul pro exportování webových adres kontaktů jako záložky
+Comment[cy]=Ategyn i allforio cyfeiriadau gwê y cysylltau fel tudnodau
+Comment[da]=Plugin til at eksporte netadresser for kontakter som bogmærker
+Comment[de]=Modul zum Export von Web-Adressen der Kontakte als Lesezeichen
+Comment[el]=Πρόσθετο για εξαγωγή των διευθύνσεων ιστοσελίδων των επαφών σαν σελιδοδείκτες
+Comment[es]=Plugin para exportar las direcciones web de los contactos como marcadores
+Comment[et]=Plugin kontaktide veebiaadresside eksportimiseks järjehoidjatena
+Comment[eu]=Kontaktuen web-helbideak laster-markak bezala esportatzeko plugin-a
+Comment[fa]=وصله برای صادرات نشانیهای وب تماسها به عنوان چوب الفها
+Comment[fi]=Liitännäinen, joka muuntaa kontaktien sisältämät verkko-osoitteet kirjanmerkeiksi
+Comment[fr]=Module d'export des adresses internet des contacts en signets
+Comment[fy]=Plugin foar it eksportearjen fan de webadressen fan de kontaktpersoanen as blêdwizers
+Comment[gl]=Extensión para exportar os enderezos web dos contactos como marcadores
+Comment[hi]=सम्पर्कों के वेब पते को पसंदीदा के रूप में निर्यात करने का प्लगइन
+Comment[hu]=Bővítőmodul webcímek exportáláshoz, könyvjelzőként
+Comment[is]=Íforrit til að skrá vefföng tengiliða sem bókarmerki
+Comment[it]=Plugin per esportare come segnalibro gli indirizzi web dei contatti
+Comment[ja]=連絡先のウェブアドレスをブックマークとしてエクスポートするプラグイン
+Comment[ka]= კონტაქტების ვებ-მისამართების სანიშნეებად ექსპორტის მოდული
+Comment[kk]=Контакттың веб адрестерін бетбелгіге экспорттау модулі
+Comment[km]=កម្មវិធី​ជំនួយ​ដើម្បី​នាំចេញ​អាសយដ្ឋាន​បណ្ដាញ​របស់​ទំនាក់ទំនង ជា​ចំណាំ
+Comment[lt]=Priedas skirtas žiniatinklio adresų kontaktuose eksportavimui į žymeles
+Comment[mk]=Приклучок за изнесување на веб-адресите на контактите како обележувачи
+Comment[ms]= Plug masuk untuk eksport alamat web untuk perhubungan sebagai tanda laman
+Comment[nb]=Programtillegg som eksporterer kontaktenes nett-addresser som bokmerker
+Comment[nds]=Moduul för't Exporteren vun Kontakt-Nettadressen as Leestekens
+Comment[ne]=पुस्तकचिनो अनुरुपका सम्पर्कका वेब ठेगानाको निर्यात गर्न प्लगइन गर्नुहोस्
+Comment[nl]=Plugin voor het exporteren van de webadressen van de contactpersonen als bladwijzers
+Comment[nn]=Programtillegg for å eksportera nettadresser av kontaktar som bokmerker
+Comment[pl]=Wtyczka eksportująca adresy WWW z wizytówek jako zakładki
+Comment[pt]=Um 'plugin' para exportar os endereços Web dos contactos como favoritos
+Comment[pt_BR]=Plug-in para exportar os endereços web de contatos como marcadores
+Comment[ru]=Экспорт веб-адресов контактов как закладок
+Comment[sk]=Modul pre export webových adries kontaktov ako záložiek
+Comment[sl]=Vstavek za izvoz spletnih naslovov stikov v obliki zaznamkov
+Comment[sr]=Прикључак за извоз веб-адреса контаката као маркера
+Comment[sr@Latn]=Priključak za izvoz veb-adresa kontakata kao markera
+Comment[sv]=Insticksprogram för export av kontaktwebbadresser som bokmärken
+Comment[ta]=இணைய முகவரிகளின் தொடர்புகளை புத்தக குறிப்புகளாக ஏற்றுவதற்கு சொருகுப்பொருள்
+Comment[tg]=Модул барои содироти веб-адресҳои алоқа ҳамчун поягузор
+Comment[tr]=Bağlantıların web adreslerini yeri imleri olarak aktarmak için eklenti
+Comment[uk]=Втулок для експорту адрес контактів у Тенетах як закладок
+Comment[zh_CN]=将联系人的网址导出为书签的插件
+Comment[zh_TW]=匯出聯絡人的網頁成書籤的外掛程式
+Type=Service
+ServiceTypes=KAddressBook/XXPort
+X-KDE-KAddressBook-XXPortPluginVersion=1
diff --git a/kaddressbook/xxport/bookmark_xxport.h b/kaddressbook/xxport/bookmark_xxport.h
new file mode 100644
index 000000000..5cc186ed6
--- /dev/null
+++ b/kaddressbook/xxport/bookmark_xxport.h
@@ -0,0 +1,53 @@
+/*
+ This file is part of KAddressbook.
+ Copyright (c) 2003 Alexander Kellett <lypanov@kde.org>
+ Tobias Koenig <tokoe@kde.org>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ 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 Qt, and distribute the resulting executable,
+ without including the source code for Qt in the source distribution.
+*/
+
+#ifndef BOOKMARK_XXPORT_H
+#define BOOKMARK_XXPORT_H
+
+#include <xxport.h>
+
+class BookmarkXXPort : public KAB::XXPort
+{
+ Q_OBJECT
+
+ public:
+ BookmarkXXPort( KABC::AddressBook *ab, QWidget *parent, const char *name = 0 );
+
+ QString identifier() const { return "bookmark"; }
+
+ public slots:
+ bool exportContacts( const KABC::AddresseeList &list, const QString &data );
+
+ signals:
+ /**
+ The following signals are used for building a bookmarks file
+ using KBookmarkDomBuilder.
+ */
+ void newBookmark( const QString &text, const QCString &url, const QString &additionnalInfo );
+ void newFolder( const QString &text, bool open, const QString &additionnalInfo );
+ void newSeparator();
+ void endFolder();
+};
+
+#endif
diff --git a/kaddressbook/xxport/bookmark_xxportui.rc b/kaddressbook/xxport/bookmark_xxportui.rc
new file mode 100644
index 000000000..654981465
--- /dev/null
+++ b/kaddressbook/xxport/bookmark_xxportui.rc
@@ -0,0 +1,11 @@
+<?xml version="1.0"?>
+<!DOCTYPE gui>
+<gui name="bookmark_xxport" version="1">
+<MenuBar>
+ <Menu name="file"><text>&amp;File</text>
+ <Menu name="file_export"><text>&amp;Export</text>
+ <Action name="file_export_bookmark"/>
+ </Menu>
+ </Menu>
+</MenuBar>
+</gui>
diff --git a/kaddressbook/xxport/configure.in.bot b/kaddressbook/xxport/configure.in.bot
new file mode 100644
index 000000000..67bc632e9
--- /dev/null
+++ b/kaddressbook/xxport/configure.in.bot
@@ -0,0 +1,7 @@
+if test "x$with_gnokii" = xcheck && test -z "$LIB_GNOKII"; then
+ echo ""
+ echo "libgnokii (http://www.gnokii.org) is missing. The KDE Addressbook mobile phone import/export filter will not be available."
+ echo ""
+ all_tests=bad
+fi
+
diff --git a/kaddressbook/xxport/configure.in.in b/kaddressbook/xxport/configure.in.in
new file mode 100644
index 000000000..3b0da67ae
--- /dev/null
+++ b/kaddressbook/xxport/configure.in.in
@@ -0,0 +1,2 @@
+# $Id$
+AM_CONDITIONAL(compile_GNOKIIXXPORT, test -n "$LIB_GNOKII")
diff --git a/kaddressbook/xxport/csv_xxport.cpp b/kaddressbook/xxport/csv_xxport.cpp
new file mode 100644
index 000000000..31611f390
--- /dev/null
+++ b/kaddressbook/xxport/csv_xxport.cpp
@@ -0,0 +1,129 @@
+/*
+ This file is part of KAddressbook.
+ Copyright (c) 2003 Tobias Koenig <tokoe@kde.org>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ 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 Qt, and distribute the resulting executable,
+ without including the source code for Qt in the source distribution.
+*/
+
+#include <qfile.h>
+
+#include <kfiledialog.h>
+#include <kio/netaccess.h>
+#include <klocale.h>
+#include <kmessagebox.h>
+#include <ktempfile.h>
+#include <kurl.h>
+
+#include "csvimportdialog.h"
+
+#include "csv_xxport.h"
+
+K_EXPORT_KADDRESSBOOK_XXFILTER( libkaddrbk_csv_xxport, CSVXXPort )
+
+CSVXXPort::CSVXXPort( KABC::AddressBook *ab, QWidget *parent, const char *name )
+ : KAB::XXPort( ab, parent, name )
+{
+ createImportAction( i18n( "Import CSV List..." ) );
+ createExportAction( i18n( "Export CSV List..." ) );
+}
+
+bool CSVXXPort::exportContacts( const KABC::AddresseeList &list, const QString& )
+{
+ KURL url = KFileDialog::getSaveURL( "addressbook.csv" );
+ if ( url.isEmpty() )
+ return true;
+
+ if ( !url.isLocalFile() ) {
+ KTempFile tmpFile;
+ if ( tmpFile.status() != 0 ) {
+ QString txt = i18n( "<qt>Unable to open file <b>%1</b>.%2.</qt>" );
+ KMessageBox::error( parentWidget(), txt.arg( url.url() )
+ .arg( strerror( tmpFile.status() ) ) );
+ return false;
+ }
+
+ doExport( tmpFile.file(), list );
+ tmpFile.close();
+
+ return KIO::NetAccess::upload( tmpFile.name(), url, parentWidget() );
+ } else {
+ QFile file( url.path() );
+ if ( !file.open( IO_WriteOnly ) ) {
+ QString txt = i18n( "<qt>Unable to open file <b>%1</b>.</qt>" );
+ KMessageBox::error( parentWidget(), txt.arg( url.path() ) );
+ return false;
+ }
+
+ doExport( &file, list );
+ file.close();
+
+ KMessageBox::information( parentWidget(), i18n( "The contacts have been exported successfully." ) );
+
+ return true;
+ }
+}
+
+KABC::AddresseeList CSVXXPort::importContacts( const QString& ) const
+{
+ CSVImportDialog dlg( addressBook(), parentWidget() );
+ if ( dlg.exec() )
+ return dlg.contacts();
+ else
+ return KABC::AddresseeList();
+}
+
+void CSVXXPort::doExport( QFile *fp, const KABC::AddresseeList &list )
+{
+ QTextStream t( fp );
+ t.setEncoding( QTextStream::Locale );
+
+ KABC::AddresseeList::ConstIterator iter;
+ KABC::Field::List fields = addressBook()->fields();
+ KABC::Field::List::Iterator fieldIter;
+ bool first = true;
+
+ // First output the column headings
+ for ( fieldIter = fields.begin(); fieldIter != fields.end(); ++fieldIter ) {
+ if ( !first )
+ t << ",";
+
+ t << "\"" << (*fieldIter)->label() << "\"";
+ first = false;
+ }
+ t << "\n";
+
+ // Then all the addressee objects
+ KABC::Addressee addr;
+ for ( iter = list.begin(); iter != list.end(); ++iter ) {
+ addr = *iter;
+ first = true;
+
+ for ( fieldIter = fields.begin(); fieldIter != fields.end(); ++fieldIter ) {
+ if ( !first )
+ t << ",";
+
+ t << "\"" << (*fieldIter)->value( addr ).replace( "\n", "\\n" ) << "\"";
+ first = false;
+ }
+
+ t << "\n";
+ }
+}
+
+#include "csv_xxport.moc"
diff --git a/kaddressbook/xxport/csv_xxport.desktop b/kaddressbook/xxport/csv_xxport.desktop
new file mode 100644
index 000000000..de6a51c42
--- /dev/null
+++ b/kaddressbook/xxport/csv_xxport.desktop
@@ -0,0 +1,102 @@
+[Desktop Entry]
+X-KDE-Library=libkaddrbk_csv_xxport
+Name=KAB CSV XXPort Plugin
+Name[af]=KAB CSV XXPort inprop module
+Name[be]=Дапаўненне KAB "Імпарт/Экспарт CSV"
+Name[bg]=Приставка за CSV XXPort на KAB
+Name[br]=Lugent XXPorzh CSV KAB
+Name[bs]=KAB dodatak za CSV XXPort
+Name[ca]=Endollable d'importació/exportació CSV per al KAB
+Name[cs]=Exportní modul CSV
+Name[cy]=Ategyn XXPort CSV KAB
+Name[da]=KAB CSV XXPort-plugin
+Name[de]=CSV-XXPort-Modul für Adressbuch
+Name[el]=Πρόσθετο εισαγωγής/εξαγωγής CSV του KAB
+Name[es]=Plugin de KAB para {im,ex}portar CSV
+Name[et]=KAB CSV eksport/importplugin
+Name[eu]=KAB-en CSV in/esportazioa plugin-a
+Name[fa]=وصلۀ KAB CSV XXPort
+Name[fi]=KAB CSV -liitännäinen
+Name[fr]=Module d'import / export CSV pour KAB
+Name[gl]=Extensión XXPort de CSV para KAB
+Name[he]=תוסף ייבוא/ייצוא של קבצי CSV של KAB
+Name[hi]=केएबी सीएसवी XXपोर्ट प्लगइन
+Name[hu]=KAB XXPort bővítőmodul
+Name[is]=Íforrit fyrir KAV CSV XXPort
+Name[ja]=KAB CSV インポート/エクスポートプラグイン
+Name[ka]=KAB CSV ექსპორტის მოდული
+Name[kk]=CSV файлды экспорт/импорт ету
+Name[km]=កម្មវិធី​ជំនួយ KAB CSV XXPort
+Name[lt]=KAB CSV XXPort priedas
+Name[ms]=Plug masuk KAB CSV XXPort
+Name[nb]=KAB-programtillegg for CSV-eksport
+Name[nds]=CSV-Im-/Exportmoduul för KAdressbook
+Name[ne]=KAB CSV XXPort प्लगइन
+Name[nn]=KAB CSV XXPort programtillegg
+Name[pl]=Wtyczka KAB do importu/eksportu z/do formatu CSV
+Name[pt]='Plugin' XXPort para CSV do KAB
+Name[pt_BR]=Plug-in de Im/Exportação de CSV do KAB
+Name[ru]=Экспорт/импорт в файлы CSV
+Name[sl]=Vstavek KAB CSV XXPort
+Name[sr]=XXPort прикључак KAB-а за CSV
+Name[sr@Latn]=XXPort priključak KAB-a za CSV
+Name[sv]=Adressbokens CSV-överföringsinsticksprogram
+Name[ta]=KAB CSV ஏற்றுமதி சொருகுப்பொருள்
+Name[tg]=Содирот/воридот ба файлҳои CSV
+Name[tr]=KAB CSV XXPort Eklentisi
+Name[uk]=Втулок KAB для обміну через CSV
+Name[zh_CN]=KAB CSV XXPort 插件
+Name[zh_TW]=KAB CSV XXPort 外掛程式
+Comment=Plugin to import and export contacts in CSV format
+Comment[af]=Inprop module wat kontakte in CSV formaat invoer en uitvoer
+Comment[be]=Дапаўненне для імпарту і экспарту кантактаў у фармаце CSV
+Comment[bg]=Приставка за импортиране/експортиране на контактите във формат CSV
+Comment[bs]=Dodatak za uvoz i izvoz kontakata u CSV formatu
+Comment[ca]=Endollable per a importar i exportar contactes en format CSV
+Comment[cs]=Modul pro import a export kontaktů ve formátu CSV
+Comment[cy]=Ategyn i fewnforio ac allforio cysylltau mewn fformat CSV
+Comment[da]=Plugin til at importere og eksportere kontakter i CSV-format
+Comment[de]=Modul zum Import/Export von Kontakten im CSV-Format
+Comment[el]=Πρόσθετο για εισαγωγή και εξαγωγή των επαφών μορφής CSV
+Comment[es]=Plugin para importar y exportar contactos en formato CSV
+Comment[et]=Plugin kontaktide importimiseks ja eksportimiseks CSV vormingus
+Comment[eu]=CSV formatuan kontaktuak esportatu eta inportatzeko plugin-a
+Comment[fa]=وصله برای واردات و صادرات تماسها در قالب CSV
+Comment[fi]=Liitännäinen kontaktien vientiin ja tuontiin CSV-muodossa
+Comment[fr]=Module d'import / export de contacts au format CSV
+Comment[fy]=Plugin foar it ymportearjen en eksportearjen fan kontaktpersoanen yn CSV-formaat
+Comment[gl]=Extensión para importar e exportar contactos e formato CSV
+Comment[hi]=सम्पर्कों को सीएसवी फार्मेट में निर्यात करने का प्लगइन
+Comment[hu]=Bővítőmodul névjegyek importálásához/exportálásához, CSV formátumban
+Comment[is]=Íforrit til að flytja tengiliði inn og út í CSV sniði
+Comment[it]=Plugin per importare ed esportare contatti in formato CSV
+Comment[ja]=CSV フォーマットで連絡先をインポート/エクスポートするプラグイン
+Comment[ka]=კონტაქტების CSV ფორმატით იმპორტ/ექსპორტის მოდული
+Comment[kk]=Контакттарды CSV пішіміне экспорт/импорт ету модулі
+Comment[km]=កម្មវិធី ជំនួយ​ដើម្បី​នាំចូល និង​នាំចេញ​ទំនាក់ទំនង​ក្នុង​ទ្រង់ទ្រាយ​ជា CSV ។
+Comment[lt]=Priedas, skirtas kontaktų eksportui ir importui CSV formatu
+Comment[mk]=Приклучок за внесување и изнесување контакти во CSV-формат
+Comment[ms]=Plug masuk untuk import dan eksport alamat perhubungan di dalam format CSV
+Comment[nb]=Programtillegg for import/eksport av kontakter i CSV-format
+Comment[nds]=Moduul för't Im- un Exporteren vun Kontakten in't CSV-Formaat
+Comment[ne]=CSV ढाँचाका सम्पर्क आयात र निर्यात गर्न प्लगइन गर्नुहोस्
+Comment[nl]=Plugin voor het importeren en exporteren van contactpersonen in CSV-formaat
+Comment[nn]=Programtillegg for å importera og eksportera kontaktar i CSV-format
+Comment[pl]=Wtyczka do importowania i eksportowania wizytówek w formacie CSV
+Comment[pt]=Um 'plugin' para importar e exportar contactos no formato CSV
+Comment[pt_BR]=Plug-in para importar e exportar contatos em formato CSV
+Comment[ru]=Импорт и экспорт контактов в формате CSV
+Comment[sk]=Modul pre import a export kontaktov vo formáte CSV
+Comment[sl]=Vstavek za uvoz in izvoz stikov v obliki CSV
+Comment[sr]=Прикључак за увоз и извоз контаката у CSV формат
+Comment[sr@Latn]=Priključak za uvoz i izvoz kontakata u CSV format
+Comment[sv]=Insticksprogram för import och export av kontakter med CSV-format
+Comment[ta]=CSV வடிவத்தில் ஏற்றுமதி மற்றும் இறக்குமதி தொடர்புகளுக்கான சொருகுப்பொருள்
+Comment[tg]=Модул барои воридот ва содироти алоқа ба формати CSV
+Comment[tr]=CSV biçimindeki bağlantıları alma ve gönderme eklentisi
+Comment[uk]=Втулок для імпорту та експорту контактів у форматі CSV
+Comment[zh_CN]=导入和导出 CSV 格式联系人的插件
+Comment[zh_TW]=以 CSV 格式匯入與匯出聯絡人外掛程式
+Type=Service
+ServiceTypes=KAddressBook/XXPort
+X-KDE-KAddressBook-XXPortPluginVersion=1
diff --git a/kaddressbook/xxport/csv_xxport.h b/kaddressbook/xxport/csv_xxport.h
new file mode 100644
index 000000000..972f4cad4
--- /dev/null
+++ b/kaddressbook/xxport/csv_xxport.h
@@ -0,0 +1,46 @@
+/*
+ This file is part of KAddressbook.
+ Copyright (c) 2003 Tobias Koenig <tokoe@kde.org>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ 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 Qt, and distribute the resulting executable,
+ without including the source code for Qt in the source distribution.
+*/
+
+#ifndef CSV_XXPORT_H
+#define CSV_XXPORT_H
+
+#include <xxport.h>
+
+class CSVXXPort : public KAB::XXPort
+{
+ Q_OBJECT
+
+ public:
+ CSVXXPort( KABC::AddressBook *ab, QWidget *parent, const char *name = 0 );
+
+ QString identifier() const { return "csv"; }
+
+ public slots:
+ bool exportContacts( const KABC::AddresseeList &list, const QString &data );
+ KABC::AddresseeList importContacts( const QString &data ) const;
+
+ private:
+ void doExport( QFile *fp, const KABC::AddresseeList &list );
+};
+
+#endif
diff --git a/kaddressbook/xxport/csv_xxportui.rc b/kaddressbook/xxport/csv_xxportui.rc
new file mode 100644
index 000000000..ff8f78a01
--- /dev/null
+++ b/kaddressbook/xxport/csv_xxportui.rc
@@ -0,0 +1,14 @@
+<?xml version="1.0"?>
+<!DOCTYPE gui>
+<gui name="csv_xxport" version="1">
+<MenuBar>
+ <Menu name="file"><text>&amp;File</text>
+ <Menu name="file_import"><text>&amp;Import</text>
+ <Action name="file_import_csv"/>
+ </Menu>
+ <Menu name="file_export"><text>&amp;Export</text>
+ <Action name="file_export_csv"/>
+ </Menu>
+ </Menu>
+</MenuBar>
+</gui>
diff --git a/kaddressbook/xxport/csvimportdialog.cpp b/kaddressbook/xxport/csvimportdialog.cpp
new file mode 100644
index 000000000..f89222aff
--- /dev/null
+++ b/kaddressbook/xxport/csvimportdialog.cpp
@@ -0,0 +1,962 @@
+/*
+ This file is part of KAddressBook.
+ Copyright (C) 2003 Tobias Koenig <tokoe@kde.org>
+ based on the code of KSpread's CSV Import Dialog
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+
+#include <qbuttongroup.h>
+#include <qcheckbox.h>
+#include <qcombobox.h>
+#include <qlabel.h>
+#include <qlayout.h>
+#include <qlineedit.h>
+#include <qpushbutton.h>
+#include <qradiobutton.h>
+#include <qtable.h>
+#include <qtextcodec.h>
+#include <qtooltip.h>
+
+#include <kapplication.h>
+#include <kdebug.h>
+#include <kdialogbase.h>
+#include <kfiledialog.h>
+#include <klineedit.h>
+#include <klocale.h>
+#include <kinputdialog.h>
+#include <kmessagebox.h>
+#include <kprogress.h>
+#include <kstandarddirs.h>
+#include <kurlrequester.h>
+
+#include "dateparser.h"
+
+#include "csvimportdialog.h"
+
+enum { Local = 0, Guess = 1, Latin1 = 2, Uni = 3, MSBug = 4, Codec = 5 };
+
+CSVImportDialog::CSVImportDialog( KABC::AddressBook *ab, QWidget *parent,
+ const char * name )
+ : KDialogBase( Plain, i18n ( "CSV Import Dialog" ), Ok | Cancel | User1 |
+ User2, Ok, parent, name, true, true ),
+ mAdjustRows( false ),
+ mStartLine( 0 ),
+ mTextQuote( '"' ),
+ mDelimiter( "," ),
+ mAddressBook( ab )
+{
+ initGUI();
+
+ mTypeMap.insert( i18n( "Undefined" ), Undefined );
+ mTypeMap.insert( KABC::Addressee::formattedNameLabel(), FormattedName );
+ mTypeMap.insert( KABC::Addressee::familyNameLabel(), FamilyName );
+ mTypeMap.insert( KABC::Addressee::givenNameLabel(), GivenName );
+ mTypeMap.insert( KABC::Addressee::additionalNameLabel(), AdditionalName );
+ mTypeMap.insert( KABC::Addressee::prefixLabel(), Prefix );
+ mTypeMap.insert( KABC::Addressee::suffixLabel(), Suffix );
+ mTypeMap.insert( KABC::Addressee::nickNameLabel(), NickName );
+ mTypeMap.insert( KABC::Addressee::birthdayLabel(), Birthday );
+
+ mTypeMap.insert( KABC::Addressee::homeAddressStreetLabel(), HomeAddressStreet );
+ mTypeMap.insert( KABC::Addressee::homeAddressLocalityLabel(),
+ HomeAddressLocality );
+ mTypeMap.insert( KABC::Addressee::homeAddressRegionLabel(), HomeAddressRegion );
+ mTypeMap.insert( KABC::Addressee::homeAddressPostalCodeLabel(),
+ HomeAddressPostalCode );
+ mTypeMap.insert( KABC::Addressee::homeAddressCountryLabel(),
+ HomeAddressCountry );
+ mTypeMap.insert( KABC::Addressee::homeAddressLabelLabel(), HomeAddressLabel );
+
+ mTypeMap.insert( KABC::Addressee::businessAddressStreetLabel(),
+ BusinessAddressStreet );
+ mTypeMap.insert( KABC::Addressee::businessAddressLocalityLabel(),
+ BusinessAddressLocality );
+ mTypeMap.insert( KABC::Addressee::businessAddressRegionLabel(),
+ BusinessAddressRegion );
+ mTypeMap.insert( KABC::Addressee::businessAddressPostalCodeLabel(),
+ BusinessAddressPostalCode );
+ mTypeMap.insert( KABC::Addressee::businessAddressCountryLabel(),
+ BusinessAddressCountry );
+ mTypeMap.insert( KABC::Addressee::businessAddressLabelLabel(),
+ BusinessAddressLabel );
+
+ mTypeMap.insert( KABC::Addressee::homePhoneLabel(), HomePhone );
+ mTypeMap.insert( KABC::Addressee::businessPhoneLabel(), BusinessPhone );
+ mTypeMap.insert( KABC::Addressee::mobilePhoneLabel(), MobilePhone );
+ mTypeMap.insert( KABC::Addressee::homeFaxLabel(), HomeFax );
+ mTypeMap.insert( KABC::Addressee::businessFaxLabel(), BusinessFax );
+ mTypeMap.insert( KABC::Addressee::carPhoneLabel(), CarPhone );
+ mTypeMap.insert( KABC::Addressee::isdnLabel(), Isdn );
+ mTypeMap.insert( KABC::Addressee::pagerLabel(), Pager );
+ mTypeMap.insert( KABC::Addressee::emailLabel(), Email );
+ mTypeMap.insert( KABC::Addressee::mailerLabel(), Mailer );
+ mTypeMap.insert( KABC::Addressee::titleLabel(), Title );
+ mTypeMap.insert( KABC::Addressee::roleLabel(), Role );
+ mTypeMap.insert( KABC::Addressee::organizationLabel(), Organization );
+ mTypeMap.insert( KABC::Addressee::noteLabel(), Note );
+ mTypeMap.insert( KABC::Addressee::urlLabel(), URL );
+
+ mCustomCounter = mTypeMap.count();
+ int count = mCustomCounter;
+
+ KABC::Field::List fields = mAddressBook->fields( KABC::Field::CustomCategory );
+ KABC::Field::List::Iterator it;
+ for ( it = fields.begin(); it != fields.end(); ++it, ++count )
+ mTypeMap.insert( (*it)->label(), count );
+
+ reloadCodecs();
+
+ connect( mDelimiterBox, SIGNAL( clicked( int ) ),
+ this, SLOT( delimiterClicked( int ) ) );
+ connect( mDelimiterEdit, SIGNAL( returnPressed() ),
+ this, SLOT( returnPressed() ) );
+ connect( mDelimiterEdit, SIGNAL( textChanged ( const QString& ) ),
+ this, SLOT( textChanged ( const QString& ) ) );
+ connect( mComboLine, SIGNAL( activated( const QString& ) ),
+ this, SLOT( lineSelected( const QString& ) ) );
+ connect( mComboQuote, SIGNAL( activated( const QString& ) ),
+ this, SLOT( textquoteSelected( const QString& ) ) );
+ connect( mIgnoreDuplicates, SIGNAL( stateChanged( int ) ),
+ this, SLOT( ignoreDuplicatesChanged( int ) ) );
+ connect( mCodecCombo, SIGNAL( activated( const QString& ) ),
+ this, SLOT( codecChanged() ) );
+
+ connect( mUrlRequester, SIGNAL( returnPressed( const QString& ) ),
+ this, SLOT( setFile( const QString& ) ) );
+ connect( mUrlRequester, SIGNAL( urlSelected( const QString& ) ),
+ this, SLOT( setFile( const QString& ) ) );
+ connect( mUrlRequester->lineEdit(), SIGNAL( textChanged ( const QString& ) ),
+ this, SLOT( urlChanged( const QString& ) ) );
+
+ connect( this, SIGNAL( user1Clicked() ),
+ this, SLOT( applyTemplate() ) );
+
+ connect( this, SIGNAL( user2Clicked() ),
+ this, SLOT( saveTemplate() ) );
+}
+
+CSVImportDialog::~CSVImportDialog()
+{
+ mCodecs.clear();
+}
+
+KABC::AddresseeList CSVImportDialog::contacts() const
+{
+ DateParser dateParser( mDatePatternEdit->text() );
+ KABC::AddresseeList contacts;
+
+ KProgressDialog progressDialog( mPage );
+ progressDialog.setAutoClose( true );
+ progressDialog.progressBar()->setTotalSteps( mTable->numRows() );
+ progressDialog.setLabel( i18n( "Importing contacts" ) );
+ progressDialog.show();
+
+ kapp->processEvents();
+
+ for ( int row = 1; row < mTable->numRows(); ++row ) {
+ KABC::Addressee a;
+ bool emptyRow = true;
+ KABC::Address addrHome( KABC::Address::Home );
+ KABC::Address addrWork( KABC::Address::Work );
+ for ( int col = 0; col < mTable->numCols(); ++col ) {
+ QComboTableItem *item = static_cast<QComboTableItem*>( mTable->item( 0,
+ col ) );
+ if ( !item ) {
+ kdError() << "ERROR: item cast failed" << endl;
+ continue;
+ }
+
+ QString value = mTable->text( row, col );
+ if ( 1 == row && static_cast<QTableItem *>(item)->text() == value )
+ // we are looking at a header row, stop now
+ break;
+
+ if ( !value.isEmpty() )
+ emptyRow = false;
+
+ switch ( posToType( item->currentItem() ) ) {
+ case Undefined:
+ continue;
+ break;
+ case FormattedName:
+ a.setFormattedName( value );
+ break;
+ case GivenName:
+ a.setGivenName( value );
+ break;
+ case FamilyName:
+ a.setFamilyName( value );
+ break;
+ case AdditionalName:
+ a.setAdditionalName( value );
+ break;
+ case Prefix:
+ a.setPrefix( value );
+ break;
+ case Suffix:
+ a.setSuffix( value );
+ break;
+ case NickName:
+ a.setNickName( value );
+ break;
+ case Birthday:
+ a.setBirthday( dateParser.parse( value ) );
+ break;
+ case Email:
+ if ( !value.isEmpty() )
+ a.insertEmail( value, true );
+ break;
+ case Role:
+ a.setRole( value );
+ break;
+ case Title:
+ a.setTitle( value );
+ break;
+ case Mailer:
+ a.setMailer( value );
+ break;
+ case URL:
+ a.setUrl( KURL( value ) );
+ break;
+ case Organization:
+ a.setOrganization( value );
+ break;
+ case Note:
+ a.setNote( a.note() + value + "\n" );
+ break;
+
+ case HomePhone:
+ if ( !value.isEmpty() ) {
+ KABC::PhoneNumber number( value, KABC::PhoneNumber::Home );
+ a.insertPhoneNumber( number );
+ }
+ break;
+ case BusinessPhone:
+ if ( !value.isEmpty() ) {
+ KABC::PhoneNumber number( value, KABC::PhoneNumber::Work );
+ a.insertPhoneNumber( number );
+ }
+ break;
+ case MobilePhone:
+ if ( !value.isEmpty() ) {
+ KABC::PhoneNumber number( value, KABC::PhoneNumber::Cell );
+ a.insertPhoneNumber( number );
+ }
+ break;
+ case HomeFax:
+ if ( !value.isEmpty() ) {
+ KABC::PhoneNumber number( value, KABC::PhoneNumber::Home |
+ KABC::PhoneNumber::Fax );
+ a.insertPhoneNumber( number );
+ }
+ break;
+ case BusinessFax:
+ if ( !value.isEmpty() ) {
+ KABC::PhoneNumber number( value, KABC::PhoneNumber::Work |
+ KABC::PhoneNumber::Fax );
+ a.insertPhoneNumber( number );
+ }
+ break;
+ case CarPhone:
+ if ( !value.isEmpty() ) {
+ KABC::PhoneNumber number( value, KABC::PhoneNumber::Car );
+ a.insertPhoneNumber( number );
+ }
+ break;
+ case Isdn:
+ if ( !value.isEmpty() ) {
+ KABC::PhoneNumber number( value, KABC::PhoneNumber::Isdn );
+ a.insertPhoneNumber( number );
+ }
+ break;
+ case Pager:
+ if ( !value.isEmpty() ) {
+ KABC::PhoneNumber number( value, KABC::PhoneNumber::Pager );
+ a.insertPhoneNumber( number );
+ }
+ break;
+
+ case HomeAddressStreet:
+ addrHome.setStreet( value );
+ break;
+ case HomeAddressLocality:
+ addrHome.setLocality( value );
+ break;
+ case HomeAddressRegion:
+ addrHome.setRegion( value );
+ break;
+ case HomeAddressPostalCode:
+ addrHome.setPostalCode( value );
+ break;
+ case HomeAddressCountry:
+ addrHome.setCountry( value );
+ break;
+ case HomeAddressLabel:
+ addrHome.setLabel( value );
+ break;
+
+ case BusinessAddressStreet:
+ addrWork.setStreet( value );
+ break;
+ case BusinessAddressLocality:
+ addrWork.setLocality( value );
+ break;
+ case BusinessAddressRegion:
+ addrWork.setRegion( value );
+ break;
+ case BusinessAddressPostalCode:
+ addrWork.setPostalCode( value );
+ break;
+ case BusinessAddressCountry:
+ addrWork.setCountry( value );
+ break;
+ case BusinessAddressLabel:
+ addrWork.setLabel( value );
+ break;
+ default:
+ KABC::Field::List fields = mAddressBook->fields( KABC::Field::CustomCategory );
+ KABC::Field::List::Iterator it;
+
+ int counter = 0;
+ for ( it = fields.begin(); it != fields.end(); ++it ) {
+ if ( counter == (int)( posToType( item->currentItem() ) - mCustomCounter ) ) {
+ (*it)->setValue( a, value );
+ break;
+ }
+ ++counter;
+ }
+ break;
+ }
+ }
+
+ kapp->processEvents();
+
+ if ( progressDialog.wasCancelled() )
+ return KABC::AddresseeList();
+
+ progressDialog.progressBar()->advance( 1 );
+
+ if ( !addrHome.isEmpty() )
+ a.insertAddress( addrHome );
+ if ( !addrWork.isEmpty() )
+ a.insertAddress( addrWork );
+
+ if ( !emptyRow && !a.isEmpty() )
+ contacts.append( a );
+ }
+
+ return contacts;
+}
+
+void CSVImportDialog::initGUI()
+{
+ mPage = plainPage();
+
+ QGridLayout *layout = new QGridLayout( mPage, 1, 1, marginHint(),
+ spacingHint() );
+ QHBoxLayout *hbox = new QHBoxLayout();
+ hbox->setSpacing( spacingHint() );
+
+ QLabel *label = new QLabel( i18n( "File to import:" ), mPage );
+ hbox->addWidget( label );
+
+ mUrlRequester = new KURLRequester( mPage );
+ mUrlRequester->setFilter( "*.csv" );
+ hbox->addWidget( mUrlRequester );
+
+ layout->addMultiCellLayout( hbox, 0, 0, 0, 4 );
+
+ // Delimiter: comma, semicolon, tab, space, other
+ mDelimiterBox = new QButtonGroup( i18n( "Delimiter" ), mPage );
+ mDelimiterBox->setColumnLayout( 0, Qt::Vertical );
+ mDelimiterBox->layout()->setSpacing( spacingHint() );
+ mDelimiterBox->layout()->setMargin( marginHint() );
+ QGridLayout *delimiterLayout = new QGridLayout( mDelimiterBox->layout() );
+ delimiterLayout->setAlignment( Qt::AlignTop );
+ layout->addMultiCellWidget( mDelimiterBox, 1, 4, 0, 0 );
+
+ mRadioComma = new QRadioButton( i18n( "Comma" ), mDelimiterBox );
+ mRadioComma->setChecked( true );
+ delimiterLayout->addWidget( mRadioComma, 0, 0 );
+
+ mRadioSemicolon = new QRadioButton( i18n( "Semicolon" ), mDelimiterBox );
+ delimiterLayout->addWidget( mRadioSemicolon, 0, 1 );
+
+ mRadioTab = new QRadioButton( i18n( "Tabulator" ), mDelimiterBox );
+ delimiterLayout->addWidget( mRadioTab, 1, 0 );
+
+ mRadioSpace = new QRadioButton( i18n( "Space" ), mDelimiterBox );
+ delimiterLayout->addWidget( mRadioSpace, 1, 1 );
+
+ mRadioOther = new QRadioButton( i18n( "Other" ), mDelimiterBox );
+ delimiterLayout->addWidget( mRadioOther, 0, 2 );
+
+ mDelimiterEdit = new QLineEdit( mDelimiterBox );
+ delimiterLayout->addWidget( mDelimiterEdit, 1, 2 );
+
+ mComboLine = new QComboBox( false, mPage );
+ mComboLine->insertItem( i18n( "1" ) );
+ layout->addWidget( mComboLine, 2, 3 );
+
+ mComboQuote = new QComboBox( false, mPage );
+ mComboQuote->insertItem( i18n( "\"" ), 0 );
+ mComboQuote->insertItem( i18n( "'" ), 1 );
+ mComboQuote->insertItem( i18n( "None" ), 2 );
+ layout->addWidget( mComboQuote, 2, 2 );
+
+ mDatePatternEdit = new QLineEdit( mPage );
+ mDatePatternEdit->setText( "Y-M-D" ); // ISO 8601 format as default
+ QToolTip::add( mDatePatternEdit, i18n( "<ul><li>y: year with 2 digits</li>"
+ "<li>Y: year with 4 digits</li>"
+ "<li>m: month with 1 or 2 digits</li>"
+ "<li>M: month with 2 digits</li>"
+ "<li>d: day with 1 or 2 digits</li>"
+ "<li>D: day with 2 digits</li></ul>" ) );
+ layout->addWidget( mDatePatternEdit, 2, 4 );
+
+ label = new QLabel( i18n( "Start at line:" ), mPage );
+ layout->addWidget( label, 1, 3 );
+
+ label = new QLabel( i18n( "Textquote:" ), mPage );
+ layout->addWidget( label, 1, 2 );
+
+ label = new QLabel( i18n( "Date format:" ), mPage );
+ layout->addWidget( label, 1, 4 );
+
+ mIgnoreDuplicates = new QCheckBox( mPage );
+ mIgnoreDuplicates->setText( i18n( "Ignore duplicate delimiters" ) );
+ layout->addMultiCellWidget( mIgnoreDuplicates, 3, 3, 2, 4 );
+
+ mCodecCombo = new QComboBox( mPage );
+ layout->addMultiCellWidget( mCodecCombo, 4, 4, 2, 4 );
+
+ mTable = new QTable( 0, 0, mPage );
+ mTable->setSelectionMode( QTable::NoSelection );
+ mTable->horizontalHeader()->hide();
+ layout->addMultiCellWidget( mTable, 5, 5, 0, 4 );
+
+ setButtonText( User1, i18n( "Apply Template..." ) );
+ setButtonText( User2, i18n( "Save Template..." ) );
+
+ enableButtonOK( false );
+ actionButton( User1 )->setEnabled( false );
+ actionButton( User2 )->setEnabled( false );
+
+ resize( 400, 300 );
+}
+
+void CSVImportDialog::fillTable()
+{
+ int row, column;
+ bool lastCharDelimiter = false;
+ bool ignoreDups = mIgnoreDuplicates->isChecked();
+ enum { S_START, S_QUOTED_FIELD, S_MAYBE_END_OF_QUOTED_FIELD, S_END_OF_QUOTED_FIELD,
+ S_MAYBE_NORMAL_FIELD, S_NORMAL_FIELD } state = S_START;
+
+ QChar x;
+ QString field;
+
+ // store previous assignment
+ mTypeStore.clear();
+ for ( column = 0; column < mTable->numCols(); ++column ) {
+ QComboTableItem *item = static_cast<QComboTableItem*>( mTable->item( 0,
+ column ) );
+ if ( !item || mClearTypeStore )
+ mTypeStore.append( typeToPos( Undefined ) );
+ else if ( item )
+ mTypeStore.append( item->currentItem() );
+ }
+
+ clearTable();
+
+ row = column = 1;
+
+ QTextStream inputStream( mFileArray, IO_ReadOnly );
+
+ // find the current codec
+ int code = mCodecCombo->currentItem();
+ if ( code == Local )
+ inputStream.setEncoding( QTextStream::Locale );
+ else if ( code >= Codec )
+ inputStream.setCodec( mCodecs.at( code - Codec ) );
+ else if ( code == Uni )
+ inputStream.setEncoding( QTextStream::Unicode );
+ else if ( code == MSBug )
+ inputStream.setEncoding( QTextStream::UnicodeReverse );
+ else if ( code == Latin1 )
+ inputStream.setEncoding( QTextStream::Latin1 );
+ else if ( code == Guess ) {
+ QTextCodec* codec = QTextCodec::codecForContent( mFileArray.data(), mFileArray.size() );
+ if ( codec ) {
+ KMessageBox::information( this, i18n( "Using codec '%1'" ).arg( codec->name() ), i18n( "Encoding" ) );
+ inputStream.setCodec( codec );
+ }
+ }
+
+ int maxColumn = 0;
+ while ( !inputStream.atEnd() ) {
+ inputStream >> x; // read one char
+
+ if ( x == '\r' ) inputStream >> x; // eat '\r', to handle DOS/LOSEDOWS files correctly
+
+ switch ( state ) {
+ case S_START :
+ if ( x == mTextQuote ) {
+ state = S_QUOTED_FIELD;
+ } else if ( x == mDelimiter ) {
+ if ( ( ignoreDups == false ) || ( lastCharDelimiter == false ) )
+ ++column;
+ lastCharDelimiter = true;
+ } else if ( x == '\n' ) {
+ ++row;
+ column = 1;
+ } else {
+ field += x;
+ state = S_MAYBE_NORMAL_FIELD;
+ }
+ break;
+ case S_QUOTED_FIELD :
+ if ( x == mTextQuote ) {
+ state = S_MAYBE_END_OF_QUOTED_FIELD;
+ } else if ( x == '\n' && mTextQuote.isNull() ) {
+ setText( row - mStartLine + 1, column, field );
+ field = "";
+ if ( x == '\n' ) {
+ ++row;
+ column = 1;
+ } else {
+ if ( ( ignoreDups == false ) || ( lastCharDelimiter == false ) )
+ ++column;
+ lastCharDelimiter = true;
+ }
+ state = S_START;
+ } else {
+ field += x;
+ }
+ break;
+ case S_MAYBE_END_OF_QUOTED_FIELD :
+ if ( x == mTextQuote ) {
+ field += x;
+ state = S_QUOTED_FIELD;
+ } else if ( x == mDelimiter || x == '\n' ) {
+ setText( row - mStartLine + 1, column, field );
+ field = "";
+ if ( x == '\n' ) {
+ ++row;
+ column = 1;
+ } else {
+ if ( ( ignoreDups == false ) || ( lastCharDelimiter == false ) )
+ ++column;
+ lastCharDelimiter = true;
+ }
+ state = S_START;
+ } else {
+ state = S_END_OF_QUOTED_FIELD;
+ }
+ break;
+ case S_END_OF_QUOTED_FIELD :
+ if ( x == mDelimiter || x == '\n' ) {
+ setText( row - mStartLine + 1, column, field );
+ field = "";
+ if ( x == '\n' ) {
+ ++row;
+ column = 1;
+ } else {
+ if ( ( ignoreDups == false ) || ( lastCharDelimiter == false ) )
+ ++column;
+ lastCharDelimiter = true;
+ }
+ state = S_START;
+ } else {
+ state = S_END_OF_QUOTED_FIELD;
+ }
+ break;
+ case S_MAYBE_NORMAL_FIELD :
+ if ( x == mTextQuote ) {
+ field = "";
+ state = S_QUOTED_FIELD;
+ break;
+ }
+ case S_NORMAL_FIELD :
+ if ( x == mDelimiter || x == '\n' ) {
+ setText( row - mStartLine + 1, column, field );
+ field = "";
+ if ( x == '\n' ) {
+ ++row;
+ column = 1;
+ } else {
+ if ( ( ignoreDups == false ) || ( lastCharDelimiter == false ) )
+ ++column;
+ lastCharDelimiter = true;
+ }
+ state = S_START;
+ } else {
+ field += x;
+ }
+ }
+ if ( x != mDelimiter )
+ lastCharDelimiter = false;
+
+ if ( column > maxColumn )
+ maxColumn = column;
+ }
+
+ // file with only one line without '\n'
+ if ( field.length() > 0 ) {
+ setText( row - mStartLine + 1, column, field );
+ ++row;
+ field = "";
+ }
+
+ adjustRows( row - mStartLine );
+ mTable->setNumCols( maxColumn );
+
+ for ( column = 0; column < mTable->numCols(); ++column ) {
+ QComboTableItem *item = new QComboTableItem( mTable, mTypeMap.keys() );
+ mTable->setItem( 0, column, item );
+ if ( column < (int)mTypeStore.count() )
+ item->setCurrentItem( mTypeStore[ column ] );
+ else
+ item->setCurrentItem( typeToPos( Undefined ) );
+ mTable->adjustColumn( column );
+ }
+
+ resizeColumns();
+}
+
+void CSVImportDialog::clearTable()
+{
+ for ( int row = 0; row < mTable->numRows(); ++row )
+ for ( int column = 0; column < mTable->numCols(); ++column )
+ mTable->clearCell( row, column );
+}
+
+void CSVImportDialog::fillComboBox()
+{
+ mComboLine->clear();
+ for ( int row = 1; row < mTable->numRows() + 1; ++row )
+ mComboLine->insertItem( QString::number( row ), row - 1 );
+}
+
+void CSVImportDialog::reloadCodecs()
+{
+ mCodecCombo->clear();
+
+ mCodecs.clear();
+
+ QTextCodec *codec;
+ for ( int i = 0; ( codec = QTextCodec::codecForIndex( i ) ); i++ )
+ mCodecs.append( codec );
+
+ mCodecCombo->insertItem( i18n( "Local (%1)" ).arg( QTextCodec::codecForLocale()->name() ), Local );
+ mCodecCombo->insertItem( i18n( "[guess]" ), Guess );
+ mCodecCombo->insertItem( i18n( "Latin1" ), Latin1 );
+ mCodecCombo->insertItem( i18n( "Unicode" ), Uni );
+ mCodecCombo->insertItem( i18n( "Microsoft Unicode" ), MSBug );
+
+ for ( uint i = 0; i < mCodecs.count(); i++ )
+ mCodecCombo->insertItem( mCodecs.at( i )->name(), Codec + i );
+}
+
+void CSVImportDialog::setText( int row, int col, const QString& text )
+{
+ if ( row < 1 ) // skipped by the user
+ return;
+
+ if ( mTable->numRows() < row ) {
+ mTable->setNumRows( row + 5000 ); // We add 5000 at a time to limit recalculations
+ mAdjustRows = true;
+ }
+
+ if ( mTable->numCols() < col )
+ mTable->setNumCols( col + 50 ); // We add 50 at a time to limit recalculation
+
+ mTable->setText( row - 1, col - 1, text );
+}
+
+/*
+ * Called after the first fillTable() when number of rows are unknown.
+ */
+void CSVImportDialog::adjustRows( int rows )
+{
+ if ( mAdjustRows ) {
+ mTable->setNumRows( rows );
+ mAdjustRows = false;
+ }
+}
+
+void CSVImportDialog::resizeColumns()
+{
+ QFontMetrics fm = fontMetrics();
+ int width = 0;
+
+ QMap<QString, uint>::ConstIterator it;
+ for ( it = mTypeMap.begin(); it != mTypeMap.end(); ++it ) {
+ width = QMAX( width, fm.width( it.key() ) );
+ }
+
+ for ( int i = 0; i < mTable->numCols(); ++i )
+ mTable->setColumnWidth( i, QMAX( width + 15, mTable->columnWidth( i ) ) );
+}
+
+void CSVImportDialog::returnPressed()
+{
+ if ( mDelimiterBox->id( mDelimiterBox->selected() ) != 4 )
+ return;
+
+ mDelimiter = mDelimiterEdit->text();
+ fillTable();
+}
+
+void CSVImportDialog::textChanged ( const QString& )
+{
+ mRadioOther->setChecked ( true );
+ delimiterClicked( 4 ); // other
+}
+
+void CSVImportDialog::delimiterClicked( int id )
+{
+ switch ( id ) {
+ case 0: // comma
+ mDelimiter = ",";
+ break;
+ case 4: // other
+ mDelimiter = mDelimiterEdit->text();
+ break;
+ case 2: // tab
+ mDelimiter = "\t";
+ break;
+ case 3: // space
+ mDelimiter = " ";
+ break;
+ case 1: // semicolon
+ mDelimiter = ";";
+ break;
+ }
+
+ fillTable();
+}
+
+void CSVImportDialog::textquoteSelected( const QString& mark )
+{
+ if ( mComboQuote->currentItem() == 2 )
+ mTextQuote = 0;
+ else
+ mTextQuote = mark[ 0 ];
+
+ fillTable();
+}
+
+void CSVImportDialog::lineSelected( const QString& line )
+{
+ mStartLine = line.toInt() - 1;
+ fillTable();
+}
+
+void CSVImportDialog::slotOk()
+{
+ bool assigned = false;
+
+ for ( int column = 0; column < mTable->numCols(); ++column ) {
+ QComboTableItem *item = static_cast<QComboTableItem*>( mTable->item( 0,
+ column ) );
+ if ( item && posToType( item->currentItem() ) != Undefined )
+ assigned = true;
+ }
+
+ if ( assigned )
+ KDialogBase::slotOk();
+ else
+ KMessageBox::sorry( this, i18n( "You have to assign at least one column." ) );
+}
+
+void CSVImportDialog::applyTemplate()
+{
+ QMap<uint,int> columnMap;
+ QMap<QString, QString> fileMap;
+ QStringList templates;
+
+ // load all template files
+ QStringList list = KGlobal::dirs()->findAllResources( "data" , QString( kapp->name() ) +
+ "/csv-templates/*.desktop", true, true );
+
+ for ( QStringList::iterator it = list.begin(); it != list.end(); ++it )
+ {
+ KSimpleConfig config( *it, true );
+
+ if ( !config.hasGroup( "csv column map" ) )
+ continue;
+
+ config.setGroup( "Misc" );
+ templates.append( config.readEntry( "Name" ) );
+ fileMap.insert( config.readEntry( "Name" ), *it );
+ }
+
+ // let the user chose, what to take
+ bool ok = false;
+ QString tmp;
+ tmp = KInputDialog::getItem( i18n( "Template Selection" ),
+ i18n( "Please select a template, that matches the CSV file:" ),
+ templates, 0, false, &ok, this );
+
+ if ( !ok )
+ return;
+
+ KSimpleConfig config( fileMap[ tmp ], true );
+ config.setGroup( "General" );
+ mDatePatternEdit->setText( config.readEntry( "DatePattern", "Y-M-D" ) );
+ uint numColumns = config.readUnsignedNumEntry( "Columns" );
+ mDelimiterEdit->setText( config.readEntry( "DelimiterOther" ) );
+ mDelimiterBox->setButton( config.readNumEntry( "DelimiterType" ) );
+ delimiterClicked( config.readNumEntry( "DelimiterType" ) );
+ int quoteType = config.readNumEntry( "QuoteType" );
+ mComboQuote->setCurrentItem( quoteType );
+ textquoteSelected( mComboQuote->currentText() );
+
+ // create the column map
+ config.setGroup( "csv column map" );
+ for ( uint i = 0; i < numColumns; ++i ) {
+ int col = config.readNumEntry( QString::number( i ) );
+ columnMap.insert( i, col );
+ }
+
+ // apply the column map
+ for ( uint column = 0; column < columnMap.count(); ++column ) {
+ int type = columnMap[ column ];
+ QComboTableItem *item = static_cast<QComboTableItem*>( mTable->item( 0,
+ column ) );
+ if ( item )
+ item->setCurrentItem( typeToPos( type ) );
+ }
+}
+
+void CSVImportDialog::saveTemplate()
+{
+ QString fileName = KFileDialog::getSaveFileName(
+ locateLocal( "data", QString( kapp->name() ) + "/csv-templates/" ),
+ "*.desktop", this );
+
+ if ( fileName.isEmpty() )
+ return;
+
+ if ( !fileName.contains( ".desktop" ) )
+ fileName += ".desktop";
+
+ QString name = KInputDialog::getText( i18n( "Template Name" ), i18n( "Please enter a name for the template:" ) );
+
+ if ( name.isEmpty() )
+ return;
+
+ KConfig config( fileName );
+ config.setGroup( "General" );
+ config.writeEntry( "DatePattern", mDatePatternEdit->text() );
+ config.writeEntry( "Columns", mTable->numCols() );
+ config.writeEntry( "DelimiterType", mDelimiterBox->id( mDelimiterBox->selected() ) );
+ config.writeEntry( "DelimiterOther", mDelimiterEdit->text() );
+ config.writeEntry( "QuoteType", mComboQuote->currentItem() );
+
+ config.setGroup( "Misc" );
+ config.writeEntry( "Name", name );
+
+ config.setGroup( "csv column map" );
+
+ for ( int column = 0; column < mTable->numCols(); ++column ) {
+ QComboTableItem *item = static_cast<QComboTableItem*>( mTable->item( 0,
+ column ) );
+ if ( item )
+ config.writeEntry( QString::number( column ), posToType(
+ item->currentItem() ) );
+ else
+ config.writeEntry( QString::number( column ), 0 );
+ }
+
+ config.sync();
+}
+
+QString CSVImportDialog::getText( int row, int col )
+{
+ return mTable->text( row, col );
+}
+
+uint CSVImportDialog::posToType( int pos ) const
+{
+ uint counter = 0;
+ QMap<QString, uint>::ConstIterator it;
+ for ( it = mTypeMap.begin(); it != mTypeMap.end(); ++it, ++counter )
+ if ( counter == (uint)pos )
+ return it.data();
+
+ return 0;
+}
+
+int CSVImportDialog::typeToPos( uint type ) const
+{
+ uint counter = 0;
+ QMap<QString, uint>::ConstIterator it;
+ for ( it = mTypeMap.begin(); it != mTypeMap.end(); ++it, ++counter )
+ if ( it.data() == type )
+ return counter;
+
+ return -1;
+}
+
+void CSVImportDialog::ignoreDuplicatesChanged( int )
+{
+ fillTable();
+}
+
+void CSVImportDialog::setFile( const QString &fileName )
+{
+ if ( fileName.isEmpty() )
+ return;
+
+ QFile file( fileName );
+ if ( !file.open( IO_ReadOnly ) ) {
+ KMessageBox::sorry( this, i18n( "Cannot open input file." ) );
+ file.close();
+ return;
+ }
+
+ mFileArray = file.readAll();
+ file.close();
+
+ mClearTypeStore = true;
+ clearTable();
+ mTable->setNumCols( 0 );
+ mTable->setNumRows( 0 );
+ fillTable();
+ mClearTypeStore = false;
+
+ fillComboBox();
+}
+
+void CSVImportDialog::urlChanged( const QString &file )
+{
+ bool state = !file.isEmpty();
+
+ enableButtonOK( state );
+ actionButton( User1 )->setEnabled( state );
+ actionButton( User2 )->setEnabled( state );
+}
+
+void CSVImportDialog::codecChanged()
+{
+ fillTable();
+}
+
+#include <csvimportdialog.moc>
diff --git a/kaddressbook/xxport/csvimportdialog.h b/kaddressbook/xxport/csvimportdialog.h
new file mode 100644
index 000000000..8e9dd0710
--- /dev/null
+++ b/kaddressbook/xxport/csvimportdialog.h
@@ -0,0 +1,124 @@
+/*
+ This file is part of KAddressBook.
+ Copyright (C) 2003 Tobias Koenig <tokoe@kde.org>
+ based on the code of KSpread's CSV Import Dialog
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#ifndef CSV_IMPORT_DLG_H
+#define CSV_IMPORT_DLG_H
+
+#include <kabc/addressbook.h>
+#include <kabc/addresseelist.h>
+#include <kdialogbase.h>
+
+#include <qvaluelist.h>
+
+class KURLRequester;
+
+class QButtonGroup;
+class QComboBox;
+class QCheckBox;
+class QLineEdit;
+class QPushButton;
+class QRadioButton;
+class QTable;
+
+class CSVImportDialog : public KDialogBase
+{
+ Q_OBJECT
+
+ public:
+ CSVImportDialog( KABC::AddressBook *ab, QWidget *parent,
+ const char *name = 0 );
+ ~CSVImportDialog();
+
+ KABC::AddresseeList contacts() const;
+
+ protected slots:
+ virtual void slotOk();
+
+ private slots:
+ void returnPressed();
+ void delimiterClicked( int id );
+ void lineSelected( const QString& line );
+ void textquoteSelected( const QString& mark );
+ void textChanged ( const QString & );
+ void ignoreDuplicatesChanged( int );
+ void setFile( const QString& );
+ void urlChanged( const QString& );
+ void codecChanged();
+
+ void applyTemplate();
+ void saveTemplate();
+
+ private:
+ enum { Undefined, FormattedName, FamilyName, GivenName, AdditionalName,
+ Prefix, Suffix, NickName, Birthday,
+ HomeAddressStreet, HomeAddressLocality, HomeAddressRegion,
+ HomeAddressPostalCode, HomeAddressCountry, HomeAddressLabel,
+ BusinessAddressStreet, BusinessAddressLocality, BusinessAddressRegion,
+ BusinessAddressPostalCode, BusinessAddressCountry,
+ BusinessAddressLabel,
+ HomePhone, BusinessPhone, MobilePhone, HomeFax, BusinessFax, CarPhone,
+ Isdn, Pager, Email, Mailer, Title, Role, Organization, Note, URL
+ };
+
+ QTable* mTable;
+ QButtonGroup* mDelimiterBox;
+ QRadioButton* mRadioComma;
+ QRadioButton* mRadioSemicolon;
+ QRadioButton* mRadioTab;
+ QRadioButton* mRadioSpace;
+ QRadioButton* mRadioOther;
+ QLineEdit* mDelimiterEdit;
+ QLineEdit* mDatePatternEdit;
+ QComboBox* mComboLine;
+ QComboBox* mComboQuote;
+ QCheckBox* mIgnoreDuplicates;
+ QComboBox* mCodecCombo;
+ QWidget* mPage;
+ KURLRequester* mUrlRequester;
+
+ void initGUI();
+ void fillTable();
+ void clearTable();
+ void fillComboBox();
+ void setText( int row, int col, const QString& text );
+ void adjustRows( int rows );
+ void resizeColumns();
+ QString getText( int row, int col );
+ uint posToType( int pos ) const;
+ int typeToPos( uint type ) const;
+
+ void reloadCodecs();
+ QTextCodec *currentCodec();
+ QPtrList<QTextCodec> mCodecs;
+
+ bool mAdjustRows;
+ int mStartLine;
+ QChar mTextQuote;
+ QString mDelimiter;
+ QByteArray mFileArray;
+ QMap<QString, uint> mTypeMap;
+ KABC::AddressBook *mAddressBook;
+ int mCustomCounter;
+ bool mClearTypeStore;
+ QValueList<int> mTypeStore;
+};
+
+#endif
diff --git a/kaddressbook/xxport/dateparser.cpp b/kaddressbook/xxport/dateparser.cpp
new file mode 100644
index 000000000..ed485e0dd
--- /dev/null
+++ b/kaddressbook/xxport/dateparser.cpp
@@ -0,0 +1,112 @@
+/*
+ This file is part of KAddressbook.
+ Copyright (c) 2003 Tobias Koenig <tokoe@kde.org>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ 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 Qt, and distribute the resulting executable,
+ without including the source code for Qt in the source distribution.
+*/
+
+#include <qdatetime.h>
+
+#include "dateparser.h"
+
+DateParser::DateParser( const QString &pattern )
+ : mPattern( pattern )
+{
+}
+
+DateParser::~DateParser()
+{
+}
+
+QDate DateParser::parse( const QString &dateStr ) const
+{
+ int year, month, day;
+ year = month = day = 0;
+
+ uint currPos = 0;
+ for ( uint i = 0; i < mPattern.length(); ++i ) {
+ if ( mPattern[ i ] == 'y' ) { // 19YY
+ if ( currPos + 1 < dateStr.length() ) {
+ year = 1900 + dateStr.mid( currPos, 2 ).toInt();
+ currPos += 2;
+ } else
+ return QDate();
+ } else if ( mPattern[ i ] == 'Y' ) { // YYYY
+ if ( currPos + 3 < dateStr.length() ) {
+ year = dateStr.mid( currPos, 4 ).toInt();
+ currPos += 4;
+ } else
+ return QDate();
+ } else if ( mPattern[ i ] == 'm' ) { // M or MM
+ if ( currPos + 1 < dateStr.length() ) {
+ if ( dateStr[ currPos ].isDigit() ) {
+ if ( dateStr[ currPos + 1 ].isDigit() ) {
+ month = dateStr.mid( currPos, 2 ).toInt();
+ currPos += 2;
+ continue;
+ }
+ }
+ }
+ if ( currPos < dateStr.length() ) {
+ if ( dateStr[ currPos ].isDigit() ) {
+ month = dateStr.mid( currPos, 1 ).toInt();
+ currPos++;
+ continue;
+ }
+ }
+
+ return QDate();
+ } else if ( mPattern[ i ] == 'M' ) { // 0M or MM
+ if ( currPos + 1 < dateStr.length() ) {
+ month = dateStr.mid( currPos, 2 ).toInt();
+ currPos += 2;
+ } else
+ return QDate();
+ } else if ( mPattern[ i ] == 'd' ) { // D or DD
+ if ( currPos + 1 < dateStr.length() ) {
+ if ( dateStr[ currPos ].isDigit() ) {
+ if ( dateStr[ currPos + 1 ].isDigit() ) {
+ day = dateStr.mid( currPos, 2 ).toInt();
+ currPos += 2;
+ continue;
+ }
+ }
+ }
+ if ( currPos < dateStr.length() ) {
+ if ( dateStr[ currPos ].isDigit() ) {
+ day = dateStr.mid( currPos, 1 ).toInt();
+ currPos++;
+ continue;
+ }
+ }
+
+ return QDate();
+ } else if ( mPattern[ i ] == 'D' ) { // 0D or DD
+ if ( currPos + 1 < dateStr.length() ) {
+ day = dateStr.mid( currPos, 2 ).toInt();
+ currPos += 2;
+ } else
+ return QDate();
+ } else {
+ currPos++;
+ }
+ }
+
+ return QDate( year, month, day );
+}
diff --git a/kaddressbook/xxport/dateparser.h b/kaddressbook/xxport/dateparser.h
new file mode 100644
index 000000000..93eb597da
--- /dev/null
+++ b/kaddressbook/xxport/dateparser.h
@@ -0,0 +1,51 @@
+/*
+ This file is part of KAddressbook.
+ Copyright (c) 2003 Tobias Koenig <tokoe@kde.org>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ 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 Qt, and distribute the resulting executable,
+ without including the source code for Qt in the source distribution.
+*/
+
+#ifndef DATEPARSER_H
+#define DATEPARSER_H
+
+#include <qstring.h>
+
+/**
+ This class parses the date out of a given string with the
+ help of a pattern.
+ The pattern can contains the following key characters:
+ y = year (e.g. 82)
+ Y = year (e.g. 1982)
+ m = month (e.g. 7, 07 or 12)
+ M = month (e.g. 07 or 12)
+ d = day (e.g. 3, 03 or 17)
+ D = day (e.g. 03 or 17 )
+ */
+class DateParser
+{
+ public:
+ DateParser( const QString &pattern );
+ ~DateParser();
+
+ QDate parse( const QString &dateStr ) const;
+ private:
+ QString mPattern;
+};
+
+#endif
diff --git a/kaddressbook/xxport/eudora_xxport.cpp b/kaddressbook/xxport/eudora_xxport.cpp
new file mode 100644
index 000000000..bb4ae373b
--- /dev/null
+++ b/kaddressbook/xxport/eudora_xxport.cpp
@@ -0,0 +1,213 @@
+/*
+ This file is part of KAddressbook.
+ Copyright (c) 2003 Daniel Molkentin <molkentin@kde.org>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ 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 Qt, and distribute the resulting executable,
+ without including the source code for Qt in the source distribution.
+*/
+
+#include <qfile.h>
+
+#include <kfiledialog.h>
+#include <kio/netaccess.h>
+#include <klocale.h>
+#include <kmessagebox.h>
+#include <ktempfile.h>
+#include <kurl.h>
+
+#include <kdebug.h>
+
+#include "eudora_xxport.h"
+
+#define CTRL_C 3
+
+K_EXPORT_KADDRESSBOOK_XXFILTER( libkaddrbk_eudora_xxport, EudoraXXPort )
+
+EudoraXXPort::EudoraXXPort( KABC::AddressBook *ab, QWidget *parent, const char *name )
+ : KAB::XXPort( ab, parent, name )
+{
+ createImportAction( i18n( "Import Eudora Addressbook..." ) );
+}
+
+KABC::AddresseeList EudoraXXPort::importContacts( const QString& ) const
+{
+ QString fileName = KFileDialog::getOpenFileName( QDir::homeDirPath(),
+ "*.[tT][xX][tT]|" + i18n("Eudora Light Addressbook (*.txt)"), 0 );
+ if ( fileName.isEmpty() )
+ return KABC::AddresseeList();
+
+ QFile file( fileName );
+ if ( !file.open( IO_ReadOnly ) )
+ return KABC::AddresseeList();
+
+ QString line;
+ QTextStream stream( &file );
+ KABC::Addressee *a = 0;
+ int bytesRead = 0;
+
+ KABC::AddresseeList list;
+
+ while( !stream.eof() ) {
+ line = stream.readLine();
+ bytesRead += line.length();
+ QString tmp;
+
+ if ( line.startsWith( "alias" ) ) {
+ if ( a ) { // Write it out
+ list << *a;
+ delete a;
+ a = 0;
+ a = new KABC::Addressee();
+ } else
+ a = new KABC::Addressee();
+
+ tmp = key( line ).stripWhiteSpace();
+ if ( !tmp.isEmpty() )
+ a->setFormattedName( tmp );
+
+ tmp = email( line ).stripWhiteSpace();
+ if ( !tmp.isEmpty() )
+ a->insertEmail( tmp );
+ } else if ( line.startsWith( "note" ) ) {
+ if ( !a ) // Must have an alias before a note
+ break;
+
+ tmp = comment( line ).stripWhiteSpace();
+ if ( !tmp.isEmpty() )
+ a->setNote( tmp );
+
+ tmp = get( line, "name" ).stripWhiteSpace();
+ if ( !tmp.isEmpty() )
+ a->setNameFromString( tmp );
+
+ tmp = get( line, "address" ).stripWhiteSpace();
+ if ( !tmp.isEmpty() ) {
+ KABC::Address addr;
+ kdDebug(5720) << tmp << endl; // dump complete address
+ addr.setLabel( tmp );
+ a->insertAddress( addr );
+ }
+
+ tmp = get( line, "phone" ).stripWhiteSpace();
+ if ( !tmp.isEmpty() )
+ a->insertPhoneNumber( KABC::PhoneNumber( tmp, KABC::PhoneNumber::Home ) );
+ }
+ }
+
+ if ( a ) { // Write out address
+ list << *a;
+ delete a;
+ a = 0;
+ }
+
+ file.close();
+
+ return list;
+}
+
+QString EudoraXXPort::key( const QString& line) const
+{
+ int e;
+ QString result;
+ int b = line.find( '\"', 0 );
+
+ if ( b == -1 ) {
+ b = line.find( ' ' );
+ if ( b == -1 )
+ return result;
+
+ b++;
+ e = line.find( ' ', b );
+ result = line.mid( b, e - b );
+
+ return result;
+ }
+
+ b++;
+ e = line.find( '\"', b );
+ if ( e == -1 )
+ return result;
+
+ result = line.mid( b, e - b );
+
+ return result;
+}
+
+QString EudoraXXPort::email( const QString& line ) const
+{
+ int b;
+ QString result;
+ b = line.findRev( '\"' );
+ if ( b == -1 ) {
+ b = line.findRev( ' ' );
+ if ( b == -1 )
+ return result;
+ }
+ result = line.mid( b + 1 );
+
+ return result;
+}
+
+QString EudoraXXPort::comment( const QString& line ) const
+{
+ int b;
+ QString result;
+ uint i;
+ b = line.findRev( '>' );
+ if ( b == -1 ) {
+ b = line.findRev( '\"' );
+ if ( b == -1 )
+ return result;
+ }
+
+ result = line.mid( b + 1 );
+ for ( i = 0; i < result.length(); i++ ) {
+ if ( result[ i ] == CTRL_C )
+ result[ i ] = '\n';
+ }
+
+ return result;
+}
+
+QString EudoraXXPort::get( const QString& line, const QString& key ) const
+{
+ QString fd = "<" + key + ":";
+ int b, e;
+ uint i;
+
+ // Find formatted key, return on error
+ b = line.find( fd );
+ if ( b == -1 )
+ return QString::null;
+
+ b += fd.length();
+ e = line.find( '>', b );
+ if ( e == -1 )
+ return QString::null;
+
+ e--;
+ QString result = line.mid( b, e - b + 1 );
+ for ( i = 0; i < result.length(); i++ ) {
+ if ( result[ i ] == CTRL_C )
+ result[ i ] = '\n';
+ }
+
+ return result;
+}
+
+#include "eudora_xxport.moc"
diff --git a/kaddressbook/xxport/eudora_xxport.desktop b/kaddressbook/xxport/eudora_xxport.desktop
new file mode 100644
index 000000000..a075f3f83
--- /dev/null
+++ b/kaddressbook/xxport/eudora_xxport.desktop
@@ -0,0 +1,104 @@
+[Desktop Entry]
+X-KDE-Library=libkaddrbk_eudora_xxport
+Name=KAB Eudora XXPort Plugin
+Name[af]=KAB Eudora XXPort inprop module
+Name[be]=Дапаўненне KAB "Імпарт/Экспарт Eudora"
+Name[bg]=Приставка за Eudora XXPort на KAB
+Name[br]=Lugent XXPorzh Eudora KAB
+Name[bs]=KAB dodatak za Eudora XXPort
+Name[ca]=Endollable d'importació/exportació Eudora per al KAB
+Name[cs]=Exportní modul do Eudory
+Name[cy]=Ategyn XXPort Eudora KAB
+Name[da]=KAB Eudora XXPort-plugin
+Name[de]=Eudora-XXPort-Modul für Adressbuch
+Name[el]=Πρόσθετο εισαγωγής/εξαγωγής Eudora του KAB
+Name[es]=Plugin de KAB para {ex,im}portar de Eudora
+Name[et]=KAB Eudora eksport/importplugin
+Name[eu]=KAB-en Eudora in/esportazio plugin-a
+Name[fa]=وصلۀ KAB Eudora XXPort
+Name[fi]=KAB Euroda -liitännäinen
+Name[fr]=Module d'import / export Eudora pour KAB
+Name[gl]=Extensión XXPort de Eudora para KA
+Name[he]=תוסף ייבוא/ייצוא עבור Eurdora של KAB
+Name[hi]=केएबी यूडोरा XXपोर्ट प्लगइन
+Name[hu]=KAB Eudora XXPort bővítőmodul
+Name[is]=Íforrit fyrir KAB Eudora XXPort
+Name[ja]=KAB Eudora インポート/エクスポートプラグイン
+Name[ka]= KAB Eudora-სთან ექსპორტის მოდული
+Name[kk]=Eudora-ға экспорт/импорт ету
+Name[km]=កម្មវិធី​ជំនួយ KAB Eudora XXPort
+Name[lt]=KAB Eudora XXPort priedas
+Name[ms]=Plug masuk KAB Eudora XXPort
+Name[nb]=KAB-programtillegg for Eudora-eksport
+Name[nds]=Eudora-Im-/Exportmoduul för KAdressbook
+Name[ne]=KAB यूडोरा XXPort प्लगइन
+Name[nn]=KAB Eudora XXPort programtillegg
+Name[pl]=Wtyczka KAB do importu/eksportu wizytówek Eudory
+Name[pt]='Plugin' XXPort para Eudora do KAB
+Name[pt_BR]=Plug-in de Im/Exportação de/para Eudora do KAB
+Name[ru]=Обмен информацией с Eudora
+Name[sk]=KAB modul pre xxport Eudora
+Name[sl]=Vstavek KAB Eudora XXPort
+Name[sr]=XXPort прикључак KAB-а за Eudora-у
+Name[sr@Latn]=XXPort priključak KAB-a za Eudora-u
+Name[sv]=Adressbokens Eudora-överföringsinsticksprogram
+Name[ta]=KAB யுடோரா XXபோர்ட் சொருகுப்பொருள்
+Name[tg]=Мубодилаи иттилоот бо Eudora
+Name[tr]=KAB Eudora XXPort Eklentisi
+Name[uk]=Втулок KAB для обміну з Eudora
+Name[zh_CN]=KAB Eudora XXPort 插件
+Name[zh_TW]=KAB Eudora XXPort 外掛程式
+Comment=Plugin to import and export Eudora contacts
+Comment[af]=Inprop module wat kontakte in Eudora formaat invoer en uitvoer
+Comment[be]=Дапаўненне для імпарту і экспарту кантактаў Eudora
+Comment[bg]=Приставка за импортиране/експортиране на контактите във формат на Eudora
+Comment[bs]=Dodatak za uvoz i izvoz kontakata iz Eudore
+Comment[ca]=Endollable per a importar i exportar contactes de l'Eudora
+Comment[cs]=Modul pro import a export kontaktů programu Eudora
+Comment[cy]=Ategyn i fewnforio ac allforio cysylltau Eudora
+Comment[da]=Plugin til at importere og eksportere Eudora-kontakter
+Comment[de]=Modul zum Import/Export von Eudora-Kontakten
+Comment[el]=Πρόσθετο για εισαγωγή και εξαγωγή επαφών του Eudora
+Comment[es]=Plugin para importar y exportar contactos de Eudora
+Comment[et]=Plugin Eudora kontaktide importimiseks ja eksportimiseks
+Comment[eu]=Eudora kontaktuak inportatu/esportatzeko plugin-a
+Comment[fa]=وصله برای واردات و صادرات تماسهای Eudora
+Comment[fi]=Liitännäinen Eudora-kontaktien tuomiseen ja viemiseen
+Comment[fr]=Module d'import / export de contacts Eudora
+Comment[fy]=Plugin foar it importearjen en eksportearjen fan Eudora-kontaktpersoanen
+Comment[gl]=Extensión para importar e exportar contactos Eudora
+Comment[hi]=यूडोरा सम्पर्कों को आयात और निर्यात करने का प्लगइन
+Comment[hu]=Bővítőmodul Eudora névjegyek importálásához/exportálásához
+Comment[is]=Íforrit til að flytja inn og út Eudora tengiliði
+Comment[it]=Plugin importare ed esportare contatti Eudora
+Comment[ja]=Eudora の連絡先をインポート/エクスポートするプラグイン
+Comment[ka]=Eudora-ს კონტაქტების იმპორტ/ექსპორტის მოდული
+Comment[kk]=Eudora контакттарды экспорт/импорт ету модулі
+Comment[km]=កម្មវិធី​ជំនួយ​ដើម្បី​នាំចូល និង​នាំចេញ​ទំនាក់ទំនង​របស់ Eudora
+Comment[lt]=Priedas Eudora kontaktų importui ir eksportui
+Comment[mk]=Приклучок за внесување и изнесување контакти од Eudora
+Comment[ms]=Plug masuk untuk import dan eksport alamat perhubungan Eudora
+Comment[nb]=Programtillegg for import/eksport av Eudora-kontakter
+Comment[nds]=Moduul för't Im- un Exporteren vun Eudora-Kontakten
+Comment[ne]=यूडोरा सम्पर्क आयात निर्यात गर्न प्लगइन गर्नुहोस्
+Comment[nl]=Plugin voor het importeren en exporteren van Eudora-contactpersonen
+Comment[nn]=Programtillegg for å importera og eksportera Eudora-kontaktar
+Comment[pl]=Wtyczka do importowania i eksportowania wizytówek z/do Eudory
+Comment[pt]=Um 'plugin' para importar e exportar contactos do Eudora
+Comment[pt_BR]=Plug-in para importar e exportar contatos do Eudora
+Comment[ro]=Modul de importat şi exportat contacte Eudora
+Comment[ru]=Импорт и экспорт контактов Eudora
+Comment[sk]=Modul pre import a export kontaktov Eudora
+Comment[sl]=Vstavek za uvoz in izvoz stikov Eudore
+Comment[sr]=Прикључак за увоз и извоз Eudora контаката
+Comment[sr@Latn]=Priključak za uvoz i izvoz Eudora kontakata
+Comment[sv]=Insticksprogram för import och export av Eudora-kontakter
+Comment[ta]=யுடோரா ஏற்றுமதி மற்றும் இறக்குமதி செய்ய சொருகுப்பொருள்
+Comment[tg]=Модул барои воридот ва содироти алоқаи Eudora
+Comment[tr]=Eudora bağlantılarını alma ve gönderme eklentisi
+Comment[uk]=Втулок для імпорту та експорту контактів з або до Eudora
+Comment[zh_CN]=导入和导出 Eudora 联系人的插件
+Comment[zh_TW]=匯入與匯出 Eudora 聯絡人的外掛程式
+Type=Service
+ServiceTypes=KAddressBook/XXPort
+X-KDE-KAddressBook-XXPortPluginVersion=1
diff --git a/kaddressbook/xxport/eudora_xxport.h b/kaddressbook/xxport/eudora_xxport.h
new file mode 100644
index 000000000..be1df8ead
--- /dev/null
+++ b/kaddressbook/xxport/eudora_xxport.h
@@ -0,0 +1,49 @@
+/*
+ This file is part of KAddressbook.
+ Copyright (c) 2003 Daniel Molkentin <molkentin@kde.org>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ 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 Qt, and distribute the resulting executable,
+ without including the source code for Qt in the source distribution.
+*/
+
+#ifndef EUDORA_XXPORT_H
+#define EUDORA_XXPORT_H
+
+#include <xxport.h>
+
+class EudoraXXPort : public KAB::XXPort
+{
+ Q_OBJECT
+
+ public:
+ EudoraXXPort( KABC::AddressBook *ab, QWidget *parent, const char *name = 0 );
+
+ QString identifier() const { return "eudora"; }
+
+ public slots:
+ KABC::AddresseeList importContacts( const QString &data ) const;
+
+ private:
+ QString get( const QString& line, const QString& key ) const;
+ QString comment( const QString& line ) const;
+ QString email( const QString& line ) const;
+ QString key( const QString& line ) const;
+ int find( const QString& key ) const;
+};
+
+#endif
diff --git a/kaddressbook/xxport/eudora_xxportui.rc b/kaddressbook/xxport/eudora_xxportui.rc
new file mode 100644
index 000000000..0aab8deeb
--- /dev/null
+++ b/kaddressbook/xxport/eudora_xxportui.rc
@@ -0,0 +1,11 @@
+<?xml version="1.0"?>
+<!DOCTYPE gui>
+<gui name="eudora_xxport" version="2">
+<MenuBar>
+ <Menu name="file"><text>&amp;File</text>
+ <Menu name="file_import"><text>&amp;Import</text>
+ <Action name="file_import_eudora"/>
+ </Menu>
+ </Menu>
+</MenuBar>
+</gui>
diff --git a/kaddressbook/xxport/gnokii_xxport.cpp b/kaddressbook/xxport/gnokii_xxport.cpp
new file mode 100644
index 000000000..60675384c
--- /dev/null
+++ b/kaddressbook/xxport/gnokii_xxport.cpp
@@ -0,0 +1,1609 @@
+/*
+ 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 Qt, and distribute the resulting executable,
+ without including the source code for Qt in the source distribution.
+*/
+/*
+ Description:
+ This filter allows you to import and export the KDE 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 <qcursor.h>
+
+#include <kdebug.h>
+#include <klocale.h>
+#include <kmessagebox.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() << QString("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) QString::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( KABC::AddressBook *ab, QWidget *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 QString makeValidPhone( const QString &number )
+{
+ // allowed chars: 0-9, *, #, p, w, +
+ QString num = number.simplifyWhiteSpace();
+ QString 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 QString businit(void)
+{
+ GNOKII_DEBUG( "Using new gnokii version." );
+
+ GNOKII_DEBUG( QString("Compiled with libgnokii version 0x%1\n").arg(QString::number(LIBGNOKII_VERSION,16)) );
+ GNOKII_DEBUG( QString("Using libgnokii runtime version 0x%1\n").arg(QString::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( QString("Found mobile phone: %1 %2, Revision: %3, IMEI: %4\n")
+ .arg(manufacturer, model, revision, imei) );
+
+ return QString::null;
+}
+
+
+// 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( QString("\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 QString buildPhoneInfoString( const gn_memory_status &memstat )
+{
+ QString format = QString::fromLatin1("<tr><td><b>%1</b></td><td>%2</td></tr>");
+
+ return QString::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,
+ KABC::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);
+
+ QStringList addrlist;
+ KABC::Address *addr;
+ QString 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(QString("%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));
+ KABC::Addressee *a = new KABC::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 = QStringList::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 = QStringList::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", QString("%1%2").arg(memtypestr).arg(gn_lib_get_pb_location(state)));
+
+ // set ProductId
+ a->setProductId(QString("%1-%2-%3-%4").arg(APP).arg(model).arg(revision).arg(imei));
+
+ // evaluate timestamp (ignore timezone)
+ QDateTime datetime;
+ gn_timestamp ts = gn_lib_get_pb_date(state);
+ if (ts.year<1998)
+ datetime = QDateTime::currentDateTime();
+ else
+ datetime = QDateTime( QDate(ts.year, ts.month, ts.day),
+ QTime(ts.hour, ts.minute, ts.second) );
+ GNOKII_DEBUG(QString(" date=%1\n").arg(datetime.toString()));
+ a->setRevision(datetime);
+
+ if (!subentries_count)
+ a->insertPhoneNumber(KABC::PhoneNumber(number,
+ KABC::PhoneNumber::Work | KABC::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);
+
+ QString s = GN_FROM(number).simplifyWhiteSpace();
+ GNOKII_DEBUG(QString(" 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 = QStringList::split(';', s, true);
+ addr = new KABC::Address(KABC::Address::Work);
+ if (addrlist.count() <= 1) {
+ addrlist = QStringList::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 KABC::PhoneNumber::Types phonetype;
+ switch (number_type) {
+ case GN_PHONEBOOK_NUMBER_Mobile: phonetype = KABC::PhoneNumber::Cell; break;
+ case GN_PHONEBOOK_NUMBER_Fax: phonetype = KABC::PhoneNumber::Fax; break;
+ case GN_PHONEBOOK_NUMBER_General:
+ case GN_PHONEBOOK_NUMBER_Work: phonetype = KABC::PhoneNumber::Work; break;
+ default:
+ case GN_PHONEBOOK_NUMBER_Home: phonetype = KABC::PhoneNumber::Home; break;
+ }
+ //if (s == entry.number)
+ // type = (KABC::PhoneNumber::Types) (phonetype | KABC::PhoneNumber::Pref);
+ a->insertPhoneNumber(KABC::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(QString(" 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 KABC::Addressee *addr)
+{
+ QString 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(KABC::PhoneNumber::Pref).number();
+ if (s.isEmpty())
+ s = addr->phoneNumber(KABC::PhoneNumber::Work).number();
+ if (s.isEmpty())
+ s = addr->phoneNumber(KABC::PhoneNumber::Home).number();
+ if (s.isEmpty())
+ s = addr->phoneNumber(KABC::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);
+ QString 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
+ QDateTime datetime = addr->revision();
+ QDate date(datetime.date());
+ QTime 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(QString("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 KABC::Address homeAddr = addr->address(KABC::Address::Home);
+ const KABC::Address workAddr = addr->address(KABC::Address::Work);
+
+ // add all phone numbers
+ const KABC::PhoneNumber::List phoneList = addr->phoneNumbers();
+ KABC::PhoneNumber::List::ConstIterator it;
+ for ( it = phoneList.begin(); it != phoneList.end(); ++it ) {
+ const KABC::PhoneNumber *phonenumber = &(*it);
+ s = phonenumber->number();
+ if (s.isEmpty()) continue;
+ gn_phonebook_number_type type;
+ int pn_type = phonenumber->type();
+ if ((pn_type & KABC::PhoneNumber::Cell))
+ type = GN_PHONEBOOK_NUMBER_Mobile;
+ else if ((pn_type & KABC::PhoneNumber::Fax))
+ type = GN_PHONEBOOK_NUMBER_Fax;
+ else if ((pn_type & KABC::PhoneNumber::Home))
+ type = GN_PHONEBOOK_NUMBER_Home;
+ else if ((pn_type & KABC::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
+ QStringList 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(QString(" 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 KABC::Address::List addresses = addr->addresses();
+ KABC::Address::List::ConstIterator it2;
+ for ( it2 = addresses.begin(); it2 != addresses.end(); ++it2 ) {
+ const KABC::Address *Addr = &(*it2);
+ if (Addr->isEmpty()) continue;
+ QStringList a;
+ QChar sem(';');
+ QString sem_repl(QString::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(QString(" 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);
+}
+
+
+KABC::AddresseeList GNOKIIXXPort::importContacts( const QString& ) const
+{
+ KABC::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(QSize(450,350));
+ m_progressDlg->show();
+ processEvents();
+
+#if (QT_VERSION >= 0x030300)
+ m_progressDlg->setCursor( Qt::BusyCursor );
+#endif
+ QString 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 KABC::AddresseeList &list, const QString & )
+{
+ 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(QSize(450,350));
+ m_progressDlg->show();
+ processEvents();
+
+ KProgress* progress = (KProgress*)m_progressDlg->progressBar();
+
+ KABC::AddresseeList::ConstIterator it;
+ QStringList failedList;
+
+ gn_error error;
+ bool deleteLabelInitialized = false;
+
+#if (QT_VERSION >= 0x030300)
+ m_progressDlg->setCursor( Qt::BusyCursor );
+#endif
+ QString 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 KABC::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(QString("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(QString("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 KDE 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 QString 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 QString 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;
+
+ QCString unknown(GN_TO(i18n("Unknown")));
+ qstrncpy(manufacturer, unknown, sizeof(manufacturer)-1);
+ qstrncpy(model, unknown, sizeof(model)-1);
+ qstrncpy(revision, unknown, sizeof(revision)-1);
+ qstrncpy(imei, unknown, sizeof(imei)-1);
+
+ if (m_progressDlg->wasCancelled())
+ return QString::null;
+ else
+ error = gn_sm_functions(GN_OP_Identify, &data, &state);
+ GNOKII_CHECK_ERROR(error);
+
+ GNOKII_DEBUG( QString("Found mobile phone: %1 %2, Revision: %3, IMEI: %4\n")
+ .arg(manufacturer, model, revision, imei) );
+
+ PhoneProductId = QString("%1-%2-%3-%4").arg(APP).arg(model).arg(revision).arg(imei);
+
+ return QString::null;
+}
+
+
+// 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( QString("\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 QString buildPhoneInfoString( const gn_memory_status &memstat )
+{
+ QString format = QString::fromLatin1("<tr><td><b>%1</b></td><td>%2</td></tr>");
+
+ return QString::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 QString 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,
+ KABC::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;
+ QStringList addrlist;
+ KABC::Address *addr;
+ QString 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(QString("%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));
+ KABC::Addressee *a = new KABC::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 = QStringList::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 = QStringList::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", QString("%1%2").arg(memtypestr).arg(entry.location));
+
+ // set ProductId
+ a->setProductId(PhoneProductId);
+
+ // evaluate timestamp (ignore timezone)
+ QDateTime datetime;
+ if (entry.date.year<1998)
+ datetime = QDateTime::currentDateTime();
+ else
+ datetime = QDateTime( QDate(entry.date.year, entry.date.month, entry.date.day),
+ QTime(entry.date.hour, entry.date.minute, entry.date.second) );
+ GNOKII_DEBUG(QString(" date=%1\n").arg(datetime.toString()));
+ a->setRevision(datetime);
+
+ if (!entry.subentries_count)
+ a->insertPhoneNumber(KABC::PhoneNumber(entry.number, KABC::PhoneNumber::Work | KABC::PhoneNumber::Pref));
+
+ /* scan sub-entries */
+ if (entry.subentries_count)
+ for (int n=0; n<entry.subentries_count; n++) {
+ QString s = GN_FROM(entry.subentries[n].data.number).simplifyWhiteSpace();
+ GNOKII_DEBUG(QString(" 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 = QStringList::split(';', s, true);
+ addr = new KABC::Address(KABC::Address::Work);
+ if (addrlist.count() <= 1) {
+ addrlist = QStringList::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 KABC::PhoneNumber::Types phonetype;
+ switch (entry.subentries[n].number_type) {
+ case GN_PHONEBOOK_NUMBER_Mobile: phonetype = KABC::PhoneNumber::Cell; break;
+ case GN_PHONEBOOK_NUMBER_Fax: phonetype = KABC::PhoneNumber::Fax; break;
+ case GN_PHONEBOOK_NUMBER_General:
+ case GN_PHONEBOOK_NUMBER_Work: phonetype = KABC::PhoneNumber::Work; break;
+ default:
+ case GN_PHONEBOOK_NUMBER_Home: phonetype = KABC::PhoneNumber::Home; break;
+ }
+ //if (s == entry.number)
+ // type = (KABC::PhoneNumber::Types) (phonetype | KABC::PhoneNumber::Pref);
+ a->insertPhoneNumber(KABC::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(QString(" 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 KABC::Addressee *addr)
+{
+ gn_phonebook_entry entry;
+ QString s;
+
+ memset(&entry, 0, sizeof(entry));
+ strncpy(entry.name, GN_TO(addr->realName()), sizeof(entry.name)-1);
+ s = addr->phoneNumber(KABC::PhoneNumber::Pref).number();
+ if (s.isEmpty())
+ s = addr->phoneNumber(KABC::PhoneNumber::Work).number();
+ if (s.isEmpty())
+ s = addr->phoneNumber(KABC::PhoneNumber::Home).number();
+ if (s.isEmpty())
+ s = addr->phoneNumber(KABC::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;
+ QString 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
+ QDateTime datetime = addr->revision();
+ QDate date(datetime.date());
+ QTime 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(QString("Write #%1: name=%2, number=%3\n").arg(phone_location)
+ .arg(GN_FROM(entry.name)).arg(GN_FROM(entry.number)));
+
+ const KABC::Address homeAddr = addr->address(KABC::Address::Home);
+ const KABC::Address workAddr = addr->address(KABC::Address::Work);
+
+ entry.subentries_count = 0;
+ gn_phonebook_subentry *subentry = &entry.subentries[0];
+ // add all phone numbers
+ const KABC::PhoneNumber::List phoneList = addr->phoneNumbers();
+ KABC::PhoneNumber::List::ConstIterator it;
+ for ( it = phoneList.begin(); it != phoneList.end(); ++it ) {
+ const KABC::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 & KABC::PhoneNumber::Cell))
+ type = GN_PHONEBOOK_NUMBER_Mobile;
+ else if ((pn_type & KABC::PhoneNumber::Fax))
+ type = GN_PHONEBOOK_NUMBER_Fax;
+ else if ((pn_type & KABC::PhoneNumber::Home))
+ type = GN_PHONEBOOK_NUMBER_Home;
+ else if ((pn_type & KABC::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
+ QStringList 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(QString(" 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 KABC::Address::List addresses = addr->addresses();
+ KABC::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 KABC::Address *Addr = &(*it2);
+ if (Addr->isEmpty()) continue;
+ subentry->entry_type = GN_PHONEBOOK_ENTRY_Postal;
+ QStringList a;
+ QChar sem(';');
+ QString sem_repl(QString::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(QString(" 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(QString("Deleting entry %1\n").arg(phone_location));
+ gn_error error = gn_sm_functions(GN_OP_WritePhonebook, &data, &state);
+ GNOKII_CHECK_ERROR(error);
+ return error;
+}
+
+KABC::AddresseeList GNOKIIXXPort::importContacts( const QString& ) const
+{
+ KABC::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(QSize(450,350));
+ m_progressDlg->show();
+ processEvents();
+
+#if (QT_VERSION >= 0x030300)
+ m_progressDlg->setCursor( Qt::BusyCursor );
+#endif
+ QString 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 KABC::AddresseeList &list, const QString & )
+{
+ 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(QSize(450,350));
+ m_progressDlg->show();
+ processEvents();
+
+ KProgress* progress = (KProgress*)m_progressDlg->progressBar();
+
+ KABC::AddresseeList::ConstIterator it;
+ QStringList failedList;
+
+ gn_error error;
+ bool deleteLabelInitialized = false;
+
+#if (QT_VERSION >= 0x030300)
+ m_progressDlg->setCursor( Qt::BusyCursor );
+#endif
+ QString 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 KABC::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(QString("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(QString("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 */
+
+KABC::AddresseeList GNOKIIXXPort::importContacts( const QString& ) const
+{
+ KABC::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 KABC::AddresseeList &list, const QString & )
+{
+ 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"
+
+/* vim: set sts=4 ts=4 sw=4: */
diff --git a/kaddressbook/xxport/gnokii_xxport.desktop b/kaddressbook/xxport/gnokii_xxport.desktop
new file mode 100644
index 000000000..c937a7d70
--- /dev/null
+++ b/kaddressbook/xxport/gnokii_xxport.desktop
@@ -0,0 +1,103 @@
+[Desktop Entry]
+X-KDE-Library=libkaddrbk_gnokii_xxport
+Name=KAB Mobile Phone XXPort Plugin
+Name[af]=KAB selfoon XXPort inprop module
+Name[bg]=Приставка за XXPort на мобилен телефон на KAB
+Name[bs]=KAB dodatak XXPort u/iz mobilnog telefona
+Name[ca]=Endollable d'importació/exportació de telèfon mòbil per al KAB
+Name[cs]=Exportní modul do mobilního telefonu
+Name[cy]=Ategyn XXPort Ffôn Symudol KAB
+Name[da]=KAB Mobiltelefon XXPort-plugin
+Name[de]=Mobiltelefon-XXPort-Modul für Adressbuch
+Name[el]=Πρόσθετο εισαγωγής/εξαγωγής κινητών τηλεφώνων του KAB
+Name[es]=Plugin de KAB para {im,ex}portar números de móvil
+Name[et]=KAB mobiiltelefoni eksport/importplugin
+Name[eu]=KAB-en mugikorren in/esporatazio plugin-a
+Name[fa]=وصلۀ XXPort تلفن همراه KAB
+Name[fi]=KAB-matkapuhelinliitännäinen
+Name[fr]=Module d'import / export de téléphone portable pour KAB
+Name[fy]=KAB Mobile Tillefoan XXPort-plugin
+Name[gl]=Extensión XXPort de Teléfono Móbil para KAB
+Name[he]=תוסף ייבוא/ייצוא עבור טלפונים ניידים של KAB
+Name[hi]=केएबी मोबाइल फोन XXपोर्ट प्लगइन
+Name[hu]=KAB mobiltelefon XXPort bővítőmodul
+Name[is]=Íforrit fyrir KAB farsíma XXPort
+Name[it]=Plugin KAB telefono cellulare XXPort
+Name[ja]=KAB 携帯電話インポート/エクスポートプラグイン
+Name[ka]=KAB მობილურ ტელეფონთან ექსპორტის მოდული
+Name[kk]=Қалта телефонға экспорт/импорт ету
+Name[km]=កម្មវិធី​ជំនួយ KAB Mobile Phone XXPort
+Name[lt]=KAB mobilaus telefono XXPort priedas
+Name[ms]=Plug masuk KAB Fon Mudah Alih XXPort
+Name[nb]=KAB-programtillegg for mobiltelefon
+Name[nds]=Mobiltelefoon-Im-/Exportmoduul för KAdressbook
+Name[ne]=KAB मोबाइल फोन XXPort प्लगइन
+Name[nl]=KAB Mobiele Telefoon XXPort-plugin
+Name[nn]=KAB Mobiltelefon XXPort programtillegg
+Name[pl]=Wtyczka KAB do importu/eksportu z/do telefonu komórkowego
+Name[pt]='Plugin' XXPort para Telemóveis do KAB
+Name[pt_BR]=Plug-in de Im/Exportação de/para Telefone Móvel do KAB
+Name[ru]=Синхронизация с мобильным телефоном
+Name[sk]=KAB modul pre xxport z mobilu
+Name[sl]=Vstavek KAB Mobile Phone XXPort
+Name[sr]=XXPort прикључак KAB-а за мобилне телефоне
+Name[sr@Latn]=XXPort priključak KAB-a za mobilne telefone
+Name[sv]=Adressbokens överföringsinsticksprogram för mobiltelefon
+Name[ta]=KAB நடமாடும் தொலைபேசி XXபோர்ட் சொருகுப்பொருள்
+Name[tg]=Синхронизатсия бо телефони мобилӣ
+Name[tr]=KAB Cep Telefonu XXPort Eklentisi
+Name[uk]=Втулок KAB для обміну з мобільними телефонами
+Name[zh_CN]=KAB 移动电话 XXPort 插件
+Name[zh_TW]=KAB Mobile Phone XXPort 外掛程式
+Comment=Mobile Phone Plugin to Import and Export Addressbook Entries
+Comment[af]=Inprop module wat kontakte in selfoon formaat invoer en uitvoer
+Comment[bg]=Приставка за експортиране/импортиране на контактите от/към мобилен телефон
+Comment[bs]=Dodatak za uvoz i izvoz stavki adresara iz mobilnog telefona
+Comment[ca]=Endollable de telèfon mòbil per a importar i exportar entrades de la llibreta d'adreces
+Comment[cs]=Modul mobilního telefonu pro import a export záznamů Knihy adres
+Comment[cy]=Ategyn Ffôn Symudol i fewnforio ac allforio cofnodion y Llyfr Cyfeiriadau
+Comment[da]=Mobiltelefon-plugin til at importere og eksportere adressebogsindgange
+Comment[de]=Mobiltelefon-Modul zum Import/Export von Adressbuch-Einträgen
+Comment[el]=Πρόσθετο για εισαγωγή και εξαγωγή επαφών βιβλίου διευθύνσεων από κινητά τηλέφωνα
+Comment[es]=Plugin para importar y exportar números de móviles de las entradas de la libreta de direcciones
+Comment[et]=Mobiiltelefoni plugin aadressiraamatu kirjete importimiseks ja eksportimiseks
+Comment[eu]=Helbide-liburuko sarrerak in/esportatzeko mugikorren plugin-a
+Comment[fa]=وصلۀ تلفن همراه جهت واردات و صادرات مدخلهای کتاب نشانی
+Comment[fi]=Matkapuhelinliitännäinen osoitekirjan kontaktien tuontiin ja vientiin.
+Comment[fr]=Module de téléphone portable pour importer et exporter des entrées du carnet d'adresses
+Comment[fy]=Mobile-tillefoan-plugin faor it importearjen en eksportearjen fan adresboekitems
+Comment[gl]=Extensión de Teléfono Móbil para importar e exportar entradas do caderno de enderezos
+Comment[hi]=पता पुस्तिका प्रविष्टियों को आयात और निर्यात करने का मोबाइल फोन प्लगइन
+Comment[hu]=Mobiltelefonos bővítőmodul címbejegyzések importálásához/exportálásához
+Comment[is]=Íforrit til að færa tengilið milli póstfangaskrár og farsíma
+Comment[it]=Plugin per importare ed esportare voci della rubrica da un telefono cellulare
+Comment[ja]=アドレス帳のエントリをインポート/エクスポートする携帯電話用プラグイン
+Comment[ka]=მობილური ტელეფონის მოდული წიგნაკის ელემენტების იმპორტ/ექსპორტისათვის
+Comment[kk]=Қалта телефонға адр. кітапша жазуын экспорт/импорт ету модулі
+Comment[km]=កម្មវិធី​ជំនួយ​ទូរស័ព្ទ​ចល័ត​ដើម្បី​នាំចូល និង​នាំចេញ​ធាតុ​សៀវភៅ​អាសយដ្ឋាន
+Comment[lt]=Priedas skirtas importuoti ir eksportuoti adresų knygelės įrašus į mobiliuosius telefonus
+Comment[mk]=Приклучок за мобилни телефони за внесување и изнесување контакти од адресарот
+Comment[ms]=Plug masuk Fon Mudah Alih untuk Import dan Eksport Input Buku Alamat
+Comment[nb]=Programtillegg for import/eksport av adressebok fra/til mobiltelefon
+Comment[nds]=Mobiltelefoon-Moduul för't Im- un Exporteren vun KAdressbook-Indrääg
+Comment[ne]=ठेगाना पुस्तिका प्रविष्टि आयात र निर्यात गर्न मोबाइल फोन प्लगइन गर्नुहोस्
+Comment[nl]=Mobiele-telefoon-plugin voor het importeren en exporteren van adresboekitems
+Comment[nn]=Programtillegg for å importera og eksportera adressebokoppføringar i mobiltelefon
+Comment[pl]=Wtyczka do importowania i eksportowania wizytówek z/do telefonu komórkowego
+Comment[pt]=Um 'plugin' para importar e exportar contactos da agenda do telemóvel
+Comment[pt_BR]=Plug-in para Importar e Exportar Entradas do Livro de Endereços de/para Telefone Móvel
+Comment[ru]=Импорт и экспорт контактов мобильного телефона
+Comment[sk]=Modul pre import a export kontaktov z modulu
+Comment[sl]=Vstavek za uvoz in izvoz vnosov v adresarju prenosnih telefonov.
+Comment[sr]=Прикључак за увоз и извоз ставки из адресара у мобилни телефон
+Comment[sr@Latn]=Priključak za uvoz i izvoz stavki iz adresara u mobilni telefon
+Comment[sv]=Insticksprogram för import och export av adressboksposter till mobiltelefon
+Comment[ta]=முகவரி புத்தகத்தின் உள்ளிடுகளை ஏற்றுமதி மற்றும் இறக்குமதி செய்ய செல்பேசி மூலம் சொருகுப்பொருள்
+Comment[tg]=Модул барои воридот ва содироти алоқаи телефони мобилӣ
+Comment[tr]=Adres Defteri Girdilerini Cep Telefonuna Alma ve Gönderme Eklentisi
+Comment[uk]=Втулок для імпорту та експорту записів у адресній книзі мобільних телефонів
+Comment[zh_CN]=导入和导出地址簿项的移动电话插件
+Comment[zh_TW]=匯入與匯出通訊錄的手機外掛程式
+Type=Service
+ServiceTypes=KAddressBook/XXPort
+X-KDE-KAddressBook-XXPortPluginVersion=1
diff --git a/kaddressbook/xxport/gnokii_xxport.h b/kaddressbook/xxport/gnokii_xxport.h
new file mode 100644
index 000000000..64176fcaf
--- /dev/null
+++ b/kaddressbook/xxport/gnokii_xxport.h
@@ -0,0 +1,43 @@
+/*
+ This file is part of KAddressbook.
+ Copyright (c) 2003 - 2003 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 as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ 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 Qt, and distribute the resulting executable,
+ without including the source code for Qt in the source distribution.
+*/
+
+#ifndef GNOKII_XXPORT_H
+#define GNOKII_XXPORT_H
+
+#include <xxport.h>
+
+class GNOKIIXXPort : public KAB::XXPort
+{
+ Q_OBJECT
+
+ public:
+ GNOKIIXXPort( KABC::AddressBook *ab, QWidget *parent, const char *name = 0 );
+
+ QString identifier() const { return "gnokii"; }
+
+ public slots:
+ bool exportContacts( const KABC::AddresseeList &list, const QString &data );
+ KABC::AddresseeList importContacts( const QString &data ) const;
+};
+
+#endif
diff --git a/kaddressbook/xxport/gnokii_xxportui.rc b/kaddressbook/xxport/gnokii_xxportui.rc
new file mode 100644
index 000000000..78e323a45
--- /dev/null
+++ b/kaddressbook/xxport/gnokii_xxportui.rc
@@ -0,0 +1,14 @@
+<?xml version="1.0"?>
+<!DOCTYPE gui>
+<gui name="gnokii_xxport" version="2">
+<MenuBar>
+ <Menu name="file"><text>&amp;File</text>
+ <Menu name="file_import"><text>&amp;Import</text>
+ <Action name="file_import_gnokii"/>
+ </Menu>
+ <Menu name="file_export"><text>&amp;Export</text>
+ <Action name="file_export_gnokii"/>
+ </Menu>
+ </Menu>
+</MenuBar>
+</gui>
diff --git a/kaddressbook/xxport/kde2_xxport.cpp b/kaddressbook/xxport/kde2_xxport.cpp
new file mode 100644
index 000000000..03a524e9f
--- /dev/null
+++ b/kaddressbook/xxport/kde2_xxport.cpp
@@ -0,0 +1,79 @@
+/*
+ This file is part of KAddressbook.
+ Copyright (c) 2003 Tobias Koenig <tokoe@kde.org>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ 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 Qt, and distribute the resulting executable,
+ without including the source code for Qt in the source distribution.
+*/
+
+#include <qfile.h>
+
+#include <kdebug.h>
+#include <kfiledialog.h>
+#include <kio/netaccess.h>
+#include <klocale.h>
+#include <kmessagebox.h>
+#include <kprocess.h>
+#include <kstandarddirs.h>
+#include <ktempfile.h>
+#include <kurl.h>
+
+#include "xxportmanager.h"
+
+#include "kde2_xxport.h"
+
+K_EXPORT_KADDRESSBOOK_XXFILTER( libkaddrbk_kde2_xxport, KDE2XXPort )
+
+KDE2XXPort::KDE2XXPort( KABC::AddressBook *ab, QWidget *parent, const char *name )
+ : KAB::XXPort( ab, parent, name )
+{
+ createImportAction( i18n( "Import KDE 2 Addressbook..." ) );
+}
+
+KABC::AddresseeList KDE2XXPort::importContacts( const QString& ) const
+{
+ QString fileName = locateLocal( "data", "kabc/std.vcf" );
+ if ( !QFile::exists( fileName ) ) {
+ KMessageBox::sorry( parentWidget(), i18n( "<qt>Could not find a KDE 2 address book <b>%1</b>.</qt>" ).arg( fileName ) );
+ return KABC::AddresseeList();
+ }
+
+ int result = KMessageBox::questionYesNoCancel( parentWidget(),
+ i18n( "Override previously imported entries?" ),
+ i18n( "Import KDE 2 Addressbook" ), i18n("Import"), i18n("Do Not Import") );
+
+ if ( !result ) return KABC::AddresseeList();
+
+ KProcess proc;
+
+ if ( result == KMessageBox::Yes ) {
+ proc << "kab2kabc";
+ proc << "--override";
+ } else if ( result == KMessageBox::No )
+ proc << "kab2kabc";
+ else
+ kdDebug(5720) << "KAddressBook::importKDE2(): Unknow return value." << endl;
+
+ proc.start( KProcess::Block );
+
+ addressBook()->load();
+
+ return KABC::AddresseeList();
+}
+
+#include "kde2_xxport.moc"
diff --git a/kaddressbook/xxport/kde2_xxport.desktop b/kaddressbook/xxport/kde2_xxport.desktop
new file mode 100644
index 000000000..f2c20026c
--- /dev/null
+++ b/kaddressbook/xxport/kde2_xxport.desktop
@@ -0,0 +1,106 @@
+[Desktop Entry]
+X-KDE-Library=libkaddrbk_kde2_xxport
+Name=KAB KDE2 XXPort Plugin
+Name[af]=KAB KDE2 XXPort inprop module
+Name[be]=Дапаўненне KAB "Імпарт/Экспарт KDE2"
+Name[bg]=Приставка за KDE2 XXPort на KAB
+Name[br]=Lugent XXPorzh KAB KDE2
+Name[bs]=KAB dodatak za KDE2 XXPort
+Name[ca]=Endollable d'importació/exportació KDE2 per al KAB
+Name[cs]=Exportní modul KDE2
+Name[cy]=Ategyn XXPort KDE2 KAB
+Name[da]=KAB KDE2 XXPort-plugin
+Name[de]=KDE2-XXPort-Modul für Adressbuch
+Name[el]=Πρόσθετο εισαγωγής KDE2 του KAB
+Name[es]=Plugin KAB para {im,ex}portar KDE2
+Name[et]=KAB KDE2 importplugin
+Name[eu]=KAB-en KDE2 in/esportazio plugin-a
+Name[fa]=وصلۀ KAB KDE2 XXPort
+Name[fi]=KAB KDE2 -liitännäinen
+Name[fr]=Module d'import / export de KDE 2 pour KAB
+Name[fy]=KAB KDE2 XXPort-plugin
+Name[gl]=Extensión XXPort de KDE2 para KAB
+Name[he]=תוסף ייבוא/ייצוא עבור KDE2 של KAB
+Name[hi]=केएबी केडीई2 XXपोर्ट प्लगइन
+Name[hu]=KAB KDE2 XXPort bővítőmodul
+Name[is]=Íforrit fyrir KAB KDE2 XXPort
+Name[ja]=KAB KDE2 インポート/プラグイン
+Name[ka]=KAB KDE2-ს ექსპორტის მოდული
+Name[kk]=KDE2 пішімінен импорт ету
+Name[km]=កម្មវិធី​ជំនួយ KAB KDE2 XXPort
+Name[lt]=KAB KDE2 XXPort priedas
+Name[ms]=Plug masuk KAB KDE2 XXPort
+Name[nb]=KAB-programtillegg for KDE2
+Name[nds]=KDE2-Importmoduul för KAdressbook
+Name[ne]=KAB KDE2 XXPort प्लगइन
+Name[nl]=KAB KDE2 XXPort-plugin
+Name[nn]=KAB KDE2 XXPort programtillegg
+Name[pl]=Wtyczka KAB do importu książki adresowej KDE2
+Name[pt]='Plugin' XXPort para KDE2 do KAB
+Name[pt_BR]=Plug-in de Importação de KDE2 do KAB
+Name[ru]=Импорт адресной книги KDE2
+Name[sl]=Vstavek KAB KDE2 XXPort
+Name[sr]=XXPort прикључак KAB-а за KDE2
+Name[sr@Latn]=XXPort priključak KAB-a za KDE2
+Name[sv]=Adressbokens KDE 2-överföringsinsticksprogram
+Name[ta]=KAB KDE2 ஏற்றுமதி சொருகுப்பொருள்
+Name[tg]=Воридоти китоби адресии KDE2
+Name[tr]=KAB KDE2 XXPort Eklentisi
+Name[uk]=Втулок KAB для обміну з KDE2
+Name[zh_CN]=KAB KDE2 XXPort 插件
+Name[zh_TW]=KAB KDE2 XXPort 外掛程式
+Comment=Plugin to import the old KDE 2 address book
+Comment[af]=Inprop module om 'n ou KDE 2 adres boek in te voer
+Comment[be]=Дапаўненне для імпарту старой адраснай кнігі KDE 2
+Comment[bg]=Приставка за импортиране на контактите от адресника в KDE 2
+Comment[bs]=Dodatak za uvoz iz starog KDE 2 adresara
+Comment[ca]=Endollable per a importar l'antiga llibreta d'adreces del KDE 2
+Comment[cs]=Modul pro import staré KDE 2 knihy adres
+Comment[cy]=Ategyn i fewnforio'r hen lyfr cyfeiriadau KDE2
+Comment[da]=Plugin til at importere den gamle KDE 2 adressebog
+Comment[de]=Modul zum Import von Adressbüchern aus KDE 2
+Comment[el]=Πρόσθετο για εισαγωγή του παλιού βιβλίου διευθύνσεων του KDE 2
+Comment[es]=Plugin para importar de la libreta de direcciones de KDE 2
+Comment[et]=Plugin vana KDE2 aadressiraamatu importimiseks
+Comment[eu]=KDE2-ko helbide-liburu zaharrak inporatzeko plugin-a
+Comment[fa]=وصله برای واردات کتاب نشانی قدیمی KDE ۲
+Comment[fi]=Liitännäinen vanhan KDE2-osoitekirjan tuontiin
+Comment[fr]=Module d'import du vieux carnet d'adresses de KDE 2
+Comment[fy]=Plugin foar it importearjen fan it âlde KDE 2-adresboek
+Comment[gl]=Extensión para importar o vello caderno de enderezos de KDE 2
+Comment[hi]=पुराना केडीई 2 पता पुस्तिका को आयात के लिए प्लगइन
+Comment[hu]=Bővítőmodul KDE2-es címjegyzék importálásához
+Comment[is]=Íforrit til að færa inn gömlu KDE2 vistfangaskrána
+Comment[it]=Plugin per importare le vecchie voci della rubrica di KDE2
+Comment[ja]=古い KDE 2 アドレス帳をインポートするプラグイン
+Comment[ka]=ძველი KDE2-ს წიგნაკის იმპორტის მოდული
+Comment[kk]=Ескі KDE2 адр.кітапшасынан импорт ету модулі
+Comment[km]=កម្មវិធី​ជំនួយ​ដើម្បី​នាំចូល​សៀវភៅ​អាសយដ្ឋាន KDE 2 ចាស់ៗ
+Comment[lt]=Priedas senosios KDE 2 adresų knygelės importui
+Comment[mk]=Приклучок за внесување на старите адресари од KDE 2
+Comment[ms]=Plug masuk untuk import buku alamat lama KDE 2
+Comment[nb]=Programtillegg for å importere adressebok fra KDE2
+Comment[nds]=Moduul för't Importeren vun KDE2-Adressböker
+Comment[ne]=पूरानो केडीई २ ठेगाना पुस्तिका आयात गर्न प्लगइन गर्नुहोस्
+Comment[nl]=Plugin voor het importeren van het oude KDE 2-adresboek
+Comment[nn]=Programtillegg for å importera den gamle KDE 2 adresseboka
+Comment[pl]=Wtyczka do importu starej książki adresowej z KDE 2
+Comment[pt]=Um 'plugin' para importar o livro de endereços antigo do KDE 2
+Comment[pt_BR]=Plug-in para importar o antigo livro de endereços do KDE2
+Comment[ru]=Импорт файлов адресной книги KDE2
+Comment[sk]=Plugin pre import starej knihy adries z KDE 2
+Comment[sl]=Vstavek za uvoz starih adresarjev iz KDE 2
+Comment[sr]=Прикључак за увоз старог KDE 2 адресара
+Comment[sr@Latn]=Priključak za uvoz starog KDE 2 adresara
+Comment[sv]=Insticksprogram för import av den gamla KDE 2 adressboken
+Comment[ta]=பழைய KDE 2 கேமுகவரிபுத்தகத்தை ஏற்றுமதி செய்ய சொருகுப்பொருள்
+Comment[tg]=Модул барои воридоти файлҳои китобиадресии KDE2
+Comment[tr]=KDE 2 adres defteri bilgilerini alma eklentisi
+Comment[uk]=Втулок для імпорту адресної книги старого формату часів KDE 2
+Comment[uz]=Eski KDE 2 manzillar daftarini import qilish uchun plagin
+Comment[uz@cyrillic]=Эски KDE 2 манзиллар дафтарини импорт қилиш учун плагин
+Comment[zh_CN]=导入旧的 KDE 2 地址簿的插件
+Comment[zh_TW]=匯入舊的 KDE2 通訊錄的外掛程式
+Type=Service
+ServiceTypes=KAddressBook/XXPort
+X-KDE-KAddressBook-XXPortPluginVersion=1
diff --git a/kaddressbook/xxport/kde2_xxport.h b/kaddressbook/xxport/kde2_xxport.h
new file mode 100644
index 000000000..4f5f2edb0
--- /dev/null
+++ b/kaddressbook/xxport/kde2_xxport.h
@@ -0,0 +1,42 @@
+/*
+ This file is part of KAddressbook.
+ Copyright (c) 2003 Tobias Koenig <tokoe@kde.org>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ 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 Qt, and distribute the resulting executable,
+ without including the source code for Qt in the source distribution.
+*/
+
+#ifndef KDE2_XXPORT_H
+#define KDE2_XXPORT_H
+
+#include <xxport.h>
+
+class KDE2XXPort : public KAB::XXPort
+{
+ Q_OBJECT
+
+ public:
+ KDE2XXPort( KABC::AddressBook *ab, QWidget *parent, const char *name = 0 );
+
+ QString identifier() const { return "kde2"; }
+
+ public slots:
+ KABC::AddresseeList importContacts( const QString &data ) const;
+};
+
+#endif
diff --git a/kaddressbook/xxport/kde2_xxportui.rc b/kaddressbook/xxport/kde2_xxportui.rc
new file mode 100644
index 000000000..990b3e7b3
--- /dev/null
+++ b/kaddressbook/xxport/kde2_xxportui.rc
@@ -0,0 +1,11 @@
+<?xml version="1.0"?>
+<!DOCTYPE gui>
+<gui name="kde2_xxport" version="1">
+<MenuBar>
+ <Menu name="file"><text>&amp;File</text>
+ <Menu name="file_import"><text>&amp;Import</text>
+ <Action name="file_import_kde2"/>
+ </Menu>
+ </Menu>
+</MenuBar>
+</gui>
diff --git a/kaddressbook/xxport/ldif_xxport.cpp b/kaddressbook/xxport/ldif_xxport.cpp
new file mode 100644
index 000000000..342ff9d81
--- /dev/null
+++ b/kaddressbook/xxport/ldif_xxport.cpp
@@ -0,0 +1,140 @@
+/*
+ This file is part of KAddressbook.
+ Copyright (c) 2000 - 2002 Oliver Strutynski <olistrut@gmx.de>
+ Copyright (c) 2002 - 2003 Helge Deller <deller@kde.org>
+ Tobias Koenig <tokoe@kde.org>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ 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 Qt, and distribute the resulting executable,
+ without including the source code for Qt in the source distribution.
+*/
+
+/*
+ Description:
+ The LDAP Data Interchange Format (LDIF) is a common ASCII-text based
+ Internet interchange format. Most programs allow you to export data in
+ LDIF format and e.g. Netscape and Mozilla store by default their
+ Personal Address Book files in this format.
+ This import and export filter reads and writes any LDIF version 1 files
+ into your KDE Addressbook.
+*/
+
+#include <qfile.h>
+
+#include <kfiledialog.h>
+#include <kio/netaccess.h>
+#include <klocale.h>
+#include <kmdcodec.h>
+#include <kmessagebox.h>
+#include <ktempfile.h>
+#include <kurl.h>
+#include <kabc/ldifconverter.h>
+
+#include <kdebug.h>
+
+#include "ldif_xxport.h"
+
+K_EXPORT_KADDRESSBOOK_XXFILTER( libkaddrbk_ldif_xxport, LDIFXXPort )
+
+LDIFXXPort::LDIFXXPort( KABC::AddressBook *ab, QWidget *parent, const char *name )
+ : KAB::XXPort( ab, parent, name )
+{
+ createImportAction( i18n( "Import LDIF Addressbook..." ) );
+ createExportAction( i18n( "Export LDIF Addressbook..." ) );
+}
+
+/* import */
+
+KABC::AddresseeList LDIFXXPort::importContacts( const QString& ) const
+{
+ KABC::AddresseeList addrList;
+
+ QString fileName = KFileDialog::getOpenFileName( QDir::homeDirPath(),
+ "text/x-ldif", 0 );
+ if ( fileName.isEmpty() )
+ return addrList;
+
+ QFile file( fileName );
+ if ( !file.open( IO_ReadOnly ) ) {
+ QString msg = i18n( "<qt>Unable to open <b>%1</b> for reading.</qt>" );
+ KMessageBox::error( parentWidget(), msg.arg( fileName ) );
+ return addrList;
+ }
+
+ QTextStream t( &file );
+ t.setEncoding( QTextStream::Latin1 );
+ QString wholeFile = t.read();
+ QDateTime dtDefault = QFileInfo(file).lastModified();
+ file.close();
+
+ KABC::LDIFConverter::LDIFToAddressee( wholeFile, addrList, dtDefault );
+
+ return addrList;
+}
+
+
+/* export */
+
+bool LDIFXXPort::exportContacts( const KABC::AddresseeList &list, const QString& )
+{
+ KURL url = KFileDialog::getSaveURL( QDir::homeDirPath() + "/addressbook.ldif",
+ "text/x-ldif" );
+ if ( url.isEmpty() )
+ return true;
+
+ if ( !url.isLocalFile() ) {
+ KTempFile tmpFile;
+ if ( tmpFile.status() != 0 ) {
+ QString txt = i18n( "<qt>Unable to open file <b>%1</b>.%2.</qt>" );
+ KMessageBox::error( parentWidget(), txt.arg( url.url() )
+ .arg( strerror( tmpFile.status() ) ) );
+ return false;
+ }
+
+ doExport( tmpFile.file(), list );
+ tmpFile.close();
+
+ return KIO::NetAccess::upload( tmpFile.name(), url, parentWidget() );
+ } else {
+ QString filename = url.path();
+ QFile file( filename );
+
+ if ( !file.open( IO_WriteOnly ) ) {
+ QString txt = i18n( "<qt>Unable to open file <b>%1</b>.</qt>" );
+ KMessageBox::error( parentWidget(), txt.arg( filename ) );
+ return false;
+ }
+
+ doExport( &file, list );
+ file.close();
+
+ return true;
+ }
+}
+
+void LDIFXXPort::doExport( QFile *fp, const KABC::AddresseeList &list )
+{
+ QString str;
+ KABC::LDIFConverter::addresseeToLDIF( list, str );
+
+ QTextStream t( fp );
+ t.setEncoding( QTextStream::UnicodeUTF8 );
+ t << str;
+}
+
+#include "ldif_xxport.moc"
+
diff --git a/kaddressbook/xxport/ldif_xxport.desktop b/kaddressbook/xxport/ldif_xxport.desktop
new file mode 100644
index 000000000..abdc10958
--- /dev/null
+++ b/kaddressbook/xxport/ldif_xxport.desktop
@@ -0,0 +1,105 @@
+[Desktop Entry]
+X-KDE-Library=libkaddrbk_ldif_xxport
+Name=KAB LDIF XXPort Plugin
+Name[af]=KAB LDIF XXPort inprop module
+Name[be]=Дапаўненне KAB "Імпарт LDIF"
+Name[bg]=Приставка за LDIF XXPort на KAB
+Name[br]=Lugent XXPorzh KAB LDIF
+Name[bs]=KAB dodatak za LDIF XXPort
+Name[ca]=Endollable per importació/exportació de LDIF per al KAB
+Name[cs]=Exportní modul LDIF
+Name[cy]=Ategyn XXPort LDIF KAB
+Name[da]=KAB LDIF XXPort-plugin
+Name[de]=LDIF-XXPort-Modul für Adressbuch
+Name[el]=Πρόσθετο εισαγωγής/εξαγωγής LDIF του KAB
+Name[es]=Plugin para {im,ex}portar LDIF
+Name[et]=KAB LDIF eksport/importplugin
+Name[eu]=KAB-en LDIF in/esportazio plugin-a
+Name[fa]=وصلۀ KAB LDIF XXPort
+Name[fi]=KAB LDIF -liitännäinen
+Name[fr]=Module d'import / export LDIF pour KAB
+Name[fy]=KAB LDIF XXPort-plugin
+Name[gl]=Extensión XXPort de LDIF para KAB
+Name[he]=תוסף ייבוא/ייצוא עבור LDIF של KAB
+Name[hi]=केएबी एलडीआईएफ XXपोर्ट प्लगइन
+Name[hu]=KAB LDIF XXPort bővítőmodul
+Name[is]=Íforrit fyrir KAB LDIF XXPort
+Name[ja]=KAB LDIF インポート/エクスポートプラグイン
+Name[ka]=KAB LDIF-ის ექსპორტის მოდული
+Name[kk]=LDIF пішіміне экспорт/импорт ету
+Name[km]=កម្មវិធី​ជំនួយ KAB LDIF XXPort
+Name[lt]=KAB LDIF XXPort priedas
+Name[ms]=Plug masuk KAB LDIF XXPort
+Name[nb]=KAB-programtillegg for LDIF-format
+Name[nds]=LDIF-Im-/Exportmoduul för KAdressbook
+Name[ne]=KAB LDIF XXPort प्लगइन
+Name[nl]=KAB LDIF XXPort-plugin
+Name[nn]=KAB LDIF XXPort programtillegg
+Name[pl]=Wtyczka KAB do importu/eksportu z/do formatu LDIF
+Name[pt]='Plugin' XXPort para LDIF do KAB
+Name[pt_BR]=Plug-in de Im/Exportação de LDIF do KAB
+Name[ru]=Обмен информацией через LDIF
+Name[sk]=KAB modul pre xxport LDIF
+Name[sl]=Vstavek KAB LDIF XXPort
+Name[sr]=XXPort прикључак KAB-а за LDIF
+Name[sr@Latn]=XXPort priključak KAB-a za LDIF
+Name[sv]=Adressbokens LDIF-överföringsinsticksprogram
+Name[ta]=KAB LDIF சோதனை சொருகுப்பொருள்
+Name[tg]=Мубодилаи иттилоот аз KDE2
+Name[tr]=KAB LDIF XXPort Eklentisi
+Name[uk]=Втулок KAB для обміну через LDIF
+Name[zh_CN]=KAB LDIF XXPort 插件
+Name[zh_TW]=KAB LDIF XXPort 外掛程式
+Comment=Plugin to import and export contacts in Netscape and Mozilla LDIF format
+Comment[af]=Inprop module wat kontakte in Netscape/Mozilla LDIF formaat invoer en uitvoer
+Comment[be]=Дапаўненне для імпарту кантактаў у фармаце Netscape/Mozilla LDIF
+Comment[bg]=Приставка за импортиране/експортиране на контактите във формат на Netscape и Mozilla (LDIF)
+Comment[bs]=Dodatak za uvoz i izvoz kontakata iz LDIF formata koji koriste Netscape i Mozilla
+Comment[ca]=Endollable per a importar i exportar contactes en el format LDIF de Mozilla i Netscape
+Comment[cs]=Modul pro import a export kontaktů ve formátu Netscape a Mozilla LDIF
+Comment[cy]=Ategyn i fewnforio ac allforio cysylltau yn fformat LDIF Netscape a Mozilla
+Comment[da]=Plugin til at importere og eksportere kontakter i Netscape og Mozilla LDIF-format
+Comment[de]=Modul zum Import/Export von Kontakten im LDIF-Format aus Netscape und Mozilla
+Comment[el]=Πρόσθετο για εισαγωγή και εξαγωγή επαφών μορφής LDIF του Netscape και Mozilla
+Comment[es]=Plugin para importar y exportar contactos en el formato de intercambio LDIF de Netscape y Mozilla
+Comment[et]=Plugin kontaktide importimiseks ja ekportimiseks Netscape ja Mozilla LDIF vormingus
+Comment[eu]=Netscape eta Mozilla-ren LDIF formatuan kontaktuak in/esportatzeko plugin-a
+Comment[fa]=وصله برای واردات و صادرات تماسها در قالب LDIF موزیلا و نت‌اسکیپ
+Comment[fi]=Liitännäinen Netscapen ja Mozillan LDIF-muodon kontaktien tuontiin ja vientiin
+Comment[fr]=Module d'import / export des contacts au format LDIF Mozilla et Netscape
+Comment[fy]=Plugin foar it ymportearjen en eksportearjen fan kontaktpersoanen yn Netscape's en Mozilla's LDIF-formaat
+Comment[gl]=Extensión para importar e exportar contactos en formato LDIF de Netscape e Mozilla
+Comment[hi]=नेटस्केप तथा मोजिला एलडीआईएफ फार्मेट में सम्पर्कों को आयात और निर्यात करने का प्लगइन
+Comment[hu]=Bővítőmodul Netscape és Mozilla LDIF formátumú névjegyek importálásához/exportálásához
+Comment[is]=Íforrit sem flytur flytja inn eða út tengiliði í Netscape og Mozilla LDIF sniði
+Comment[it]=Plugin per importare ed esportare contatti in formato Netscape e Mozilla LDIF
+Comment[ja]=Netscape と Mozilla の LDIF フォーマットで連絡先をインポート/エクスポートするプラグイン
+Comment[ka]= Netscape-სა და Mozilla-ს კონტაქტების იმპორტ/ექსპორტის მოდული LDIF ფორმატით
+Comment[kk]=Netscape пен Mozilla LDIF пішіміне экспорт/импорт ету модулі
+Comment[km]=កម្មវិធី​ជំនួយ​ដើម្បី​នាំចូល និង​នាំចេញ​ទំនាក់ទំនង​ក្នុង​ទ្រង់ទ្រាយ​ជា Netscape និង Mozilla LDIF
+Comment[lt]=Priedas, skirtas kontaktų importavimui ir eksportavimui Netscape ir Mozilla LDIFF formatu
+Comment[mk]=Приклучок за внесување и изнесување контакти во форматите на Netscape и Mozilla LDIF
+Comment[ms]=Plug masuk untuk import dan eksport alamat perhubungan di dalam format LDIF Netscape dan Mozilla
+Comment[nb]=Programtillegg for import/eksport av kontakter i Netscape og Mozillas LDIF-format
+Comment[nds]=Moduul för't Im- un Exporteren vun Kontakten in't LDIF-Formaat vun Netscape und Mozilla
+Comment[ne]=नेटस्क्येप र मोजिला LDIF ढाँचामा आयात निर्यात गर्न प्लगइन गर्नुहोस्
+Comment[nl]=Plugin voor het importeren en exporteren van contactpersonen in Netscape's en Mozilla's LDIF-formaat
+Comment[nn]=Programtillegg for å importera og eksportera kontaktar i Netscape og Mozilla LDIF-format
+Comment[pl]=Wtyczka do importowania i eksportowania wizytówek z/do formatu LDIF używanego przez Mozillę i Netscape'a
+Comment[pt]=Um 'plugin' para importar e exportar os contactos no formato LDIF do Netscape e do Mozilla
+Comment[pt_BR]=Plug-in para importar e exportar contatos no formato LDIF do Netscape e Mozilla
+Comment[ru]=Импорт и экспорт контактов через формат LDIF Netscape и Mozilla
+Comment[sk]=Modul pre import a export kontaktov z Netscape a Mozilla formátu LDIF
+Comment[sl]=Vstavek za uvoz in izvoz stikov v obliki LDIF (Netscape in Mozilla)
+Comment[sr]=Прикључак за увоз и извоз контаката у Netscape и Mozilla LDIF формат
+Comment[sr@Latn]=Priključak za uvoz i izvoz kontakata u Netscape i Mozilla LDIF format
+Comment[sv]=Insticksprogram för import och export av kontakter med Netscapes och Mozillas LDIF-format
+Comment[ta]=நெட்ஸ்கேப் மற்றும் மொசில்லா LDIF வடிவமைப்பை ஏற்றுமதி/இறக்குமதியில் தொடர்புக்கொள்ள சொருகுப்பொருள்
+Comment[tg]=Модул барои воридот ва содироти алоқа аз формати LDIF Netscape ва Mozilla
+Comment[tr]=Netscape ve Mozilla'nın LDIF biçimindeki bağlantılarını alma ve gönderme eklentisi
+Comment[uk]=Втулок для імпорту та експорту контактів у LDIF сумісний з Netscape та Mozilla
+Comment[zh_CN]=导入和导出 Netscape 和 Mozilla LDIF 格式联系人的插件
+Comment[zh_TW]=匯入與匯出 Netscape 與 Mozilla LDIF 格式聯絡人的外掛程式
+Type=Service
+ServiceTypes=KAddressBook/XXPort
+X-KDE-KAddressBook-XXPortPluginVersion=1
diff --git a/kaddressbook/xxport/ldif_xxport.h b/kaddressbook/xxport/ldif_xxport.h
new file mode 100644
index 000000000..d5ae2cdd3
--- /dev/null
+++ b/kaddressbook/xxport/ldif_xxport.h
@@ -0,0 +1,47 @@
+/*
+ This file is part of KAddressbook.
+ Copyright (c) 2000 - 2003 Oliver Strutynski <olistrut@gmx.de>
+ Tobias Koenig <tokoe@kde.org>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ 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 Qt, and distribute the resulting executable,
+ without including the source code for Qt in the source distribution.
+*/
+
+#ifndef LDIF_XXPORT_H
+#define LDIF_XXPORT_H
+
+#include <xxport.h>
+
+class LDIFXXPort : public KAB::XXPort
+{
+ Q_OBJECT
+
+ public:
+ LDIFXXPort( KABC::AddressBook *ab, QWidget *parent, const char *name = 0 );
+
+ QString identifier() const { return "ldif"; }
+
+ public slots:
+ bool exportContacts( const KABC::AddresseeList &list, const QString &data );
+ KABC::AddresseeList importContacts( const QString &data ) const;
+
+ private:
+ void doExport( QFile *fp, const KABC::AddresseeList &list );
+};
+
+#endif
diff --git a/kaddressbook/xxport/ldif_xxportui.rc b/kaddressbook/xxport/ldif_xxportui.rc
new file mode 100644
index 000000000..53e80523e
--- /dev/null
+++ b/kaddressbook/xxport/ldif_xxportui.rc
@@ -0,0 +1,14 @@
+<?xml version="1.0"?>
+<!DOCTYPE gui>
+<gui name="ldif_xxport" version="3">
+<MenuBar>
+ <Menu name="file"><text>&amp;File</text>
+ <Menu name="file_import"><text>&amp;Import</text>
+ <Action name="file_import_ldif"/>
+ </Menu>
+ <Menu name="file_export"><text>&amp;Export</text>
+ <Action name="file_export_ldif"/>
+ </Menu>
+ </Menu>
+</MenuBar>
+</gui>
diff --git a/kaddressbook/xxport/opera_xxport.cpp b/kaddressbook/xxport/opera_xxport.cpp
new file mode 100644
index 000000000..c3d707b88
--- /dev/null
+++ b/kaddressbook/xxport/opera_xxport.cpp
@@ -0,0 +1,126 @@
+/*
+ This file is part of KAddressbook.
+ Copyright (c) 2003 - 2003 Daniel Molkentin <molkentin@kde.org>
+ Tobias Koenig <tokoe@kde.org>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ 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 Qt, and distribute the resulting executable,
+ without including the source code for Qt in the source distribution.
+*/
+
+#include <qfile.h>
+#include <qregexp.h>
+
+#include <kfiledialog.h>
+#include <kio/netaccess.h>
+#include <klocale.h>
+#include <kmessagebox.h>
+#include <ktempfile.h>
+#include <kurl.h>
+
+#include <kdebug.h>
+
+#include "opera_xxport.h"
+
+K_EXPORT_KADDRESSBOOK_XXFILTER( libkaddrbk_opera_xxport, OperaXXPort )
+
+OperaXXPort::OperaXXPort( KABC::AddressBook *ab, QWidget *parent, const char *name )
+ : KAB::XXPort( ab, parent, name )
+{
+ createImportAction( i18n( "Import Opera Addressbook..." ) );
+}
+
+KABC::AddresseeList OperaXXPort::importContacts( const QString& ) const
+{
+ KABC::AddresseeList addrList;
+
+ QString fileName = KFileDialog::getOpenFileName( QDir::homeDirPath() + QString::fromLatin1( "/.opera/contacts.adr" ) );
+ if ( fileName.isEmpty() )
+ return addrList;
+
+ QFile file( fileName );
+ if ( !file.open( IO_ReadOnly ) ) {
+ QString msg = i18n( "<qt>Unable to open <b>%1</b> for reading.</qt>" );
+ KMessageBox::error( parentWidget(), msg.arg( fileName ) );
+ return addrList;
+ }
+
+ QTextStream stream( &file );
+ stream.setEncoding( QTextStream::UnicodeUTF8 );
+ QString line, key, value;
+ bool parseContact = false;
+ KABC::Addressee addr;
+
+ QRegExp separator( "\x02\x02" );
+
+ while ( !stream.atEnd() ) {
+ line = stream.readLine();
+ line = line.stripWhiteSpace();
+ if ( line == QString::fromLatin1( "#CONTACT" ) ) {
+ parseContact = true;
+ addr = KABC::Addressee();
+ continue;
+ } else if ( line.isEmpty() ) {
+ parseContact = false;
+ if ( !addr.isEmpty() ) {
+ addrList.append( addr );
+ addr = KABC::Addressee();
+ }
+ continue;
+ }
+
+ if ( parseContact == true ) {
+ int sep = line.find( '=' );
+ key = line.left( sep ).lower();
+ value = line.mid( sep + 1 );
+ if ( key == QString::fromLatin1( "name" ) )
+ addr.setNameFromString( value );
+ else if ( key == QString::fromLatin1( "mail" ) ) {
+ QStringList emails = QStringList::split( separator, value );
+
+ QStringList::Iterator it = emails.begin();
+ bool preferred = true;
+ for ( ; it != emails.end(); ++it ) {
+ addr.insertEmail( *it, preferred );
+ preferred = false;
+ }
+ } else if ( key == QString::fromLatin1( "phone" ) )
+ addr.insertPhoneNumber( KABC::PhoneNumber( value ) );
+ else if ( key == QString::fromLatin1( "fax" ) )
+ addr.insertPhoneNumber( KABC::PhoneNumber( value,
+ KABC::PhoneNumber::Fax | KABC::PhoneNumber::Home ) );
+ else if ( key == QString::fromLatin1( "postaladdress" ) ) {
+ KABC::Address address( KABC::Address::Home );
+ address.setLabel( value.replace( separator, "\n" ) );
+ addr.insertAddress( address );
+ } else if ( key == QString::fromLatin1( "description" ) )
+ addr.setNote( value.replace( separator, "\n" ) );
+ else if ( key == QString::fromLatin1( "url" ) )
+ addr.setUrl( KURL( value ) );
+ else if ( key == QString::fromLatin1( "pictureurl" ) ) {
+ KABC::Picture pic( value );
+ addr.setPhoto( pic );
+ }
+ }
+ }
+
+ file.close();
+
+ return addrList;
+}
+
+#include "opera_xxport.moc"
diff --git a/kaddressbook/xxport/opera_xxport.desktop b/kaddressbook/xxport/opera_xxport.desktop
new file mode 100644
index 000000000..ddbcff7bf
--- /dev/null
+++ b/kaddressbook/xxport/opera_xxport.desktop
@@ -0,0 +1,103 @@
+[Desktop Entry]
+X-KDE-Library=libkaddrbk_opera_xxport
+Name=KAB Opera XXPort Plugin
+Name[af]=KAB Opera XXPort inprop module
+Name[be]=Дапаўненне KAB "Імпарт Opera"
+Name[bg]=Приставка за Opera XXPort на KAB
+Name[br]=Lugent KAB Opera XXPort
+Name[bs]=KAB dodatak za Opera XXPort
+Name[ca]=Endollable d'importació/exportació d'Opera per al KAB
+Name[cs]=Exportní modul do Opery
+Name[cy]=Ategyn XXPort Opera KAB
+Name[da]=KAB Opera XXPort-plugin
+Name[de]=Opera-XXPort-Modul für Adressbuch
+Name[el]=Πρόσθετο εισαγωγής Opera του KAB
+Name[es]=Plugin KAB para {im,ex}portar Opera
+Name[et]=KAB Opera importplugin
+Name[eu]=KAB-en Opera in/esportazio plugin-a
+Name[fa]=وصلۀ KAB Opera XXPort
+Name[fi]=KAB Opera -liitännäinen
+Name[fr]=Module d'import / export Opera pour KAB
+Name[gl]=Extensión XXPort para de Opera KAB
+Name[he]=תוסף ייבוא/ייצוא עבור Opera של KAB
+Name[hi]=केएबी ऑपेरा XXपोर्ट प्लगइन
+Name[hu]=KAB Opera XXPort bővítőmodul
+Name[is]=Íforrit fyrir KAP Opera XXPort
+Name[ja]=KAB Opera インポート/エクスポートプラグイン
+Name[ka]=KAB Opera-ს ექსპორტის მოდული
+Name[kk]=Opera пішіміне экспорт/импорт ету
+Name[km]=កម្មវិធី​ជំនួយ KAB Opera XXPort
+Name[lt]=KAB Opera XXPort priedas
+Name[ms]=Plugin KAB Opera XXPort
+Name[nb]=KAB-programtillegg for Opera
+Name[nds]=Opera-Importmoduul för KAdressbook
+Name[ne]=KAB ओपेरा XXPort प्लगइन
+Name[nn]=KAB Opera XXPort programtillegg
+Name[pl]=Wtyczka KAB do importu z Opery
+Name[pt]='Plugin' XXPort para Opera do KAB
+Name[pt_BR]=Plug-in de Importação de Opera do KAB
+Name[ru]=Обмен информацией с Opera
+Name[sk]=KAB modul pre xxport z Opera
+Name[sl]=Vstavek KAB Opera XXPort
+Name[sr]=XXPort прикључак KAB-а за Opera-у
+Name[sr@Latn]=XXPort priključak KAB-a za Opera-u
+Name[sv]=AdressbokensOpera-överföringsinsticksprogram
+Name[ta]=KAB ஓப்பெரா ஏற்றுமதி சொருகுப்பொருள்
+Name[tg]=Мубодилаи иттилоот бо Opera
+Name[tr]=KAB Opera XXPort Eklentisi
+Name[uk]=Name=Втулок KAB для обміну з Opera
+Name[zh_CN]=KAB Opera XXPort 插件
+Name[zh_TW]=KAB Opera XXPort 外掛程式
+Comment=Plugin to import Opera contacts
+Comment[af]=Inprop module wat kontakte in Opera formaat invoer
+Comment[be]=Дапаўненне для імпарту кантактаў Opera
+Comment[bg]=Приставка за импортиране на контактите от Опера
+Comment[bs]=Dodatak za uvoz kontakata iz Opere
+Comment[ca]=Endollable per a importar contactes des d'Opera
+Comment[cs]=Modul pro import a export kontaktů programu Opera
+Comment[cy]=Ategyn i fewnforio cysylltau Opera
+Comment[da]=Plugin til at importere Opera-kontakter
+Comment[de]=Modul zum Import von Opera-Kontakten
+Comment[el]=Πρόσθετο για εισαγωγή επαφών του Opera
+Comment[es]=Plugin para importar contactos de Opera
+Comment[et]=Plugin Opera kontaktide importimiseks
+Comment[eu]=Operaren kontaktuak inportatzeko plugin-a
+Comment[fa]=وصله برای واردات تماسهای Opera
+Comment[fi]=Liitännäinen Operan kontaktien tuomiseen
+Comment[fr]=Module d'import de contacts Opera
+Comment[fy]=Plugin foar ymportearjen fan Opera's kontaktpersoanen
+Comment[gl]=Extensión para importar contactos de Opera
+Comment[hi]=ऑपेरा सम्पर्कों को आयात करने का प्लगइन
+Comment[hu]=Bővítőmodul Opera névjegyek importálásához
+Comment[is]=Íforrit til flytja inn eða út Opera tengiliði
+Comment[it]=Plugin per importare contatti da Opera
+Comment[ja]=Opera の連絡先をインポートするプラグイン
+Comment[ka]=Opera-ს კონტაქტების იმპორტის მოდული
+Comment[kk]=Opera контактарын экспорт/импорт ету модулі
+Comment[km]=កម្មវិធី​ជំនួយ​ដើម្បី​នាំចូល​ទំនាក់ទំនង​របស់ Opera
+Comment[lt]=Priedas Opera kontaktų importui
+Comment[mk]=Приклучок за внесување контакти од Opera
+Comment[ms]=Plug masuk untuk import alamat perhubungan Opera
+Comment[nb]=Programtillegg for å importere Opera-kontakter
+Comment[nds]=Modul för't Importeren vun Opera-Kontakten
+Comment[ne]=ओपेरा सम्पर्क आयात गर्न प्लगइन गर्नुहोस्
+Comment[nl]=Plugin voor het importeren an Opera's contactpersonen
+Comment[nn]=Programtillegg for å imortera Opera-kontaktar
+Comment[pl]=Wtyczka do importu wizytówek z Opery
+Comment[pt]=Um 'plugin' para importar os contactos do Opera
+Comment[pt_BR]=Plug-in para importar contatos do Opera
+Comment[ru]=Импорт контактов Opera
+Comment[sk]=Plugin pre import kontaktov z Opera
+Comment[sl]=Vstavek za uvoz stikov iz Opere
+Comment[sr]=Прикључак за увоз Opera контаката
+Comment[sr@Latn]=Priključak za uvoz Opera kontakata
+Comment[sv]=Insticksprogram för import av Opera-kontakter
+Comment[ta]=ஓப்பெரா தொடர்புகளை இறக்குமதி செய்ய சொருகுப்பொருள்
+Comment[tg]=Модул барои воридоти алоқаи Opera
+Comment[tr]=Opera bağlantılarını alma eklentisi
+Comment[uk]=Втулок для імпорту контактів Opera
+Comment[zh_CN]=导入 Opera 联系人的插件
+Comment[zh_TW]=匯入 Opera 聯絡人的外掛程式
+Type=Service
+ServiceTypes=KAddressBook/XXPort
+X-KDE-KAddressBook-XXPortPluginVersion=1
diff --git a/kaddressbook/xxport/opera_xxport.h b/kaddressbook/xxport/opera_xxport.h
new file mode 100644
index 000000000..ec4838be1
--- /dev/null
+++ b/kaddressbook/xxport/opera_xxport.h
@@ -0,0 +1,43 @@
+/*
+ This file is part of KAddressbook.
+ Copyright (c) 2003 - 2003 Daniel Molkentin <molkentin@kde.org>
+ Tobias Koenig <tokoe@kde.org>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ 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 Qt, and distribute the resulting executable,
+ without including the source code for Qt in the source distribution.
+*/
+
+#ifndef OPERA_XXPORT_H
+#define OPERA_XXPORT_H
+
+#include <xxport.h>
+
+class OperaXXPort : public KAB::XXPort
+{
+ Q_OBJECT
+
+ public:
+ OperaXXPort( KABC::AddressBook *ab, QWidget *parent, const char *name = 0 );
+
+ QString identifier() const { return "opera"; }
+
+ public slots:
+ KABC::AddresseeList importContacts( const QString &data ) const;
+};
+
+#endif
diff --git a/kaddressbook/xxport/opera_xxportui.rc b/kaddressbook/xxport/opera_xxportui.rc
new file mode 100644
index 000000000..84e4e1eb3
--- /dev/null
+++ b/kaddressbook/xxport/opera_xxportui.rc
@@ -0,0 +1,11 @@
+<?xml version="1.0"?>
+<!DOCTYPE gui>
+<gui name="opera_xxport" version="2">
+<MenuBar>
+ <Menu name="file"><text>&amp;File</text>
+ <Menu name="file_import"><text>&amp;Import</text>
+ <Action name="file_import_opera"/>
+ </Menu>
+ </Menu>
+</MenuBar>
+</gui>
diff --git a/kaddressbook/xxport/pab_mapihd.cpp b/kaddressbook/xxport/pab_mapihd.cpp
new file mode 100644
index 000000000..bcf541d75
--- /dev/null
+++ b/kaddressbook/xxport/pab_mapihd.cpp
@@ -0,0 +1,396 @@
+/***************************************************************************
+ mapihd.cpp - description
+ -------------------
+ begin : Tue Jul 25 2000
+ copyright : (C) 2000 by Hans Dijkema
+ email : kmailcvt@hum.org
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+#include "pab_pablib.h"
+
+bool operator < (mapitag_t & a,mapitag_t & b) { return a._order<b._order; }
+bool operator > (mapitag_t & a,mapitag_t & b) { return a._order>b._order; }
+bool operator == (mapitag_t & a,mapitag_t & b) { return a._order==b._order; }
+
+static word_t
+map_givenname[]=
+ { pr_givenname,
+ SET_MS_GIVEN_NAME,
+ 0
+ },
+map_email[]=
+ { pr_email,
+ SET_MS_EMAIL,
+ 0
+ },
+map_firstname[]=
+ { pr_firstname,
+ SET_MS_FIRSTNAME,
+ 0
+ },
+map_lastname[]=
+ { pr_lastname,
+ SET_MS_LASTNAME,
+ 0
+ },
+map_additionalname[]=
+ { pr_additionalname,
+ SET_MS_MIDDLENAME,
+ 0
+ },
+map_title[]=
+ { pr_title,
+ SET_MS_TITLE,
+ 0
+ },
+map_address[]=
+ { pr_address,
+ SET_MS_ADDRESS,
+ 0
+ },
+map_zip[]=
+ { pr_zip,
+ SET_MS_ZIP,
+ 0
+ },
+map_state[]=
+ { pr_state,
+ SET_MS_STATE,
+ 0
+ },
+map_town[]=
+ { pr_town,
+ SET_MS_TOWN,
+ 0
+ },
+map_country[]=
+ { pr_country,
+ SET_MS_COUNTRY,
+ 0
+ },
+map_tel[]=
+ { pr_tel,
+ SET_MS_TEL,
+ 0
+ },
+map_mobile[]=
+ { pr_mobile,
+ SET_MS_MOBILE,
+ 0
+ },
+map_fax[]=
+ { pr_fax,
+ SET_MS_FAX,
+ 0
+ },
+map_job[]=
+ { pr_job,
+ HP_OPENMAIL_JOB,
+ 0
+ },
+map_organization[]=
+ { pr_organization,
+ SET_MS_ORGANIZATION,
+ HP_OPENMAIL_ORGANIZATION,
+ 0
+ },
+map_department[]=
+ { pr_department,
+ SET_MS_DEPARTMENT,
+ HP_OPENMAIL_DEPARTMENT,
+ 0
+ },
+map_subdep[]=
+ { pr_subdep,
+ HP_OPENMAIL_SUBDEP,
+ 0
+ },
+map_notes[]=
+ { pr_notes,
+ SET_MS_COMMENT,
+ 0
+ },
+map_notused[]=
+ { pr_notused,
+ HP_OPENMAIL_LOCATION_OF_WORK, // location of work
+ SET_NOT_USED,
+ 0
+ };
+
+
+static word_t *mapi_map[]={ map_givenname, map_email,
+ map_firstname, map_lastname, map_additionalname,map_title,
+ map_address, map_town, map_zip, map_state, map_country,
+ map_tel, map_mobile, map_fax,
+ map_organization, map_department, map_subdep, map_job,
+ map_notes,
+ map_notused,
+ NULL
+ };
+
+pabrec_entry mapitag_t::matchTag(void)
+{
+int i,j;
+pabrec_entry e=pr_unknown;
+
+ for(i=0;mapi_map[i]!=NULL && e==pr_unknown;i++) {
+ for(j=1;mapi_map[i][j]!=0 && _tag!=mapi_map[i][j];j++);
+ if (mapi_map[i][j]!=0) {
+ e=(pabrec_entry) mapi_map[i][0];
+ }
+ }
+return e;
+}
+
+pabfields_t::pabfields_t(pabrec & R, QWidget * /*parent*/)
+{
+ // Skip the first two words, because they're always the
+ // same 000c 0014 ==> 0014 gives us the types, so we
+ // parse from 0014 till the next offset and order the tags.
+
+ int mb,me;
+ uint i,k;
+ content_t _tag,_order;
+
+ mb=R[1];
+ me=R[2];
+
+ while (mb<me) {
+ _tag=R.read(mb);mb+=sizeof(_tag);
+ _order=R.read(mb);mb+=sizeof(_order);
+
+ {mapitag_t mt(_tag,_order);
+ tags[tags.size()]=mt;
+ context_tags[context_tags.size()]=mt;
+ }
+ }
+ tags.sort();
+
+ // get the right entries now
+
+ for(i=2,k=0;i<R.N() && k<tags.size();i++,k++) {
+ if (!isUsed(k)) { i-=1; }
+ else {pabrec_entry e;
+ QString E;
+
+ e=isWhat(k);
+ E=R.getEntry(i);
+ { QString s=E;
+ s=s.stripWhiteSpace();
+ E=s;
+ }
+
+ /*
+ { char m[1024];
+ snprintf(m, sizeof(m), "%d %d %04x %08lx %d %s %d %d",i,k,literal(k),order(k),e,E.latin1(),E[0].latin1(),E.length());
+ info->addLog(m);
+ }
+ */
+
+ if (!E.isEmpty()) {
+
+ switch (e) {
+ case pr_givenname: givenName=E;
+ break;
+ case pr_email: email=E;
+ break;
+ case pr_firstname: firstName=E;
+ break;
+ case pr_additionalname: additionalName=E;
+ break;
+ case pr_lastname: lastName=E;
+ break;
+ case pr_title: title=E;
+ break;
+ case pr_address: address=E;
+ break;
+ case pr_town: town=E;
+ break;
+ case pr_state: state=E;
+ break;
+ case pr_zip: zip=E;
+ break;
+ case pr_country: country=E;
+ break;
+ case pr_organization: organization=E;
+ break;
+ case pr_department: department=E;
+ break;
+ case pr_subdep: subDep=E;
+ break;
+ case pr_job: job=E;
+ break;
+ case pr_tel: tel=E;
+ break;
+ case pr_fax: fax=E;
+ break;
+ case pr_modem: modem=E;
+ break;
+ case pr_mobile: mobile=E;
+ break;
+ case pr_url: homepage=E;
+ break;
+ case pr_talk: talk=E;
+ break;
+ case pr_notes: comment=E;
+ break;
+ case pr_birthday: birthday=E;
+ break;
+ case pr_notused:
+ break;
+ default: {/*char m[250];
+ snprintf(m,sizeof(m),"unknown tag '%x'",literal(k));
+ info->log(m);*/
+ }
+ break;
+ }
+ }
+ }
+ }
+
+ if (!firstName.isEmpty() && !lastName.isEmpty()) {
+ givenName=lastName+", "+firstName;
+ }
+
+ // Determine if the record is ok.
+
+ OK=true;
+}
+
+bool pabfields_t::isUsed(int k)
+{
+return tags[k].isUsed();
+}
+
+pabrec_entry pabfields_t::isWhat(int k)
+{
+return tags[k].matchTag();
+}
+
+word_t pabfields_t::literal(int k)
+{
+return tags[k].literal();
+}
+
+content_t pabfields_t::order(int k)
+{
+return tags[k].order();
+}
+
+KABC::Addressee pabfields_t::get() {
+ KABC::Addressee a;
+ if (!givenName.isEmpty()) a.setFormattedName(givenName);
+ if (!email.isEmpty()) a.insertEmail(email);
+ if (!title.isEmpty()) a.setTitle(title);
+ if (!firstName.isEmpty()) a.setName(firstName);
+ if (!additionalName.isEmpty()) a.setAdditionalName(additionalName);
+ if (!lastName.isEmpty()) a.setFamilyName(lastName);
+
+ KABC::Address addr;
+ if (!address.isEmpty()) addr.setStreet(address);
+ if (!town.isEmpty()) addr.setLocality(town);
+ if (!zip.isEmpty()) addr.setPostalCode(zip);
+ if (!state.isEmpty()) addr.setRegion(state);
+ if (!country.isEmpty()) addr.setCountry(country);
+ a.insertAddress(addr);
+
+ if (!organization.isEmpty()) a.setOrganization(organization);
+ if (!department.isEmpty()) a.setRole(department);
+ // Miss out department, subDep, job
+ if (!tel.isEmpty()) a.insertPhoneNumber( KABC::PhoneNumber( tel, KABC::PhoneNumber::Voice ) );
+ if (!fax.isEmpty()) a.insertPhoneNumber( KABC::PhoneNumber( fax, KABC::PhoneNumber::Fax ) );
+ if (!mobile.isEmpty()) a.insertPhoneNumber( KABC::PhoneNumber( mobile, KABC::PhoneNumber::Cell ) );
+ if (!modem.isEmpty()) a.insertPhoneNumber( KABC::PhoneNumber( modem, KABC::PhoneNumber::Modem ) );
+ if (!homepage.isEmpty()) a.setUrl(KURL( homepage ));
+ // Miss out talk
+ if (!comment.isEmpty()) a.setNote(comment);
+ // Miss out birthday
+ return a;
+}
+
+
+
+
+/* class pabrec {
+ private:
+ char entry[1024];
+ byte *_mem;
+ word_t *_N;
+ word_t *_w;
+ public:
+ pabrec(pab *); // expects record the begin at reading point (ftell).
+ ~pabrec();
+ public:
+ word_t N(void) { return _N[0]; }
+ word_t operator[](int i) { return _w[i]; }
+ const char *getEntry(int i);
+ public:
+ content_t read(word_t offset);
+ };
+*/
+
+pabrec::pabrec(pab & P)
+{
+adr_t A=P.tell();
+content_t hdr;
+word_t offset,size,dummy;
+int i;
+
+ hdr=P.go(A);
+ offset=P.lower(hdr);
+
+ size=offset;
+ _mem=new byte[size];
+ P.read(_mem,size);
+
+ P.go(A+offset);
+ P.read(m_N);
+ m_W=new word_t[m_N+1];
+
+ P.read(dummy);
+ for(i=0;i<=m_N;i++) {
+ P.read(m_W[i]);
+ }
+}
+
+pabrec::~pabrec()
+{
+ delete _mem;
+ delete m_W;
+}
+
+
+content_t pabrec::read(word_t offset)
+{
+content_t R;
+ R=_mem[offset+3];
+ R<<=8;R+=_mem[offset+2];
+ R<<=8;R+=_mem[offset+1];
+ R<<=8;R+=_mem[offset];
+return R;
+}
+
+const char *pabrec::getEntry(int i)
+{
+int mb,me;
+int k;
+ mb=m_W[i];me=m_W[i+1];
+ for(k=0;mb!=me;mb++) {
+ if (_mem[mb]>=' ' || _mem[mb]=='\n' || _mem[mb]==13 || _mem[mb]=='\t') {
+ if (_mem[mb]==13) { entry[k]='\n'; }
+ else { entry[k]=_mem[mb]; }
+ k+=1;
+ }
+ }
+ entry[k]='\0';
+return (const char *) entry;
+}
diff --git a/kaddressbook/xxport/pab_mapihd.h b/kaddressbook/xxport/pab_mapihd.h
new file mode 100644
index 000000000..c4bb58a77
--- /dev/null
+++ b/kaddressbook/xxport/pab_mapihd.h
@@ -0,0 +1,117 @@
+/***************************************************************************
+ mapihd.h - description
+ -------------------
+ begin : Tue Jul 25 2000
+ copyright : (C) 2000 by Hans Dijkema
+ email : kmailcvt@hum.org
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+#ifndef _MAPIHD_H_
+#define _MAPIHD_H_
+
+#include <qmemarray.h>
+
+#include "pab_xxport.h"
+
+#define T_MS_ARRAY 0x1100 // Some sort of array
+#define T_MS_STRING ((unsigned long) 0x1e) // definitely a string
+
+ typedef unsigned long adr_t;
+ typedef unsigned long content_t;
+ typedef unsigned short pabsize_t;
+ typedef unsigned char byte_t;
+ typedef unsigned short word_t;
+ typedef byte_t byte;
+
+ class pab;
+
+ class pabrec {
+ private:
+ char entry[1024];
+ byte *_mem;
+ word_t m_N;
+ word_t *m_W;
+ public:
+ pabrec(pab &); // expects record the begin at reading point (ftell).
+ ~pabrec();
+ public:
+ word_t N(void) { return m_N; }
+ word_t operator[](int i) { return m_W[i]; }
+ const char *getEntry(int i);
+ public:
+ content_t read(word_t offset);
+ };
+
+ typedef enum {
+ pr_unknown,pr_notused,
+ pr_givenname,pr_email,
+ pr_firstname,pr_additionalname,pr_lastname,pr_title,
+ pr_address,pr_town,pr_state,pr_zip,pr_country,
+ pr_organization,pr_department,pr_subdep,pr_job,
+ pr_tel,pr_fax,pr_modem,pr_mobile,pr_url,pr_talk,
+ pr_notes,pr_birthday
+ }
+ pabrec_entry;
+
+ class mapitag_t
+ {
+ friend bool operator < (mapitag_t &,mapitag_t &);
+ friend bool operator > (mapitag_t &,mapitag_t &);
+ friend bool operator == (mapitag_t &,mapitag_t &);
+ private:
+ word_t _tag;
+ word_t _type;
+ content_t _order;
+ public:
+ mapitag_t(content_t tag,content_t order) { _tag=(word_t) tag;_type=(word_t) (tag>>16);_order=order; }
+ mapitag_t() { _tag=0;_type=0;_order=0; }
+ public:
+ mapitag_t & operator = (mapitag_t & t) { _tag=t._tag;_type=t._type;_order=t._order;return *this; }
+ public:
+ bool isUsed(void) { return (_type==T_MS_STRING || (_type&T_MS_ARRAY)!=0) && _order!=0; }
+ word_t literal(void) { return _tag; }
+ content_t order(void) { return _order; }
+ pabrec_entry matchTag(void);
+ };
+
+ bool operator < (mapitag_t & a,mapitag_t & b);
+ bool operator > (mapitag_t & a,mapitag_t & b);
+ bool operator == (mapitag_t & a,mapitag_t & b);
+
+ class pabfields_t
+ {
+ private:
+ QMemArray<mapitag_t> tags,context_tags;
+ pabrec *m_R;
+ QString givenName,email,
+ title,firstName,additionalName,lastName,
+ address,town,state,zip,country,
+ organization,department,subDep,job,
+ tel,fax,modem,mobile,homepage,talk,
+ comment,birthday;
+ bool OK;
+ private:
+ bool isUsed(int k);
+ pabrec_entry isWhat(int k);
+ word_t literal(int k);
+ content_t order(int k);
+ public:
+ pabfields_t(pabrec & R, QWidget *parent);
+ public:
+ KABC::Addressee get( );
+ bool isOK(void) { return OK; }
+ bool isUsable(void) { return givenName!=""; }
+ };
+
+
+#endif
+
diff --git a/kaddressbook/xxport/pab_pablib.cpp b/kaddressbook/xxport/pab_pablib.cpp
new file mode 100644
index 000000000..c56c4e9a3
--- /dev/null
+++ b/kaddressbook/xxport/pab_pablib.cpp
@@ -0,0 +1,333 @@
+/***************************************************************************
+ pablib.cxx - description
+ -------------------
+ begin : Tue Jul 4 2000
+ copyright : (C) 2000 by Hans Dijkema
+ email : kmailcvt@hum.org
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+#include "pab_pablib.h"
+
+#define REC_OK PAB_REC_OK
+
+
+pab::pab(const char *_pabfile)
+{
+ pabfile=_pabfile;
+ in.setName(pabfile);
+ in.open(IO_ReadOnly);
+ cap=i18n("Import MS Exchange Personal Address Book (.PAB)");
+}
+
+
+pab::~pab()
+{
+ if (in.isOpen()) { in.close(); }
+}
+
+//////////////////////////////////////////////////////////////////////
+//
+// Main conversion
+//
+//////////////////////////////////////////////////////////////////////
+
+bool pab::convert(void)
+{
+adr_t A;
+bool ret;
+
+ if (!in.isOpen()) {QString msg;
+ msg=i18n("Cannot open %1 for reading").arg(pabfile);
+ // info->alert(msg);
+ return false;
+ }
+ if (!knownPAB()) {
+ return false;
+ }
+
+/*
+ if (!f->openAddressBook(info)) {
+ return false;
+ }
+*/
+
+ A=go(INDEX_OF_INDEX);
+ ret=convert(A,0,0);
+
+ // f->closeAddressBook();
+
+return ret;
+}
+
+bool pab::convert(adr_t A,content_t ,content_t )
+{
+adr_t table;
+content_t start,stop,T;
+int n, N = 0;
+
+ go(A);
+ T=read();
+
+ // Now we have to decide if this is a distribution list
+ // or an addressbook container. If it is the last just
+ // jump directly to dotable().
+
+ //if (upper(T)==PAB_REC_OK) {
+ // dotable(A,strt,stp);
+ // return true;
+ //}
+
+ // OK, it's not an addressbook container,
+ // handle it like a distribution list
+
+ start=T;
+ while(start!=0) {
+ N+=1;
+ stop=read();
+ table=read();
+ start=read();
+ }
+ if (N==0) { N=1; }
+/* {char m[100];
+ sprintf(m,"%d",N);
+ info->alert("",m);
+ }*/
+
+ //A=go(INDEX_OF_INDEX);
+ //printf("IoI=%08lx\n",A);
+ go(A);
+ start=read();
+ n=0;
+ while(start!=0) {adr_t cp;
+ stop=read();
+ table=read();
+ cp=tell();
+ dotable(table,start,stop);
+ //convert(table,start,stop);
+ go(cp);
+ start=read();
+ n+=1;
+ // info->setOverall( 100 * n / N );
+ }
+
+return true;
+}
+
+
+void pab::dotable(adr_t T,content_t start,content_t stop)
+{
+adr_t REC,pREC,cp;
+content_t cmp,skip;
+int N,n;
+
+ go(T);
+ cp=tell();
+
+ REC=0xffffffff;
+ pREC=0;
+ cmp=read();
+ if (cmp!=start) {
+ // first try processing as if this was a record. I.e. at the stop thing
+ processRec(stop);
+ // Then exit
+ // info->setCurrent();
+ // info->setCurrent(100);
+ return;
+ } // This is not a table.
+
+ // info->setCurrent();
+ N=0;
+ while (cmp!=stop && REC!=pREC) {
+ pREC=REC;
+ REC=read();
+ if (REC!=pREC) {
+ skip=read();
+ cmp=read();
+ }
+ N+=1;
+ }
+
+ go(cp);
+ REC=0xffffffff;
+ pREC=0;
+
+ cmp=read();
+
+ n=0;
+ while(cmp!=stop && REC!=pREC) {adr_t cp;
+ pREC=REC;
+ REC=read();
+ if (REC!=pREC) {
+ skip=read();
+ cp=tell();
+ processRec(REC);
+ go(cp);
+ cmp=read();
+ }
+ n+=1;
+ // info->setCurrent(100 * n / N);
+ }
+
+ // info->setCurrent();
+ // info->setCurrent(100);
+}
+
+
+void pab::processRec(adr_t REC)
+{
+content_t hdr;
+
+ hdr=go(REC);
+ if (upper(hdr)==REC_OK) { // Now read a record and instantiate!
+ pabrec rec(*this);
+ pabfields_t fields(rec, NULL);
+
+ if (fields.isOK() && fields.isUsable()) {
+ // f->addContact( fields.get() );
+ }
+ }
+}
+
+void pab::prt(unsigned char *,pabrec &,pabrec_entry )
+{
+}
+
+#define PABREC_N (sizeof(pabrec)/sizeof(word_t))
+
+void pab::rdPabRec(pabrec & )
+{
+}
+
+//////////////////////////////////////////////////////////////////////
+//
+// Here's where we recognize the record types
+//
+//////////////////////////////////////////////////////////////////////
+
+bool pab::recUnknown(pabrec &)
+{
+return false;
+}
+
+bool pab::recNoFunction(pabrec & )
+{
+return false;
+}
+
+const char *pab::get(unsigned char *,pabrec_entry ,pabrec & )
+{
+return "";
+}
+
+void pab::getrange(pabrec & ,pabrec_entry ,word_t & ,word_t & )
+{
+}
+
+//////////////////////////////////////////////////////////////////////
+//
+// Here's where we recognize the PAB files
+//
+//////////////////////////////////////////////////////////////////////
+
+bool pab::knownPAB(void)
+{
+content_t id;
+ id=go(0);
+ if (id!=PAB_FILE_ID) {QString msg;
+ msg=i18n("%1 has no PAB id that I know of, cannot convert this").arg(pabfile);
+ // info->alert(msg);
+ return false;
+ }
+return true;
+}
+
+
+//////////////////////////////////////////////////////////////////////
+//
+// Functions to do file reading/positioning
+//
+//////////////////////////////////////////////////////////////////////
+
+content_t pab::go(adr_t a)
+{
+content_t A;
+ in.at(a);
+ A=read();
+ in.at(a);
+return A;
+}
+
+content_t pab::read(void)
+{
+unsigned char mem[4];
+content_t A;
+ in.readBlock((char *) &mem, sizeof(A)); // WinTel unsigned long opslag
+ A=mem[3];
+ A<<=8;A|=mem[2];
+ A<<=8;A|=mem[1];
+ A<<=8;A|=mem[0];
+return A;
+}
+
+void pab::read(word_t & w)
+{
+unsigned char mem[2];
+ in.readBlock((char *) &mem, sizeof(w));
+ w=mem[1];
+ w<<=8;w|=mem[0];
+}
+
+content_t pab::relative(int words)
+{
+adr_t a;
+ a=in.at();
+return go(a+(words*sizeof(content_t)));
+}
+
+content_t pab::add(adr_t & A,int words)
+{
+ A+=(words*sizeof(content_t));
+return go(A);
+}
+
+pabsize_t pab::size(content_t A)
+{
+return A&0xFFFF;
+}
+
+word_t pab::lower(content_t A)
+{
+return A&0xFFFF;
+}
+
+word_t pab::upper(content_t A)
+{
+return A>>16;
+}
+
+void pab::size(content_t A,pabsize_t & s1,pabsize_t & s2)
+{
+ s1=A&0xFFFF;
+ s2>>=16;
+}
+
+byte_t pab::readbyte(void)
+{
+byte_t c;
+ c=in.getch();
+return c;
+}
+
+void pab::read(unsigned char *mem,content_t size)
+{
+ in.readBlock((char *) mem, size);
+}
diff --git a/kaddressbook/xxport/pab_pablib.h b/kaddressbook/xxport/pab_pablib.h
new file mode 100644
index 000000000..ff54a32a2
--- /dev/null
+++ b/kaddressbook/xxport/pab_pablib.h
@@ -0,0 +1,77 @@
+/***************************************************************************
+ pablib.hxx - description
+ -------------------
+ begin : Tue Jul 4 2000
+ copyright : (C) 2000 by Hans Dijkema
+ email : kmailcvt@hum.org
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+
+#ifndef PAB_LIB_HXX
+#define PAB_LIB_HXX
+
+#include <klocale.h>
+#include <qfile.h>
+
+#include "pab_mapihd.h"
+
+#define INDEX_OF_INDEX 0x000000c4
+#define PAB_REC_OK 0xbcec
+#define PAB_FILE_ID 0x4e444221
+
+class pab
+{
+ friend class pabrec;
+
+ private:
+ QFile in;
+ const char *pabfile;
+ QString cap;
+ QWidget *parent;
+ public:
+ pab(const char *pabFile);
+ ~pab();
+ private:
+ content_t skip(int longwords) { return relative(longwords); }
+ content_t go(adr_t);
+ content_t relative(int longwords);
+ content_t relative(pabsize_t);
+ content_t add(adr_t &,int words);
+ content_t read(void);
+ void read(unsigned char *mem,content_t size);
+ void read(word_t &);
+ pabsize_t size(content_t);
+ void size(content_t,pabsize_t &, pabsize_t &);
+ word_t lower(content_t);
+ word_t upper(content_t);
+ byte_t readbyte(void);
+ adr_t curpos(void) { return in.at(); }
+ adr_t tell(void) { return curpos(); }
+ private:
+ bool recUnknown(pabrec & R);
+ bool recNoFunction(pabrec & R);
+ const char *get(unsigned char *mem,pabrec_entry e,pabrec & R);
+ bool knownPAB(void);
+ private:
+ void rdPabRec(pabrec & R);
+ void prt(unsigned char *mem,pabrec & R,pabrec_entry E);
+ void getrange(pabrec & R,pabrec_entry e,word_t & b,word_t & _e);
+ private:
+ bool convert(adr_t A,content_t start,content_t stop);
+ void dotable(adr_t table,content_t start,content_t stop);
+ void processRec(adr_t REC);
+ public:
+ bool convert(void);
+};
+
+
+#endif
diff --git a/kaddressbook/xxport/pab_xxport.cpp b/kaddressbook/xxport/pab_xxport.cpp
new file mode 100644
index 000000000..621e5d2c2
--- /dev/null
+++ b/kaddressbook/xxport/pab_xxport.cpp
@@ -0,0 +1,71 @@
+/*
+ This file is part of KAddressbook.
+ Copyright (c) 2000 Hans Dijkema <kmailcvt@hum.org>
+ Copyright (c) 2003 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 as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ 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 Qt, and distribute the resulting executable,
+ without including the source code for Qt in the source distribution.
+*/
+
+#include <qfile.h>
+
+#include <kdebug.h>
+#include <kfiledialog.h>
+#include <kio/netaccess.h>
+#include <klocale.h>
+#include <kmessagebox.h>
+#include <kprocess.h>
+#include <kstandarddirs.h>
+#include <ktempfile.h>
+#include <kurl.h>
+
+#include "xxportmanager.h"
+
+#include "pab_xxport.h"
+
+K_EXPORT_KADDRESSBOOK_XXFILTER( libkaddrbk_pab_xxport, PABXXPort )
+
+PABXXPort::PABXXPort( KABC::AddressBook *ab, QWidget *parent, const char *name )
+ : KAB::XXPort( ab, parent, name )
+{
+ createImportAction( i18n("Import MS Exchange Personal Address Book (.PAB)") );
+}
+
+KABC::AddresseeList PABXXPort::importContacts( const QString& ) const
+{
+ KABC::AddresseeList addrList;
+
+ QString fileName = KFileDialog::getOpenFileName( QDir::homeDirPath(),
+ "*.[pP][aA][bB]|" + i18n("MS Exchange Personal Address Book Files (*.pab)"), 0 );
+ if ( fileName.isEmpty() )
+ return addrList;
+ if ( !QFile::exists( fileName ) ) {
+ KMessageBox::sorry( parentWidget(), i18n( "<qt>Could not find a MS Exchange Personal Address Book <b>%1</b>.</qt>" ).arg( fileName ) );
+ return addrList;
+ }
+
+ // pab PAB(QFile::encodeName(file),this,info);
+ // info->setFrom(file);
+ // PAB.convert();
+
+ return addrList;
+}
+
+#include "pab_xxport.moc"
+
+// vim: ts=2 sw=2 et
diff --git a/kaddressbook/xxport/pab_xxport.desktop b/kaddressbook/xxport/pab_xxport.desktop
new file mode 100644
index 000000000..e35ad24d4
--- /dev/null
+++ b/kaddressbook/xxport/pab_xxport.desktop
@@ -0,0 +1,103 @@
+[Desktop Entry]
+X-KDE-Library=libkaddrbk_pab_xxport
+Name=KAB MS Exchange Personal Addressbook XXPort Plugin
+Name[af]=KAB MS Exchange adresboek XXPort inprop module
+Name[be]=Дапаўненне KAB "Імпарт пэрсанальнай адраснай кнігі MS Exchange"
+Name[bg]=Приставка за XXPort на MS Exchange на KAB
+Name[bs]=KAB dodatak za MS Exchange Personal Addressbook XXPort
+Name[ca]=Endollable d'importació/exportació de la llibreta d'adreces personal d'MS Exchange per al KAB
+Name[cs]=Exportní modul do adresáře MS Exchange
+Name[cy]=Ategyn XXPort Llyfr Cyfeiriadau Personol MS Exchange KAB
+Name[da]=KAB MS Exchange personlig adressebog XXPort Plugin
+Name[de]=MS-Exchange-Adressbuch-XXPort-Modul
+Name[el]=Πρόσθετο εισαγωγής MS Exchange προσωπικού βιβλίου διευθύνσεων του KAB
+Name[es]=Plugin de KAB para {im,ex}portar libretas de direcciones personales de MS Exchange
+Name[et]=KAB MS Exchange personaalse aadressiraamatu importplugin
+Name[eu]=KAB-en MS Exchange Personal helbide-liburu in/esportazio plugin-a
+Name[fa]=وصلۀ XXPort کتاب نشانی شخصی مبادلۀ KAB MS
+Name[fi]=KAB MS Exchangen henkilökohtaisen osoitekirjan liitännäinen
+Name[fr]=Module d'import / export de carnets d'adresses personnels de MS Exchange pour KAB
+Name[fy]=KAB MS Exchange Personal Addressbook XXPort-plugin
+Name[gl]=Extensión XXPort do Caderno de Enderezos de MS Exchange para KAB
+Name[hi]=केएबी एमएस एक्सचेंज निजी पता पुस्तिका XXपोर्ट प्लगइन
+Name[hu]=KAB XXPort bővítőmodul MS Exchange személyes címjegyzékekhez
+Name[is]=Íforrit fyrir KAB MS Exchange Personal Addressbook XXPort
+Name[ja]=KAB MS Exchange パーソナルアドレス帳インポート/エクスポートプラグイン
+Name[ka]= MS Exchange-ის პერსონალური წიგნაკის ექსპორტის მოდული
+Name[kk]=MS Exchange адрестік кітапшасына экспорт/импорт ету
+Name[km]=កម្មវិធី​ជំនួយ KAB MS Exchange Personal Addressbook XXPort
+Name[lt]=KAB MS Exchange asmeninės adresų knygelės XXPort priedas
+Name[ms]=Plugin Buku Alamat Peribadi KAB MS Exchange XXPort Plugin
+Name[nb]=KAB-programtillegg for import fra MS Exchange
+Name[nds]=MSExchange-Importmoduul för KAdressbook
+Name[ne]=KAB MS बिनिमय व्यक्तिगत ठेगाना पुस्तिका XXPort प्लगइन
+Name[nl]=KAB MS Exchange Personal Addressbook XXPort-plugin
+Name[nn]=KAB MS Exchange personleg adressebok XXPort programtillegg
+Name[pl]=Wtyczka KAB do importu Osobistej książki adresowej MS Exchange
+Name[pt]='Plugin' XXPort do Livro de Endereços Pessoal do MS Exchange para o KAB
+Name[pt_BR]=Plug-in do KAB para Im/Exportação de/para Livro de Endereços Pessoal do MS Exchange
+Name[ru]=Импорт контактов MS Exchange
+Name[sk]=KAB modul pre xxport z osobného adresára MS Exchange
+Name[sl]=Vstavek KAB MS Exchange Personal Addressbook XXPort
+Name[sr]=XXPort прикључак KAB-а за MS Exchange лични адресар
+Name[sr@Latn]=XXPort priključak KAB-a za MS Exchange lični adresar
+Name[sv]=Adressbokens överföringsinsticksprogram för MS Exchange personlig adressbok
+Name[ta]=KAB MS Exchange Personal Address Books ஏற்றுமதி சொருகுப்பொருள்
+Name[tg]=Воридоти алоқаҳои MS Exchange
+Name[tr]=KAB MS Exchange Kişisel Adres Defteri XXPort Eklentisi
+Name[uk]=Втулок KAB для обміну з персональною адресною книгою MS Exchange
+Name[zh_CN]=KAB MS Exchange 个人地址簿 XXPort 插件
+Name[zh_TW]=KAB MS Exchange Personal Addressbook XXPort 外掛程式
+Comment=Plugin to import MS Exchange Personal Address Books
+Comment[af]=Inprop module wat kontakte in MS Exchange adresboek formaat invoer
+Comment[be]=Дапаўненне для імпарту пэрсанальнай адраснай кнігі MS Exchange
+Comment[bg]=Приставка за импортиране на контактите от MS Exchange Personal Address Books
+Comment[bs]=Dodatak za uvoz iz MS Exchange personalnog adresara
+Comment[ca]=Endollable per a importar des de la llibreta d'adreces personal d'MS Exchange
+Comment[cs]=Modul pro import osobní knihy adres MS Exchange
+Comment[cy]=Ategyn i fewnforio Llyfrau Cyfeiriadau Personol MS Exchange
+Comment[da]=Plugin til at importere MS Exchange personlige adressebøger
+Comment[de]=Modul für den Import von persönlichen Adressbüchern aus MS Exchange
+Comment[el]=Πρόσθετο για εισαγωγή προσωπικών βιβλίων διευθύνσεων του MS Exchange
+Comment[es]=Plugin para importar libretas de direcciones personales de MS Exchange
+Comment[et]=Plugin MS Exchange personaalse aadressiraamatu importimiseks
+Comment[eu]=MS Exchange Personal helbid-liburuak in/esportatzeko plugina-
+Comment[fa]=وصله برای واردات کتابهای نشانی شخصی مبادلۀ MS
+Comment[fi]=Liitännäinen MS Exchangen henkilökohtaisten osoitekirjojen tuontiin
+Comment[fr]=Module d'import des carnets d'adresses personnels MS Exchange
+Comment[fy]=Plugin foar it ymporteajen fan MS Exchange-adresboeken
+Comment[gl]=Extensión para importar Cadernos de Enderezos Persoais de MS Exchange
+Comment[hi]=एमएस एक्सचेंज निजी पता पुस्तिका को आयात करने का प्लगइन
+Comment[hu]=Bővítőmodul MS Exchange személyes címjegyzékek importálásához
+Comment[is]=Íforrit til að flytja tengiliði í eða úr MS Exchange Personal Address Book
+Comment[it]=Plugin per importare rubriche personali da MS Exchange
+Comment[ja]=MS Exchange パーソナルアドレス帳をインポートするプラグイン
+Comment[ka]=MS Exchange-ის პერსონალური წიგნაკის იმპორტის მოდული
+Comment[kk]=MS Exchange адрестік кітапшасына экспорт/импорт ету модулі
+Comment[km]=កម្មវិធី​ជំនួយ​ដើម្បី​នាំចូល​សៀវភៅ​អាសយដ្ឋាន​ផ្ទាល់​ខ្លួន​របស់ MS Exchange
+Comment[lt]=Priedas leidžiantis importuoti MS Exchange asmenines adresų knygeles
+Comment[mk]=Приклучок за внесување лични адресари од MS Exchange
+Comment[ms]=Plugin untuk mengimpot Buku Alamat Peribadi MS Exchange
+Comment[nb]=Programtillegg for import av personlige adressebøker fra MS Exchange
+Comment[nds]=Moduul för't Importeren vun persöönliche Adressböker ut MS Exchange
+Comment[ne]=MS बिनिमय व्यक्तिगत ठेगाना पुस्तिका आयात गर्न प्लगइन गर्नुहोस्
+Comment[nl]=Plugin voor het importeren van MS Exchange-adresboeken
+Comment[nn]=Programtillegg for å imortera MS Exchange personleg adressebok
+Comment[pl]=Wtyczka do importu Osobistej książki adresowej z MS Exchange
+Comment[pt]=Um 'plugin' para importar os livros de endereços pessoais do MS Exchange
+Comment[pt_BR]=Plug-in para importar Livros de Endereços Pessoais do MS Exchange
+Comment[ru]=Импорт персональных адресных книг MS Exchange
+Comment[sk]=Modul pre import osobných adresárov MS Exchange
+Comment[sl]=Vstavek za uvoz osebnih adresarjev MS Exchange
+Comment[sr]=Прикључак за увоз MS Exchange личних адресара
+Comment[sr@Latn]=Priključak za uvoz MS Exchange ličnih adresara
+Comment[sv]=Insticksprogram för import av MS Exchange personliga adressböcker
+Comment[ta]=MS Exchange Personal Address Books இறக்குமதி செய்ய சொருகுப்பொருள்
+Comment[tg]=Модул барои воридоти китобҳои адреси шахсии MS Exchange
+Comment[tr]=MS Exchange Kişisel Adres Defteri aktarım eklentisi
+Comment[uk]=Втулок для імпорту персональних адресних книг MS Exchange
+Comment[zh_CN]=导入 MS Exchange 个人地址簿的插件
+Comment[zh_TW]=匯入 MS Exchange Personal 通訊錄的外掛程式
+Type=Service
+ServiceTypes=KAddressBook/XXPort
+X-KDE-KAddressBook-XXPortPluginVersion=1
diff --git a/kaddressbook/xxport/pab_xxport.h b/kaddressbook/xxport/pab_xxport.h
new file mode 100644
index 000000000..5c1edb508
--- /dev/null
+++ b/kaddressbook/xxport/pab_xxport.h
@@ -0,0 +1,217 @@
+/*
+ This file is part of KAddressbook.
+ Copyright (c) 2000 - 2000 Hans Dijkema <kmailcvt@hum.org>
+ 2003 - 2003 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 as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ 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 Qt, and distribute the resulting executable,
+ without including the source code for Qt in the source distribution.
+*/
+
+#ifndef PAB_XXPORT_H
+#define PAB_XXPORT_H
+
+#include <xxport.h>
+
+class PABXXPort : public KAB::XXPort
+{
+ Q_OBJECT
+
+ public:
+ PABXXPort( KABC::AddressBook *ab, QWidget *parent, const char *name = 0 );
+
+ QString identifier() const { return "pab"; }
+
+ public slots:
+ KABC::AddresseeList importContacts( const QString &data ) const;
+
+ private:
+ void doExport( QFile *fp, const KABC::AddresseeList &list );
+};
+
+
+
+
+/////////////////////////////////////////////////////////////////////////////
+
+/*
+ * MS Windows tags as reengineered from an MS Exchange .PAB and
+ * Outlook .PAB file.
+ */
+
+/////////////////////////////////////////////////////////////////////////////
+
+#define MS_GIVEN_NAME 0x3a13
+#define MS_GIVEN_NAME_1 0x3a45
+#define MS_GIVEN_NAME_2 0x3a47
+#define MS_GIVEN_NAME_3 0x3a4f
+#define MS_GIVEN_NAME_4 0x3001
+#define MS_GIVEN_NAME_5 0x3a20
+#define SET_MS_GIVEN_NAME \
+ MS_GIVEN_NAME,MS_GIVEN_NAME_1,MS_GIVEN_NAME_2, \
+ MS_GIVEN_NAME_3,MS_GIVEN_NAME_4,MS_GIVEN_NAME_5
+
+/////////////////////////////////////////////////////////////////////////////
+
+#define MS_EMAIL 0x3a56
+#define MS_EMAIL_1 0x3003
+#define SET_MS_EMAIL \
+ MS_EMAIL,MS_EMAIL_1
+
+/////////////////////////////////////////////////////////////////////////////
+
+#define MS_FIRSTNAME 0x3a06
+#define SET_MS_FIRSTNAME \
+ MS_FIRSTNAME
+
+/////////////////////////////////////////////////////////////////////////////
+
+#define MS_LASTNAME 0x3a11
+#define SET_MS_LASTNAME \
+ MS_LASTNAME
+
+
+/////////////////////////////////////////////////////////////////////////////
+
+#define MS_MIDDLENAME 0x3a44
+#define SET_MS_MIDDLENAME \
+ MS_MIDDLENAME
+
+/////////////////////////////////////////////////////////////////////////////
+
+#define MS_TITLE 0x3a17
+#define SET_MS_TITLE \
+ MS_TITLE
+
+/////////////////////////////////////////////////////////////////////////////
+
+#define MS_ADDRESS 0x3a15
+#define MS_ADDRESS_1 0x3a29
+#define MS_ADDRESS_2 0x3a59
+#define SET_MS_ADDRESS \
+ MS_ADDRESS, MS_ADDRESS_1, MS_ADDRESS_2
+
+/////////////////////////////////////////////////////////////////////////////
+
+#define MS_ZIP 0x3a5b
+#define MS_ZIP_1 0x3a2a
+#define SET_MS_ZIP \
+ MS_ZIP, MS_ZIP_1
+
+/////////////////////////////////////////////////////////////////////////////
+
+#define MS_STATE 0x3a28
+#define MS_STATE_1 0x3a5c
+#define SET_MS_STATE \
+ MS_STATE, MS_STATE_1
+
+/////////////////////////////////////////////////////////////////////////////
+
+#define MS_TOWN 0x3a27
+#define MS_TOWN_1 0x3a59
+#define SET_MS_TOWN \
+ MS_TOWN, MS_TOWN_1
+
+/////////////////////////////////////////////////////////////////////////////
+
+#define MS_COUNTRY 0x3a26
+#define MS_COUNTRY_1 0x3a5a
+#define SET_MS_COUNTRY \
+ MS_COUNTRY, MS_COUNTRY_1
+
+/////////////////////////////////////////////////////////////////////////////
+
+#define MS_TEL 0x3a08
+#define MS_TEL_1 0x3a09
+#define MS_TEL_2 0x3a1a
+#define MS_TEL_3 0x3a1b
+#define MS_TEL_4 0x3a1f
+#define MS_TEL_5 0x3a1d
+#define MS_TEL_6 0x3a2d
+#define MS_TEL_7 0x3a2f
+#define SET_MS_TEL \
+ MS_TEL,MS_TEL_1,MS_TEL_2,MS_TEL_3,MS_TEL_4, \
+ MS_TEL_5,MS_TEL_6,MS_TEL_7
+
+/////////////////////////////////////////////////////////////////////////////
+
+#define MS_MOBILE 0x3a1c
+#define MS_MOBILE_1 0x3a1e
+#define MS_MOBILE_2 0x3a21
+#define SET_MS_MOBILE \
+ MS_MOBILE,MS_MOBILE_1,MS_MOBILE_2
+
+/////////////////////////////////////////////////////////////////////////////
+
+#define MS_FAX 0x3a23
+#define MS_FAX_1 0x3a24
+#define MS_FAX_2 0x3a25
+#define MS_FAX_3 0x3a2c
+#define SET_MS_FAX \
+ MS_FAX,MS_FAX_1,MS_FAX_2,MS_FAX_3
+
+/////////////////////////////////////////////////////////////////////////////
+
+#define MS_ORG 0x3a16
+#define SET_MS_ORGANIZATION \
+ MS_ORG
+
+/////////////////////////////////////////////////////////////////////////////
+
+#define MS_DEP 0x3a18
+#define SET_MS_DEPARTMENT \
+ MS_DEP
+
+/////////////////////////////////////////////////////////////////////////////
+
+#define MS_COMMENT 0x3004
+#define SET_MS_COMMENT \
+ MS_COMMENT
+
+/////////////////////////////////////////////////////////////////////////////
+
+#define SET_NOT_USED \
+ 0x3002, \
+ 0x300b, \
+ 0x3a2e, \
+ 0x3a30, \
+ 0x3a19
+ // 3002 probably address type
+ // 300b some sort of key
+ // 3a2e secretary tel number
+ // 3a30 name of secretary
+ // 3a19 office location
+
+
+
+/////////////////////////////////////////////////////////////////////////////
+
+/*
+ * HP Openmail as reengineered from the X.400 .PAB file.
+ */
+
+/////////////////////////////////////////////////////////////////////////////
+
+#define HP_OPENMAIL_JOB 0x672b
+#define HP_OPENMAIL_ORGANIZATION 0x6728
+#define HP_OPENMAIL_DEPARTMENT 0x6729
+#define HP_OPENMAIL_SUBDEP 0x672b
+#define HP_OPENMAIL_LOCATION_OF_WORK 0x672a
+
+/////////////////////////////////////////////////////////////////////////////
+
+#endif
diff --git a/kaddressbook/xxport/pab_xxportui.rc b/kaddressbook/xxport/pab_xxportui.rc
new file mode 100644
index 000000000..14117f742
--- /dev/null
+++ b/kaddressbook/xxport/pab_xxportui.rc
@@ -0,0 +1,11 @@
+<?xml version="1.0"?>
+<!DOCTYPE gui>
+<gui name="pab_xxport" version="1">
+<MenuBar>
+ <Menu name="file"><text>&amp;File</text>
+ <Menu name="file_import"><text>&amp;Import</text>
+ <Action name="file_import_pab"/>
+ </Menu>
+ </Menu>
+</MenuBar>
+</gui>
diff --git a/kaddressbook/xxport/samples/PAB_format.pdf b/kaddressbook/xxport/samples/PAB_format.pdf
new file mode 100644
index 000000000..d94e1ac77
--- /dev/null
+++ b/kaddressbook/xxport/samples/PAB_format.pdf
Binary files differ
diff --git a/kaddressbook/xxport/samples/ecdancers.txt b/kaddressbook/xxport/samples/ecdancers.txt
new file mode 100644
index 000000000..7358e2bf7
--- /dev/null
+++ b/kaddressbook/xxport/samples/ecdancers.txt
@@ -0,0 +1,193 @@
+alias "John Collings" JCollings@example.com
+note "John Collings" <name:John Collings>Ball '99
+alias "Al Blank" Fandango@example.com
+note "Al Blank" <name:Al Blank and Nancy E. DeVore><address:123 Some AvenueSome Town, NY 12345-6789><phone:123 456-7890>Albert Blank & Nancy DeVore123 Some AvenueSome Town, NY 12345
+alias "Alan Wright" AWright29@example.com
+note "Alan Wright" <name:Alan Wright>Ball '99
+alias "Ann Margaret McKillop" AM194@example.com
+note "Ann Margaret McKillop" <name:Ann Margaret McKillop>
+alias "Anne Leslie" Fidhle1@example.com
+note "Anne Leslie" <name:Anne Leslie>
+alias "Anne Lowenthal" AnneL@example.com
+note "Anne Lowenthal" <name:Anne Lowenthal>
+alias "Annie Eden" AEdden@example.com
+note "Annie Eden" <name:Annie Eden>
+alias "Aurlie Laurence" AurelieMaria@example.com
+note "Aurlie Laurence" <name:Aurelie Laurence>Ball '99
+alias "Barbara Bezdek" ChesArch@example.com
+note "Barbara Bezdek" <name:Barbara Bezdek>
+alias "Barbara Orton" BarOrton@example.com
+note "Barbara Orton" <name:Barbara Orton>
+alias Bec BEC@example.com
+note Bec <name:Bec Hamadock>
+alias "Bob Le Mar" AllSo@example.com
+note "Bob Le Mar" <name:Robert D. Le Mar>ArtistP.O. Box 12345Some Park, MD 12345123-345-7890
+alias "Carl Andersen" Carl.Andersen@example.com
+note "Carl Andersen" <name:Carl E. Andersen (CAP, CORP)>Carol Kerr, tooECDers, '99
+alias Carl_F CF1125@example.com
+note Carl_F <name:Carl Friedman>
+alias "Carolyn Worthing" Worthing@example.com
+note "Carolyn Worthing" <name:Carolyn Worthing>
+alias "Catherine Langrehr" Langrehr@example.com
+note "Catherine Langrehr" <name:Catherine Langrehr>ECD Ball 99
+alias "Charlotte Bristow" CEBristow@example.com
+note "Charlotte Bristow" <name:Charlotte Bristow>
+alias "Chloe Maher" ChloeMaher@example.com
+note "Chloe Maher" <name:Chloe Maher>
+alias "Crystal Paul" CPaul@example.com
+note "Crystal Paul" <name:Crystal Paul>ECD Ball '99
+alias "Dan Gillespie" Dan.Gillespie@example.com
+note "Dan Gillespie" <name:Dan Gillespie>
+alias "Debra Rolison" Rolison@example.com
+note "Debra Rolison" <name:Debra Rolison>
+alias "Denis Orton" MBOrton@example.com
+note "Denis Orton" <name:Denis Orton>
+alias "Elizabeth Vermeer" EDVermeer@example.com
+note "Elizabeth Vermeer" <name:Elizabeth Vermeer>
+alias "Ellen Blumner" EBlumner@example.com
+note "Ellen Blumner" <name:Ellen Blumner>
+alias "Erica Knicker" gjhnah@example.com
+note "Erica Knicker" <name:Erica Knicker>Ball '99
+alias "Fred Blonder" Fred.Blonder@example.com
+note "Fred Blonder" <name:Fred Blonder>
+alias "Gabriel Epstein" Vaphil@example.com
+note "Gabriel Epstein" <name:Gabriel Epstein>
+alias "Grigsby Wotton" GWotton@example.com
+note "Grigsby Wotton" <name:Grigsby Wotton>
+alias "Helen Powell" Leap@example.com
+note "Helen Powell" <name:Spronging>
+alias "Henry Szymanski" hnd2szy@example.com
+note "Henry Szymanski" <name:Henry Szymanski>
+alias Howard HMarkham@earthlink.net
+note Howard <name:Howard A. Markham>
+alias "Jason Birzer" LongShot@example.com
+note "Jason Birzer" <name:Jason W. Birzer>
+alias "Jean Murphy" Jean.Murphy@example.com
+note "Jean Murphy" <name:Jean Murphy>ECD '99
+alias "Jennie Hango" JHango@example.com
+note "Jennie Hango" <name:Jennie Hango>
+alias "Jenny Beer" JBeer@example.com
+note "Jenny Beer" <name:Jennifer Beer>
+alias "Joan Milstead" JMacDougal@example.com
+note "Joan Milstead" <name:Joan M. Milstead>99 Ball
+alias "JoAnn Morris" JMorris@example.com
+note "JoAnn Morris" <name:JoAnn Morris>
+alias "John Montrie" IvanChort@example.com
+note "John Montrie" <name:John Montrie>Ball '99
+alias Jailbait JailBait@Apocalypse.org,
+note Jailbait <name:Richard (Jailbait) Segal>
+alias "Judith DeBiase" Judid@example.com
+note "Judith DeBiase" <name:Judith DeBiase>
+alias "Kloper - Dave and Julie" Kloper@example.com
+note "Kloper - Dave and Julie" <name:Dave and Julie Kloper>
+alias "Linda Taggart" Wilhelmina_d@example.com
+note "Linda Taggart" <name:Linda D. Taggart>
+alias "Lois Czapiewski" Lczap@example.com
+note "Lois Czapiewski" <name:Lois Czapiewski>EDC ball 1999
+alias "Lou Vosteen" LVosteen@example.com
+note "Lou Vosteen" <name:Lou Vosteen><address:Louis Vosteen1234 Some TreeSome Town VA 12345>ECDer
+alias "Maryn McKenna" MMcKenna@example.com>
+note "Maryn McKenna" <name:Maryn McKenna>
+alias "Maureen Orton" Mborton@example.com
+note "Maureen Orton" <name:Maureen Orton>Maureen and DenisBall 99
+alias "Melissa Weisshaus" Melissa@example.come
+note "Melissa Weisshaus" <name:Melissa Weisshaus>Entered MSW program at Bryn Mawr, Fall/Winter 1997.
+alias "Naomi Davis" NJDavis3@example.com
+note "Naomi Davis" <name:Naomi Davis>Ball '99
+alias "Pat Ruggiero" RuggieroP@example.come
+note "Pat Ruggiero" <phone:804-589-6264><address:RR #1, Box 12345Some Town, VA 12345><name:Pat Ruggiero>
+alias "Pat Ruth" Patricia.Ruth@example.come
+note "Pat Ruth" <name:Pat Ruth>
+alias "Paul Ballard" Ballard@example.com
+note "Paul Ballard" <name:Paul Ballard>
+alias "Ralph Shore" RDShore@example.com
+note "Ralph Shore" <name:Ralph Shore>ECD Ball 1999
+alias "Richard Winston" RBWinston@example.com
+note "Richard Winston" <name:Richard B. Winston>ECD '99
+alias Rudy SFRudy@example.com
+note Rudy <name:Susan Rudy>
+alias "Sam Rotenberg" SRotenbe@example.com
+note "Sam Rotenberg" <name:Sam Rotenberg>
+alias "Sandra Linenschmidt" S2LINEN@example.com
+note "Sandra Linenschmidt" <name:Sandi Linenschmidt>Ball '99
+alias "Susan Dudley" SusanDudle@example.com
+note "Susan Dudley" <name:Susan Dudley>Ball Registrant, 1998
+alias "Susie Lorland" ben@example.com
+note "Susie Lorland" <name:Susie Lorland>
+alias "Tanya Rotenberg" GTRotenb@example.com
+note "Tanya Rotenberg" <name:Tanya Rotenberg>
+alias "Ted Rudofker" TedRudofker@example.com
+note "Ted Rudofker" <name:Ted Rudofker>
+alias "Tenby Ihde" Dyfed@example.com
+note "Tenby Ihde" <name:Tenby Ihde>New ECDer from VA.
+alias "Terry Shehan" SheehanTA@example.com
+note "Terry Shehan" <name:Terry Sheehan>
+alias "Tom Anastasio" taanatasio@example.com
+note "Tom Anastasio" <name:Tom Anastasio>
+alias "Vicky Bocock" HMVB@example.com
+note "Vicky Bocock" <name:Vicky Bocock>
+alias "Wayne Harvey" Waynne@example.com
+note "Wayne Harvey" <name:Wayne Harvey>
+alias Wexelblatt tigerlil@example.com
+note Wexelblatt <name:Pat Wexelblatt>
+alias Witt LauerWitt@example.com
+note Witt <name:Gretchen & Andrew Witt>
+alias "Kim Shaw" Trailmix5@example.com
+note "Kim Shaw" <name:Kim Shaw>Ball '99 on scholarship
+alias "JoAnne Rawls" JRawls@example.com
+note "JoAnne Rawls" <name:JoAnne Rawls>ljrawls@example.com
+alias "Susan Murrow" 75272.730@example.com
+note "Susan Murrow" <name:Susan Murrow>
+alias "Carol Oneill"
+note "Carol Oneill" <address:12346 Some AveSome Town, PA 12345-1234><name:Carol Oneill>
+alias "Valerie Webster" I_W_Webster@example.com
+note "Valerie Webster" <address:2 Some CloseSome Town, Some County AB12 3DFEngland><name:Valerie and Ian Webster>Dancer in England
+alias "Margherita Davis" Margheritad@example.com
+note "Margherita Davis" <name:Margherita Davis>
+alias Sheryl Sheryl.Griffith@example.com
+note Sheryl <name:Sheryl Griffith>
+alias "Alice Rose" AliceRoseAdams@example.com
+note "Alice Rose" <name:Alice Rose Adams>
+alias "Arlene Ring" ARleneRing@example.com
+note "Arlene Ring" <name:Arlene Ring>
+alias "Tom Maher" ClareCello@example.com
+note "Tom Maher" <name:Tom Maher>
+alias "Holly Steussy" SteussyHa@example.com
+note "Holly Steussy" <name:Holly Steussy>
+alias "Barbara Harding" BarbHarding@example.com
+note "Barbara Harding" <name:Barbara Harding>
+alias "David Millstone" Millstone@example.com
+note "David Millstone" <name:David H. Millstone>
+alias "Leonard Lu" LWLu@example.com
+alias "Al Petty" APetty@example.com
+note "Al Petty" <name:Al Petty>
+alias "Bob Farrell" Baronanely@example.com
+note "Bob Farrell" <name:Bob Farrell>
+alias "Deborah Sheldon" DSheldon@example.com
+note "Deborah Sheldon" <name:Deborah Sheldon>
+alias "Diane Friedman" DinkyDiane@example.com
+note "Diane Friedman" <name:Diane Friedman>
+alias "Peggy Edwards" PeggyW@example.com
+note "Peggy Edwards" <name:Peggy Edwards>
+alias "David Mallinak" Matchlck@example.com
+note "David Mallinak" <name:David Mallinak>
+alias "Kathleen Norvell" Appin1@example.com
+note "Kathleen Norvell" <name:Kathleen Norvell>
+alias "Linda Wolfe" WolfeLinda@example.com
+note "Linda Wolfe" <name:Linda Wolfe>
+alias "Theresa Abell" TAAbell@aol.com
+note "Theresa Abell" <name:Theresa Abell>
+alias "Karen Grycewicz" Grycewicz@example.com
+note "Karen Grycewicz" <name:Karen Grycewicz>
+alias "Kathy Wooldridge" KWoold@widomaker.com
+note "Kathy Wooldridge" <name:Kathy Wooldridge>
+alias "Paul Koehler" wznwhail@example.com
+note "Paul Koehler" <name:Paul Koehler>
+alias "Lori Fraind" LoriFraind@example.com
+note "Lori Fraind" <name:Lori Fraind>
+alias "Tabitha Barr" TBarr@example.com
+note "Tabitha Barr" <name:Tabitha Barr>
+alias "Gordon Daiger" Gordon Daiger <daiger@example.com>
+note "Gordon Daiger" <name:Gordon Daiger>
+alias "Virginia Jenkins" VirginiaJenkins@example.com
+note "Virginia Jenkins" <name:Gina Jenkins>
diff --git a/kaddressbook/xxport/samples/netscape.ldif b/kaddressbook/xxport/samples/netscape.ldif
new file mode 100644
index 000000000..85f090079
--- /dev/null
+++ b/kaddressbook/xxport/samples/netscape.ldif
@@ -0,0 +1,38 @@
+dn: cn=John Smith,mail=john@smilt.com
+modifytimestamp: 20030219222547Z
+cn: John Smith
+xmozillanickname: JS
+mail: john@smilt.com
+xmozillausehtmlmail: FALSE
+o: Beer
+locality: Peckham
+givenname: John
+sn: Smith
+st: London
+description:: Tm9uZSByZWFsbHkKQW5vdGhlciBsaW5lIQ==
+title: Mr
+streetaddress: 1 Some Street
+postalcode: ABC 123
+countryname: England
+telephonenumber: 020 8888 2232
+homephone: 020 8888 1234
+facsimiletelephonenumber: 020 7777 1234
+xmozillauseconferenceserver: 0
+ou: Brewing
+cellphone: 07752 123 456
+homeurl: www.johnsmith.com
+xmozillaanyphone: 020 8888 2232
+objectclass: top
+objectclass: person
+
+# this is a comment
+dn: cn=KDE,mail=kde@kde.org
+modifytimestamp: 20030219222638Z
+cn: KDE
+mail: kde@kde.org
+xmozillausehtmlmail: FALSE
+givenname: KDE
+xmozillauseconferenceserver: 0
+objectclass: top
+objectclass: person
+
diff --git a/kaddressbook/xxport/samples/rfc2849.txt b/kaddressbook/xxport/samples/rfc2849.txt
new file mode 100644
index 000000000..040022d86
--- /dev/null
+++ b/kaddressbook/xxport/samples/rfc2849.txt
@@ -0,0 +1 @@
+http://www.rfc-editor.org/rfc/rfc2849.txt
diff --git a/kaddressbook/xxport/vcard_xxport.cpp b/kaddressbook/xxport/vcard_xxport.cpp
new file mode 100644
index 000000000..9fb368278
--- /dev/null
+++ b/kaddressbook/xxport/vcard_xxport.cpp
@@ -0,0 +1,537 @@
+/*
+ This file is part of KAddressbook.
+ Copyright (c) 2003 Tobias Koenig <tokoe@kde.org>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ 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 Qt, and distribute the resulting executable,
+ without including the source code for Qt in the source distribution.
+*/
+
+#include <qcheckbox.h>
+#include <qfile.h>
+#include <qfont.h>
+#include <qlabel.h>
+#include <qlayout.h>
+#include <qpushbutton.h>
+
+#include <kabc/vcardconverter.h>
+#include <kdialogbase.h>
+#include <kfiledialog.h>
+#include <kio/netaccess.h>
+#include <klocale.h>
+#include <kmessagebox.h>
+#include <ktempfile.h>
+#include <kurl.h>
+#include <kapplication.h>
+#include <libkdepim/addresseeview.h>
+
+#include "config.h" // ??
+
+#include "gpgmepp/context.h"
+#include "gpgmepp/data.h"
+#include "gpgmepp/key.h"
+#include "qgpgme/dataprovider.h"
+
+#include "xxportmanager.h"
+
+#include "vcard_xxport.h"
+
+K_EXPORT_KADDRESSBOOK_XXFILTER( libkaddrbk_vcard_xxport, VCardXXPort )
+
+class VCardViewerDialog : public KDialogBase
+{
+ public:
+ VCardViewerDialog( const KABC::Addressee::List &list,
+ QWidget *parent, const char *name = 0 );
+
+ KABC::Addressee::List contacts() const;
+
+ protected:
+ void slotUser1();
+ void slotUser2();
+ void slotApply();
+ void slotCancel();
+
+ private:
+ void updateView();
+
+ KPIM::AddresseeView *mView;
+
+ KABC::Addressee::List mContacts;
+ KABC::Addressee::List::Iterator mIt;
+};
+
+class VCardExportSelectionDialog : public KDialogBase
+{
+ public:
+ VCardExportSelectionDialog( QWidget *parent, const char *name = 0 );
+ ~VCardExportSelectionDialog();
+
+ bool exportPrivateFields() const;
+ bool exportBusinessFields() const;
+ bool exportOtherFields() const;
+ bool exportEncryptionKeys() const;
+
+ private:
+ QCheckBox *mPrivateBox;
+ QCheckBox *mBusinessBox;
+ QCheckBox *mOtherBox;
+ QCheckBox *mEncryptionKeys;
+};
+
+VCardXXPort::VCardXXPort( KABC::AddressBook *ab, QWidget *parent, const char *name )
+ : KAB::XXPort( ab, parent, name )
+{
+ createImportAction( i18n( "Import vCard..." ) );
+ createExportAction( i18n( "Export vCard 2.1..." ), "v21" );
+ createExportAction( i18n( "Export vCard 3.0..." ), "v30" );
+}
+
+bool VCardXXPort::exportContacts( const KABC::AddresseeList &addrList, const QString &data )
+{
+ KABC::VCardConverter converter;
+ KURL url;
+ KABC::AddresseeList list;
+
+ list = filterContacts( addrList );
+
+ bool ok = true;
+ if ( list.isEmpty() ) {
+ return ok;
+ } else if ( list.count() == 1 ) {
+ url = KFileDialog::getSaveURL( list[ 0 ].givenName() + "_" + list[ 0 ].familyName() + ".vcf" );
+ if ( url.isEmpty() )
+ return true;
+
+ if ( data == "v21" )
+ ok = doExport( url, converter.createVCards( list, KABC::VCardConverter::v2_1 ) );
+ else
+ ok = doExport( url, converter.createVCards( list, KABC::VCardConverter::v3_0 ) );
+ } else {
+ QString msg = i18n( "You have selected a list of contacts, shall they be "
+ "exported to several files?" );
+
+ switch ( KMessageBox::questionYesNo( parentWidget(), msg, QString::null, i18n("Export to Several Files"), i18n("Export to One File") ) ) {
+ case KMessageBox::Yes: {
+ KURL baseUrl = KFileDialog::getExistingURL();
+ if ( baseUrl.isEmpty() )
+ return true;
+
+ KABC::AddresseeList::ConstIterator it;
+ uint counter = 0;
+ for ( it = list.begin(); it != list.end(); ++it ) {
+ QString testUrl;
+ if ( (*it).givenName().isEmpty() && (*it).familyName().isEmpty() )
+ testUrl = baseUrl.url() + "/" + (*it).organization();
+ else
+ testUrl = baseUrl.url() + "/" + (*it).givenName() + "_" + (*it).familyName();
+
+ if ( KIO::NetAccess::exists( testUrl + (counter == 0 ? "" : QString::number( counter )) + ".vcf", false, parentWidget() ) ) {
+ counter++;
+ url = testUrl + QString::number( counter ) + ".vcf";
+ } else
+ url = testUrl + ".vcf";
+
+ bool tmpOk;
+ KABC::AddresseeList tmpList;
+ tmpList.append( *it );
+
+ if ( data == "v21" )
+ tmpOk = doExport( url, converter.createVCards( tmpList, KABC::VCardConverter::v2_1 ) );
+ else
+ tmpOk = doExport( url, converter.createVCards( tmpList, KABC::VCardConverter::v3_0 ) );
+
+ ok = ok && tmpOk;
+ }
+ break;
+ }
+ case KMessageBox::No:
+ default: {
+ url = KFileDialog::getSaveURL( "addressbook.vcf" );
+ if ( url.isEmpty() )
+ return true;
+
+ if ( data == "v21" )
+ ok = doExport( url, converter.createVCards( list, KABC::VCardConverter::v2_1 ) );
+ else
+ ok = doExport( url, converter.createVCards( list, KABC::VCardConverter::v3_0 ) );
+ }
+ }
+ }
+
+ return ok;
+}
+
+KABC::AddresseeList VCardXXPort::importContacts( const QString& ) const
+{
+ QString fileName;
+ KABC::AddresseeList addrList;
+ KURL::List urls;
+
+ if ( !XXPortManager::importData.isEmpty() )
+ addrList = parseVCard( XXPortManager::importData );
+ else {
+ if ( XXPortManager::importURL.isEmpty() )
+ urls = KFileDialog::getOpenURLs( QString::null, "*.vcf|vCards", parentWidget(),
+ i18n( "Select vCard to Import" ) );
+ else
+ urls.append( XXPortManager::importURL );
+
+ if ( urls.count() == 0 )
+ return addrList;
+
+ QString caption( i18n( "vCard Import Failed" ) );
+ bool anyFailures = false;
+ KURL::List::Iterator it;
+ for ( it = urls.begin(); it != urls.end(); ++it ) {
+ if ( KIO::NetAccess::download( *it, fileName, parentWidget() ) ) {
+
+ QFile file( fileName );
+
+ if ( file.open( IO_ReadOnly ) ) {
+ QByteArray rawData = file.readAll();
+ file.close();
+ if ( rawData.size() > 0 )
+ addrList += parseVCard( rawData );
+
+ KIO::NetAccess::removeTempFile( fileName );
+ } else {
+ QString text = i18n( "<qt>When trying to read the vCard, there was an error opening the file '%1': %2</qt>" );
+ text = text.arg( (*it).url() );
+ text = text.arg( kapp->translate( "QFile",
+ file.errorString().latin1() ) );
+ KMessageBox::error( parentWidget(), text, caption );
+ anyFailures = true;
+ }
+ } else {
+ QString text = i18n( "<qt>Unable to access vCard: %1</qt>" );
+ text = text.arg( KIO::NetAccess::lastErrorString() );
+ KMessageBox::error( parentWidget(), text, caption );
+ anyFailures = true;
+ }
+ }
+
+ if ( !XXPortManager::importURL.isEmpty() ) { // a vcard was passed via cmd
+ if ( addrList.isEmpty() ) {
+ if ( anyFailures && urls.count() > 1 )
+ KMessageBox::information( parentWidget(),
+ i18n( "No contacts were imported, due to errors with the vCards." ) );
+ else if ( !anyFailures )
+ KMessageBox::information( parentWidget(), i18n( "The vCard does not contain any contacts." ) );
+ } else {
+ VCardViewerDialog dlg( addrList, parentWidget() );
+ dlg.exec();
+ addrList = dlg.contacts();
+ }
+ }
+ }
+
+ return addrList;
+}
+
+KABC::AddresseeList VCardXXPort::parseVCard( const QString &data ) const
+{
+ KABC::VCardConverter converter;
+
+ return converter.parseVCards( data );
+}
+
+bool VCardXXPort::doExport( const KURL &url, const QString &data )
+{
+ KTempFile tmpFile;
+ tmpFile.setAutoDelete( true );
+
+ QTextStream stream( tmpFile.file() );
+ stream.setEncoding( QTextStream::UnicodeUTF8 );
+
+ stream << data;
+ tmpFile.close();
+
+ return KIO::NetAccess::upload( tmpFile.name(), url, parentWidget() );
+}
+
+KABC::AddresseeList VCardXXPort::filterContacts( const KABC::AddresseeList &addrList )
+{
+ KABC::AddresseeList list;
+
+ if ( addrList.isEmpty() )
+ return addrList;
+
+ VCardExportSelectionDialog dlg( parentWidget() );
+ if ( !dlg.exec() )
+ return list;
+
+ KABC::AddresseeList::ConstIterator it;
+ for ( it = addrList.begin(); it != addrList.end(); ++it ) {
+ KABC::Addressee addr;
+
+ addr.setUid( (*it).uid() );
+ addr.setFormattedName( (*it).formattedName() );
+ addr.setPrefix( (*it).prefix() );
+ addr.setGivenName( (*it).givenName() );
+ addr.setAdditionalName( (*it).additionalName() );
+ addr.setFamilyName( (*it).familyName() );
+ addr.setSuffix( (*it).suffix() );
+ addr.setNickName( (*it).nickName() );
+ addr.setMailer( (*it).mailer() );
+ addr.setTimeZone( (*it).timeZone() );
+ addr.setGeo( (*it).geo() );
+ addr.setProductId( (*it).productId() );
+ addr.setSortString( (*it).sortString() );
+ addr.setUrl( (*it).url() );
+ addr.setSecrecy( (*it).secrecy() );
+ addr.setSound( (*it).sound() );
+ addr.setEmails( (*it).emails() );
+ addr.setCategories( (*it).categories() );
+
+ if ( dlg.exportPrivateFields() ) {
+ addr.setBirthday( (*it).birthday() );
+ addr.setNote( (*it).note() );
+ addr.setPhoto( (*it).photo() );
+ }
+
+ if ( dlg.exportBusinessFields() ) {
+ addr.setTitle( (*it).title() );
+ addr.setRole( (*it).role() );
+ addr.setOrganization( (*it).organization() );
+
+ addr.setLogo( (*it).logo() );
+
+ KABC::PhoneNumber::List phones = (*it).phoneNumbers( KABC::PhoneNumber::Work );
+ KABC::PhoneNumber::List::Iterator phoneIt;
+ for ( phoneIt = phones.begin(); phoneIt != phones.end(); ++phoneIt )
+ addr.insertPhoneNumber( *phoneIt );
+
+ KABC::Address::List addresses = (*it).addresses( KABC::Address::Work );
+ KABC::Address::List::Iterator addrIt;
+ for ( addrIt = addresses.begin(); addrIt != addresses.end(); ++addrIt )
+ addr.insertAddress( *addrIt );
+ }
+
+ KABC::PhoneNumber::List phones = (*it).phoneNumbers();
+ KABC::PhoneNumber::List::Iterator phoneIt;
+ for ( phoneIt = phones.begin(); phoneIt != phones.end(); ++phoneIt ) {
+ int type = (*phoneIt).type();
+
+ if ( type & KABC::PhoneNumber::Home && dlg.exportPrivateFields() )
+ addr.insertPhoneNumber( *phoneIt );
+ else if ( type & KABC::PhoneNumber::Work && dlg.exportBusinessFields() )
+ addr.insertPhoneNumber( *phoneIt );
+ else if ( dlg.exportOtherFields() )
+ addr.insertPhoneNumber( *phoneIt );
+ }
+
+ KABC::Address::List addresses = (*it).addresses();
+ KABC::Address::List::Iterator addrIt;
+ for ( addrIt = addresses.begin(); addrIt != addresses.end(); ++addrIt ) {
+ int type = (*addrIt).type();
+
+ if ( type & KABC::Address::Home && dlg.exportPrivateFields() )
+ addr.insertAddress( *addrIt );
+ else if ( type & KABC::Address::Work && dlg.exportBusinessFields() )
+ addr.insertAddress( *addrIt );
+ else if ( dlg.exportOtherFields() )
+ addr.insertAddress( *addrIt );
+ }
+
+ if ( dlg.exportOtherFields() )
+ addr.setCustoms( (*it).customs() );
+
+ if ( dlg.exportEncryptionKeys() ) {
+ addKey( addr, KABC::Key::PGP );
+ addKey( addr, KABC::Key::X509 );
+ }
+
+ list.append( addr );
+ }
+
+ return list;
+}
+
+void VCardXXPort::addKey( KABC::Addressee &addr, KABC::Key::Types type )
+{
+ QString fingerprint = addr.custom( "KADDRESSBOOK",
+ (type == KABC::Key::PGP ? "OPENPGPFP" : "SMIMEFP") );
+ if ( fingerprint.isEmpty() )
+ return;
+
+ GpgME::Context * context = GpgME::Context::createForProtocol( GpgME::Context::OpenPGP );
+ if ( !context ) {
+ kdError() << "No context available" << endl;
+ return;
+ }
+
+ context->setArmor( false );
+ context->setTextMode( false );
+
+ QGpgME::QByteArrayDataProvider dataProvider;
+ GpgME::Data dataObj( &dataProvider );
+ GpgME::Error error = context->exportPublicKeys( fingerprint.latin1(), dataObj );
+ delete context;
+
+ if ( error ) {
+ kdError() << error.asString() << endl;
+ return;
+ }
+
+ KABC::Key key;
+ key.setType( type );
+ key.setBinaryData( dataProvider.data() );
+
+ addr.insertKey( key );
+}
+
+// ---------- VCardViewer Dialog ---------------- //
+
+VCardViewerDialog::VCardViewerDialog( const KABC::Addressee::List &list,
+ QWidget *parent, const char *name )
+ : KDialogBase( Plain, i18n( "Import vCard" ), Yes | No | Apply | Cancel, Yes,
+ parent, name, true, true, KStdGuiItem::no(), KStdGuiItem::yes() ),
+ mContacts( list )
+{
+ QFrame *page = plainPage();
+ QVBoxLayout *layout = new QVBoxLayout( page, marginHint(), spacingHint() );
+
+ QLabel *label = new QLabel( i18n( "Do you want to import this contact in your address book?" ), page );
+ QFont font = label->font();
+ font.setBold( true );
+ label->setFont( font );
+ layout->addWidget( label );
+
+ mView = new KPIM::AddresseeView( page );
+ mView->enableLinks( 0 );
+ mView->setVScrollBarMode( QScrollView::Auto );
+ layout->addWidget( mView );
+
+ setButtonText( Apply, i18n( "Import All..." ) );
+
+ mIt = mContacts.begin();
+
+ updateView();
+}
+
+KABC::Addressee::List VCardViewerDialog::contacts() const
+{
+ return mContacts;
+}
+
+void VCardViewerDialog::updateView()
+{
+ mView->setAddressee( *mIt );
+
+ KABC::Addressee::List::Iterator it = mIt;
+ actionButton( Apply )->setEnabled( (++it) != mContacts.end() );
+}
+
+void VCardViewerDialog::slotUser1()
+{
+ mIt = mContacts.remove( mIt );
+
+ if ( mIt == mContacts.end() )
+ slotApply();
+
+ updateView();
+}
+
+void VCardViewerDialog::slotUser2()
+{
+ mIt++;
+
+ if ( mIt == mContacts.end() )
+ slotApply();
+
+ updateView();
+}
+
+void VCardViewerDialog::slotApply()
+{
+ QDialog::accept();
+}
+
+void VCardViewerDialog::slotCancel()
+{
+ mContacts.clear();
+ QDialog::accept();
+}
+
+// ---------- VCardExportSelection Dialog ---------------- //
+
+VCardExportSelectionDialog::VCardExportSelectionDialog( QWidget *parent,
+ const char *name )
+ : KDialogBase( Plain, i18n( "Select vCard Fields" ), Ok | Cancel, Ok,
+ parent, name, true, true )
+{
+ QFrame *page = plainPage();
+
+ QVBoxLayout *layout = new QVBoxLayout( page, marginHint(), spacingHint() );
+
+ QLabel *label = new QLabel( i18n( "Select the fields which shall be exported in the vCard." ), page );
+ layout->addWidget( label );
+
+ mPrivateBox = new QCheckBox( i18n( "Private fields" ), page );
+ layout->addWidget( mPrivateBox );
+
+ mBusinessBox = new QCheckBox( i18n( "Business fields" ), page );
+ layout->addWidget( mBusinessBox );
+
+ mOtherBox = new QCheckBox( i18n( "Other fields" ), page );
+ layout->addWidget( mOtherBox );
+
+ mEncryptionKeys = new QCheckBox( i18n( "Encryption keys" ), page );
+ layout->addWidget( mEncryptionKeys );
+
+ KConfig config( "kaddressbookrc" );
+ config.setGroup( "XXPortVCard" );
+
+ mPrivateBox->setChecked( config.readBoolEntry( "ExportPrivateFields", true ) );
+ mBusinessBox->setChecked( config.readBoolEntry( "ExportBusinessFields", false ) );
+ mOtherBox->setChecked( config.readBoolEntry( "ExportOtherFields", false ) );
+ mEncryptionKeys->setChecked( config.readBoolEntry( "ExportEncryptionKeys", false ) );
+}
+
+VCardExportSelectionDialog::~VCardExportSelectionDialog()
+{
+ KConfig config( "kaddressbookrc" );
+ config.setGroup( "XXPortVCard" );
+
+ config.writeEntry( "ExportPrivateFields", mPrivateBox->isChecked() );
+ config.writeEntry( "ExportBusinessFields", mBusinessBox->isChecked() );
+ config.writeEntry( "ExportOtherFields", mOtherBox->isChecked() );
+ config.writeEntry( "ExportEncryptionKeys", mEncryptionKeys->isChecked() );
+}
+
+bool VCardExportSelectionDialog::exportPrivateFields() const
+{
+ return mPrivateBox->isChecked();
+}
+
+bool VCardExportSelectionDialog::exportBusinessFields() const
+{
+ return mBusinessBox->isChecked();
+}
+
+bool VCardExportSelectionDialog::exportOtherFields() const
+{
+ return mOtherBox->isChecked();
+}
+
+bool VCardExportSelectionDialog::exportEncryptionKeys() const
+{
+ return mEncryptionKeys->isChecked();
+}
+
+#include "vcard_xxport.moc"
diff --git a/kaddressbook/xxport/vcard_xxport.desktop b/kaddressbook/xxport/vcard_xxport.desktop
new file mode 100644
index 000000000..d0a0146a2
--- /dev/null
+++ b/kaddressbook/xxport/vcard_xxport.desktop
@@ -0,0 +1,105 @@
+[Desktop Entry]
+X-KDE-Library=libkaddrbk_vcard_xxport
+Name=KAB vCard XXPort Plugin
+Name[af]=KAB vCard XXPort inprop module
+Name[be]=Дапаўненне KAB "Імпарт/Экспарт vCard"
+Name[bg]=Приставка за vCard XXPort на KAB
+Name[br]=Lugent KAB vCard XXPort
+Name[bs]=KAB dodatak za vCard XXPort
+Name[ca]=Endollable d'importació/exportació vCard per al KAB
+Name[cs]=Exportní modul vCard
+Name[cy]=Ategyn XXPort vCard KAB
+Name[da]=KAB vCard XXPort-plugin
+Name[de]=vCard-XXPort-Modul für Adressbuch
+Name[el]=Πρόσθετο εισαγωγής/εξαγωγής vCard του KAB
+Name[es]=Plugin KAB para {im,ex}portar vCard
+Name[et]=KAB vCardi eksport/importplugin
+Name[eu]=KAB-en vCard in/esportazio plugin-a
+Name[fa]=وصلۀ KAB vCard XXPort
+Name[fi]=KAB vCard liitännäinen
+Name[fr]=Module d'import / export vCard pour KAB
+Name[fy]=KAB vCard XXPort-plugin
+Name[gl]=Extensión XXPort de vCard para KAB
+Name[he]=תוסף ייבוא/ייצוא עבור vCard של KAB
+Name[hi]=केएबी वी-कार्डXXपोर्ट प्लगइन
+Name[hu]=KAB vCard XXPort bővítőmodul
+Name[is]=Íforrit fyrir KAB vCard XXPort
+Name[ja]=KAB vCazrd インポート/エクスポートプラグイン
+Name[ka]=KAB vCard ექსპორტის მოდული
+Name[kk]=vCard-ты экспорт/импорт ету
+Name[km]=កម្មវិធី​ជំនួយ KAB vCard XXPort
+Name[lt]=KAB vCard XXPort priedas
+Name[ms]=Plugin KAB vCard XXPort
+Name[nb]=KAB-programtillegg for vCard
+Name[nds]=vCard-Im-/Exportmoduul för KAdressbook
+Name[ne]=KAB भी कार्ड XXPort प्लगइन
+Name[nl]=KAB vCard XXPort-plugin
+Name[nn]=KAB vCard XXPort programtillegg
+Name[pl]=Wtyczka KAB do importu/eksportu z/do formatu vCard
+Name[pt]='Plugin' XXPort para vCard do KAB
+Name[pt_BR]=Plug-in de Im/Exportação de vCard do KAB
+Name[ru]=Работа с vCard
+Name[sk]=KAB modul pre xxport z vCard
+Name[sl]=Vstavek KAB vCard XXPort
+Name[sr]=XXPort прикључак KAB-а за vCard
+Name[sr@Latn]=XXPort priključak KAB-a za vCard
+Name[sv]=Adressbokens vCard-överföringsinsticksprogram
+Name[ta]=kab vஅட்டைxxபோர்ட் சொருகுப்பொருள்
+Name[tg]=Кор бо vCard
+Name[tr]=KAB vCard XXPort Eklentisi
+Name[uk]=Втулок KAB для обміну через vCard
+Name[zh_CN]=KAB vCard XXPort 插件
+Name[zh_TW]=KAB vCard XXPort 外掛程式
+Comment=Plugin to import and export contacts in vCard format
+Comment[af]=Inprop module wat kontakte in vCard formaat invoer en uitvoer
+Comment[be]=Дапаўненне для імпарту і экспарту кантактаў у фармаце vCard
+Comment[bg]=Приставка за експортиране/импортиране на контактите във формат на vCard
+Comment[bs]=Dodatak za uvoz i izvoz kontakata u vCard formatu
+Comment[ca]=Endollable per a importar i exportar contactes en el format vCard
+Comment[cs]=Modul pro import a export kontaktů ve formátu vCard
+Comment[cy]=Ategyn i fewnforio ac allforio cysylltau yn fformat vCard
+Comment[da]=Plugin til at importere og eksportere kontakter i vCard-format
+Comment[de]=Modul für Import/Export von Kontakten im vCard-Format
+Comment[el]=Πρόσθετο για εισαγωγή και εξαγωγή επαφών μορφής vCard
+Comment[es]=Plugin para importar y exportar contactos en formato vCard
+Comment[et]=Plugin kontaktide importimiseks ja eksportimiseks vCardi vormingus
+Comment[eu]=vCard formatuko kontaktuak in/esportatzeko plugin-a
+Comment[fa]=وصله برای واردات و صادرات تماسها در قالب vCard
+Comment[fi]=Liitännäinen vCard-muodossa olevien kontaktien tuontiin ja vientiin
+Comment[fr]=Module d'import / export de contacts au format vCard
+Comment[fy]=Plugin foar it ymportearjen fan kontaktpersoanen yn vCard-formaat
+Comment[gl]=Plugin para importar e exportar contactos en formato vCard
+Comment[hi]=सम्पर्कों को वी-कार्ड फार्मेट में आयात और निर्यात करने का प्लगइन
+Comment[hu]=Bővítőmodul vCard névjegyek importálásához/exportálásához
+Comment[is]=Íforrit til að flytja inn eða út tengiliði í vCard sniði
+Comment[it]=Plugin per importare ed esportare contatti in formato vCard
+Comment[ja]=vCard フォーマットで連絡先をインポート/エクスポートするプラグイン
+Comment[ka]=კონტაქტების vCard-ის ფორმატით იმპორტ/ექსპორტის მოდული
+Comment[kk]=vCard пішіміне экспорт/импорт ету модулі
+Comment[km]=កម្មវិធី​ជំនួយ​ដើម្បី​នាំចូល និង​នាំចេញ​ទំនាក់ទំនង​ក្នុង​ទ្រង់ទ្រាយ​ជា vCard
+Comment[lt]=Įskiepis kontaktų importavimui ir eksportavimui vCard formatu
+Comment[mk]=Приклучок за внесување и изнесување контакти во vCard-формат
+Comment[ms]=Plugin untuk mengimpot dan mengekspot orang hubungan dalam format vCard
+Comment[nb]=Programtillegg for import og eksport av kontakter i vCard-format
+Comment[nds]=Moduul för't Im-/Exporteren vun Kontakten in't vCard-Formaat
+Comment[ne]=भी कार्ड ढाँचामा आयात र निर्यात गर्न प्लगइन गर्नुहोस्
+Comment[nl]=Plugin voor het importeren en exporteren van contactpersonen in vCard-formaat
+Comment[nn]=Programtillegg for å importera og eksportera kontaktar i vCard-format
+Comment[pl]=Wtyczka do importu i eksportu wizytówek w formacie vCard
+Comment[pt]=Um 'plugin' para importar e exportar os contactos no formato vCard
+Comment[pt_BR]=Plug-in para importar e exportar contatos no formato vCard
+Comment[ru]=Импорта и экспорт контактов в формате vCard
+Comment[sk]=Plugin pre import a export kontaktov v vCard formáte
+Comment[sl]=Vstavek za uvoz in izvoz stikov v obliki vCard
+Comment[sr]=Прикључак за увоз и извоз контаката у vCard формат
+Comment[sr@Latn]=Priključak za uvoz i izvoz kontakata u vCard format
+Comment[sv]=Insticksprogram för import och export av kontakter med vCard-format
+Comment[ta]=ஏற்றுமதி மற்றும் இறக்குமதி தொடர்புகளை vஅட்டை வடிவமைப்பில் செலுத்த சொருகுப்பொருள்
+Comment[tg]=Модул барои воридот ва содироти алоқот ба формати vCard
+Comment[tr]=vCard biçimi bağlantıları alma ve gönderme eklentisi
+Comment[uk]=Втулок для імпорту та експорту контактів у форматі vCard
+Comment[zh_CN]=导入和导出 vCard 格式联系人的插件
+Comment[zh_TW]=匯入與匯出 vCard 格式聯絡人的外掛程式
+Type=Service
+ServiceTypes=KAddressBook/XXPort
+X-KDE-KAddressBook-XXPortPluginVersion=1
diff --git a/kaddressbook/xxport/vcard_xxport.h b/kaddressbook/xxport/vcard_xxport.h
new file mode 100644
index 000000000..d67aaeffe
--- /dev/null
+++ b/kaddressbook/xxport/vcard_xxport.h
@@ -0,0 +1,50 @@
+/*
+ This file is part of KAddressbook.
+ Copyright (c) 2003 Tobias Koenig <tokoe@kde.org>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ 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 Qt, and distribute the resulting executable,
+ without including the source code for Qt in the source distribution.
+*/
+
+#ifndef VCARD_XXPORT_H
+#define VCARD_XXPORT_H
+
+#include <xxport.h>
+
+class VCardXXPort : public KAB::XXPort
+{
+ Q_OBJECT
+
+ public:
+ VCardXXPort( KABC::AddressBook *ab, QWidget *parent, const char *name = 0 );
+
+ QString identifier() const { return "vcard"; }
+
+ public slots:
+ bool exportContacts( const KABC::AddresseeList &list, const QString &data );
+ KABC::AddresseeList importContacts( const QString &data ) const;
+
+ private:
+ KABC::AddresseeList parseVCard( const QString &data ) const;
+ bool doExport( const KURL &url, const QString &data );
+ void addKey( KABC::Addressee &addr, KABC::Key::Types type );
+
+ KABC::AddresseeList filterContacts( const KABC::AddresseeList& );
+};
+
+#endif
diff --git a/kaddressbook/xxport/vcard_xxportui.rc b/kaddressbook/xxport/vcard_xxportui.rc
new file mode 100644
index 000000000..2c748af87
--- /dev/null
+++ b/kaddressbook/xxport/vcard_xxportui.rc
@@ -0,0 +1,15 @@
+<?xml version="1.0"?>
+<!DOCTYPE gui>
+<gui name="vcard_xxport" version="1">
+<MenuBar>
+ <Menu name="file"><text>&amp;File</text>
+ <Menu name="file_import"><text>&amp;Import</text>
+ <Action name="file_import_vcard"/>
+ </Menu>
+ <Menu name="file_export"><text>&amp;Export</text>
+ <Action name="file_export_vcard_v21"/>
+ <Action name="file_export_vcard_v30"/>
+ </Menu>
+ </Menu>
+</MenuBar>
+</gui>