diff options
author | toma <toma@283d02a7-25f6-0310-bc7c-ecb5cbfe19da> | 2009-11-25 17:56:58 +0000 |
---|---|---|
committer | toma <toma@283d02a7-25f6-0310-bc7c-ecb5cbfe19da> | 2009-11-25 17:56:58 +0000 |
commit | 460c52653ab0dcca6f19a4f492ed2c5e4e963ab0 (patch) | |
tree | 67208f7c145782a7e90b123b982ca78d88cc2c87 /kaddressbook | |
download | tdepim-460c52653ab0dcca6f19a4f492ed2c5e4e963ab0.tar.gz tdepim-460c52653ab0dcca6f19a4f492ed2c5e4e963ab0.zip |
Copy the KDE 3.5 branch to branches/trinity for new KDE 3.5 features.
BUG:215923
git-svn-id: svn://anonsvn.kde.org/home/kde/branches/trinity/kdepim@1054174 283d02a7-25f6-0310-bc7c-ecb5cbfe19da
Diffstat (limited to 'kaddressbook')
315 files changed, 43792 insertions, 0 deletions
diff --git a/kaddressbook/HACKING b/kaddressbook/HACKING new file mode 100644 index 000000000..b5714e390 --- /dev/null +++ b/kaddressbook/HACKING @@ -0,0 +1,100 @@ +Coding Style +============ + +See http://korganizer.kde.org/develop/hacking.html for an HTML version. + +Formatting +---------- + +- No Tabs. +- Indent with 2 spaces. +- A line must not have more than 80 chars. +- Put Spaces between brackets and arguments of functions. +- For if, else, while and similar statements put the brackets on the same line + as the statement. +- Function and class definitions have their brackets on separate lines. + +Example: + +void MyClass::myFunction() +{ + if ( blah == fasel ) { + blubbVariable = arglValue; + } else { + blubbVariable = oerxValue; + } +} + + +Header Formatting +----------------- + +- General formatting rules apply. +- Access modifiers are indented. +- Put curly brackets of class definition on its own line. +- Double inclusion protection defines are all upper case letters and are + composed of the namespace (if available), the classname and a H suffix + separated by underscores. +- Inside a namespace there is no indentation. + +Example: + +#ifndef XKJ_MYCLASS_H +#define XKJ_MYCLASS_H + +namespace XKJ { + +class MyClass +{ + public: + MyClass(); + + private: + int mMyInt; +}; + +} + +#endif + + +API docs +-------- + +- Each public function must have a Doxygen compatible comment in the header +- Use C-style comments without additional asterisks +- Indent correctly. +- Comments should be grammatically correct, e.g. sentences start with uppercase + letters and end with a full stop. +- Be concise. + +Example: + + /** + This function makes tea. + + @param cups number of cups. + @result tea + */ + Tea makeTea( int cups ); + + +Class and File Names +-------------------- + +- Put classes in files, which have the same name as the class, but only + lower-case letters. +- Designer-generated files should have a name classname_base.ui and shoul + contain a class called ClassnameBase. +- Classes inheriting from designer-generated classes have the same name as the + generated class, but without the Base suffix. + +Class and Variable Names +------------------------ + +- For class, variable, function names seperate multiple words by upper-casing + the words precedeed by other words. +- Class names start with an upper-case letter. +- Function names start with a lower-case letter. +- Variable names start with a lower-case letter. +- Member variables of a class start with "m" followed by an upper-case letter. diff --git a/kaddressbook/Makefile.am b/kaddressbook/Makefile.am new file mode 100644 index 000000000..fe39a1084 --- /dev/null +++ b/kaddressbook/Makefile.am @@ -0,0 +1,96 @@ +SUBDIRS = interfaces common printing editors . views features xxport kcmconfigs pics csv-templates \ + thumbnailcreator +SRCDOC_DEST = $(kde_htmldir)/en/kaddressbook + + +INCLUDES= -I$(top_srcdir)/kaddressbook/interfaces \ + -I$(top_srcdir)/kaddressbook/features \ + -I$(top_srcdir)/kaddressbook/views \ + -I$(top_srcdir)/kaddressbook/printing \ + -I$(top_srcdir)/kaddressbook/common \ + -I$(top_srcdir)/kaddressbook/editors \ + -I$(top_builddir)/kaddressbook/common \ + -I$(top_srcdir) \ + -I$(top_buildir)/kaddressbook/editors \ + $(all_includes) + +bin_PROGRAMS = kaddressbook + +kaddressbook_SOURCES = main.cpp kaddressbookmain.cpp +kaddressbook_LDFLAGS = $(all_libraries) $(KDE_RPATH) +kaddressbook_LDADD = libkaddressbook.la + +kde_module_LTLIBRARIES = libkaddressbookpart.la + +libkaddressbookpart_la_SOURCES = kaddressbook_part.cpp +libkaddressbookpart_la_LDFLAGS = -module $(KDE_PLUGIN) $(KDE_RPATH) $(all_libraries) -no-undefined +libkaddressbookpart_la_LIBADD = libkaddressbook.la + +lib_LTLIBRARIES = libkaddressbook.la +libkaddressbook_la_SOURCES = addresseeconfig.cpp addresseeeditordialog.cpp \ + addresseeeditorwidget.cpp addresseeeditorbase.cpp addresseeeditorextension.cpp addresseeutil.cpp addresseditwidget.cpp \ + addviewdialog.cpp emaileditwidget.cpp extensionmanager.cpp \ + filtereditdialog.cpp filterselectionwidget.cpp geowidget.cpp \ + imagewidget.cpp incsearchwidget.cpp jumpbuttonbar.cpp kabcore.cpp kablock.cpp \ + kaddressbookiface.skel kaddressbookservice.cpp \ + kaddressbookview.cpp keywidget.cpp ldapsearchdialog.cpp nameeditdialog.cpp \ + phoneeditwidget.cpp secrecywidget.cpp soundwidget.cpp \ + viewconfigurefieldspage.cpp viewconfigurefilterpage.cpp \ + viewconfigurewidget.cpp undocmds.cpp viewmanager.cpp \ + xxportmanager.cpp xxportselectdialog.cpp contacteditorwidgetmanager.cpp \ + simpleaddresseeeditor.cpp advancedcustomfields.cpp customfieldswidget.cpp \ + freebusywidget.cpp searchmanager.cpp imeditwidget.cpp kabtools.cpp distributionlistpicker.cpp distributionlisteditor.cpp distributionlistentryview.cpp +libkaddressbook_la_LDFLAGS = $(all_libraries) $(KDE_RPATH) -no-undefined +libkaddressbook_la_LIBADD = $(top_builddir)/kaddressbook/printing/libprinter.la \ + $(top_builddir)/kaddressbook/interfaces/libkabinterfaces.la \ + $(top_builddir)/libkdepim/libkdepim.la \ + $(top_builddir)/libkcal/libkcal.la \ + -lkabc_file $(LIB_KABC) $(LIB_KHTML) \ + $(top_builddir)/kaddressbook/common/libkabcommon.la \ + $(top_builddir)/kaddressbook/editors/libkabim.la \ + -lkdeprint +libkaddressbook_la_COMPILE_FIRST = $(top_srcdir)/libkdepim/categoryselectdialog.h \ + $(top_srcdir)/libkdepim/categoryeditdialog.h \ + $(top_builddir)/kaddressbook/common/kabprefs_base.h + + +noinst_HEADERS = \ + addresseditwidget.h addresseeconfig.h \ + addresseeeditordialog.h addresseeeditorwidget.h addresseeutil.h \ + addviewdialog.h emaileditwidget.h extensionmanager.h \ + filtereditdialog.h filterselectionwidget.h geowidget.h imagewidget.h \ + incsearchwidget.h jumpbuttonbar.h kablock.h kaddressbook_part.h \ + kaddressbookservice.h kaddressbookview.h keywidget.h \ + ldapsearchdialog.h nameeditdialog.h phoneeditwidget.h secrecywidget.h \ + soundwidget.h typecombo.h undocmds.h viewconfigurefieldspage.h \ + viewconfigurefilterpage.h viewconfigurewidget.h viewmanager.h xxportmanager.h \ + xxportselectdialog.h advancedcustomfields.h imeditwidget.h + +kaddressbook_METASOURCES = AUTO + +rcdir = $(kde_datadir)/kaddressbook +rc_DATA = kaddressbookui.rc kaddressbook_part.rc + +kabdatadir = $(kde_datadir)/kaddressbook +kabdata_DATA = zone.tab + +xdg_apps_DATA = kaddressbook.desktop + +servicetypedir = $(kde_servicetypesdir) +servicetype_DATA = kaddressbook_view.desktop dcopaddressbook.desktop + +KDE_ICON = kaddressbook + +messages: rc.cpp + $(EXTRACTRC) --context="Instant messaging" editors/im*.ui >> rc.cpp + $(EXTRACTRC) printing/*.ui >> rc.cpp + $(EXTRACTRC) */*.kcfg >> rc.cpp + $(XGETTEXT) *.h *.cpp common/*.cpp editors/*.cpp features/*.cpp printing/*.cpp views/*.cpp xxport/*.cpp interfaces/*.h -o $(podir)/kaddressbook.pot + +srcdoc: + $(mkinstalldirs) $(SRCDOC_DEST) + kdoc -H -d $(SRCDOC_DEST) kaddressbook $(noinst_HEADERS) -lqt + +include $(top_srcdir)/admin/Doxyfile.am + +kaddressbook_part.lo: common/kabprefs_base.h diff --git a/kaddressbook/TODO b/kaddressbook/TODO new file mode 100644 index 000000000..df0db82b0 --- /dev/null +++ b/kaddressbook/TODO @@ -0,0 +1,65 @@ +KAddressBook Todo (not sorted at all!): +--------------------------------------- + +-------------------- +For KDE 3.1 (July 1) +-------------------- + +New Features (features people want that have not been implemented) +------------ +- Implement other views (CardView) - 80% (Painting and selection problems) +- Embed quickedit widget - 95% +- Implement filtering - DONE +- Add a Confirm Quit dialog if the addressbook is modified and the + user tries to quit +- Printing Framework - DONE + + +Improvements (things that just need to be improved/rewritten) +------------ +- Lazy loading of views - DONE +- Move view information into the manager (don't let the part read the config + file to get a list of views) - DONE +- Redo and move the DCOP interface - 50% +- Cleanup the tableview more - DONE +- Relayout the edit contact dialog - DONE +- Remove ContactEntry*. Impelement supporting classes required + for this. - DONE +- Update the way the ConfigureView dialog gets the view config page - DONE +- Add a meta data wrapper for views - DONE +- Add show/hide toolbars in the edit menu - DONE +- Break KAddressBook into KAddressBook and ViewManager - DONE +- Change the view items to take a KABC::Addressee rather than a uid - DONE +- DnD on Card View - DONE +- Card View specific config options - DONE +- Implemented a good date picker widget somehow using the KDatePicker + widget (needed for korganizer also) - DONE +- Implement more print styles +- Add categories for Contact grouping - DONE +- Move the Filter and Incremental search tools to toolbars +- Move detailed view from a separate view to a common widget in the view + manager +- Rename the 'sync' button to 'Save' - DONE + + +Fixes (things that used to work and are now broken) +----- +- Fix import/export code to use KABC::Addressee - DONE +- Fix/reinstate LDAP dialog - DONE +- Fix vcard importing +- Fix KPilot abbrowser conduit +- Re-add specific view options pages for Table View - DONE + + +------------- +After KDE 3.1 +------------- + +New Features (features people want that have not been implemented) +------------ +- Move to a Read/Write part +- More advanced searching using any field in a contact + +Fixes +----- +- Reinstate custom fields and a custom field editor diff --git a/kaddressbook/addresseditwidget.cpp b/kaddressbook/addresseditwidget.cpp new file mode 100644 index 000000000..54171c34e --- /dev/null +++ b/kaddressbook/addresseditwidget.cpp @@ -0,0 +1,678 @@ +/* + This file is part of KAddressBook. + Copyright (c) 2002 Mike Pilone <mpilone@slac.com> + 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 <qbuttongroup.h> +#include <qcheckbox.h> +#include <qhbox.h> +#include <qlabel.h> +#include <qlayout.h> +#include <qlistbox.h> +#include <qlistview.h> +#include <qpushbutton.h> +#include <qsignal.h> +#include <qstring.h> +#include <qtextedit.h> +#include <qtoolbutton.h> +#include <qtooltip.h> + +#include <kaccelmanager.h> +#include <kactivelabel.h> +#include <kapplication.h> +#include <kbuttonbox.h> +#include <kcombobox.h> +#include <kconfig.h> +#include <kdebug.h> +#include <kdialog.h> +#include <kiconloader.h> +#include <kinputdialog.h> +#include <klineedit.h> +#include <klistview.h> +#include <klocale.h> +#include <kmessagebox.h> +#include <kseparator.h> + +#include "addresseditwidget.h" + +class TabPressEater : public QObject +{ + public: + TabPressEater( QObject *parent ) + : QObject( parent, "TabPressEater" ) + { + } + + protected: + bool eventFilter( QObject*, QEvent *event ) + { + if ( event->type() == QEvent::KeyPress ) { + QKeyEvent *keyEvent = (QKeyEvent*)event; + if ( keyEvent->key() == Qt::Key_Tab ) { + QApplication::sendEvent( parent(), event ); + return true; + } else + return false; + } else { + return false; + } + } +}; + + +AddressEditWidget::AddressEditWidget( QWidget *parent, const char *name ) + : QWidget( parent, name ) +{ + QBoxLayout *layout = new QVBoxLayout( this, 4, 2 ); + layout->setSpacing( KDialog::spacingHint() ); + + mTypeCombo = new AddressTypeCombo( mAddressList, this ); + connect( mTypeCombo, SIGNAL( activated( int ) ), + SLOT( updateAddressEdit() ) ); + layout->addWidget( mTypeCombo ); + + mAddressField = new KActiveLabel( this ); + mAddressField->setFrameStyle( QFrame::Panel | QFrame::Sunken ); + mAddressField->setMinimumHeight( 20 ); + mAddressField->setAlignment( Qt::AlignTop ); + mAddressField->setTextFormat( Qt::PlainText ); + layout->addWidget( mAddressField ); + + mEditButton = new QPushButton( i18n( "street/postal", "&Edit Addresses..." ), this ); + connect( mEditButton, SIGNAL( clicked() ), this, SLOT( edit() ) ); + + layout->addWidget( mEditButton ); +} + +AddressEditWidget::~AddressEditWidget() +{ +} + +void AddressEditWidget::setReadOnly( bool readOnly ) +{ + mEditButton->setEnabled( !readOnly ); +} + +KABC::Address::List AddressEditWidget::addresses() +{ + KABC::Address::List retList; + + KABC::Address::List::ConstIterator it; + for ( it = mAddressList.begin(); it != mAddressList.end(); ++it ) + if ( !(*it).isEmpty() ) + retList.append( *it ); + + return retList; +} + +void AddressEditWidget::setAddresses( const KABC::Addressee &addr, + const KABC::Address::List &list ) +{ + mAddressee = addr; + + mAddressList.clear(); + + // Insert types for existing numbers. + mTypeCombo->insertTypeList( list ); + + QValueList<int> defaultTypes; + defaultTypes << KABC::Address::Home; + defaultTypes << KABC::Address::Work; + + AddresseeConfig config( mAddressee ); + const QValueList<int> configList = config.noDefaultAddrTypes(); + QValueList<int>::ConstIterator it; + for ( it = configList.begin(); it != configList.end(); ++it ) + defaultTypes.remove( *it ); + + // Insert default types. + // Doing this for mPrefCombo is enough because the list is shared by all + // combos. + for ( it = defaultTypes.begin(); it != defaultTypes.end(); ++it ) { + if ( !mTypeCombo->hasType( *it ) ) + mTypeCombo->insertType( list, *it, Address( *it ) ); + } + + mTypeCombo->updateTypes(); + + // find preferred address which will be shown + int preferred = KABC::Address::Home; // default if no preferred address set + KABC::Address::List::ConstIterator addrIt; + for ( addrIt = list.begin(); addrIt != list.end(); ++addrIt ) + if ( (*addrIt).type() & KABC::Address::Pref ) { + preferred = (*addrIt).type(); + break; + } + + mTypeCombo->selectType( preferred ); + + updateAddressEdit(); +} + +void AddressEditWidget::updateAddressee( const KABC::Addressee &addr ) +{ + mAddressee = addr; + updateAddressEdit(); +} + +void AddressEditWidget::edit() +{ + AddressEditDialog dialog( mAddressList, mTypeCombo->currentItem(), this ); + if ( dialog.exec() ) { + if ( dialog.changed() ) { + mAddressList = dialog.addresses(); + + bool hasHome = false, hasWork = false; + KABC::Address::List::ConstIterator it; + for ( it = mAddressList.begin(); it != mAddressList.end(); ++it ) { + if ( (*it).type() == KABC::Address::Home ) { + if ( !(*it).isEmpty() ) + hasHome = true; + } + if ( (*it).type() == KABC::Address::Work ) { + if ( !(*it).isEmpty() ) + hasWork = true; + } + } + + AddresseeConfig config( mAddressee ); + QValueList<int> configList; + if ( !hasHome ) + configList << KABC::Address::Home; + if ( !hasWork ) + configList << KABC::Address::Work; + config.setNoDefaultAddrTypes( configList ); + + mTypeCombo->updateTypes(); + updateAddressEdit(); + emit modified(); + } + } +} + +void AddressEditWidget::updateAddressEdit() +{ + KABC::Address::List::Iterator it = mTypeCombo->selectedElement(); + + bool block = signalsBlocked(); + blockSignals( true ); + + mAddressField->setText( "" ); + + if ( it != mAddressList.end() ) { + KABC::Address a = *it; + if ( !a.isEmpty() ) { +#if KDE_VERSION >= 319 + if ( a.type() & KABC::Address::Work && mAddressee.realName() != mAddressee.organization() ) { + mAddressField->setText( a.formattedAddress( mAddressee.realName(), + mAddressee.organization() ) ); + } else { + mAddressField->setText( a.formattedAddress( mAddressee.realName() ) ); + } +#else + QString text; + if ( !a.street().isEmpty() ) + text += a.street() + "\n"; + + if ( !a.postOfficeBox().isEmpty() ) + text += a.postOfficeBox() + "\n"; + + text += a.locality() + QString(" ") + a.region(); + + if ( !a.postalCode().isEmpty() ) + text += QString(", ") + a.postalCode(); + + text += "\n"; + + if ( !a.country().isEmpty() ) + text += a.country() + "\n"; + + text += a.extended(); + + mAddressField->setText( text ); +#endif + } + } + + blockSignals( block ); +} + +AddressEditDialog::AddressEditDialog( const KABC::Address::List &list, + int selected, QWidget *parent, + const char *name ) + : KDialogBase( Plain, i18n( "street/postal", "Edit Address" ), Ok | Cancel, Ok, + parent, name, true, true ), + mPreviousAddress( 0 ) +{ + mAddressList = list; + + QWidget *page = plainPage(); + + QGridLayout *topLayout = new QGridLayout( page, 8, 2 ); + topLayout->setSpacing( spacingHint() ); + + mTypeCombo = new AddressTypeCombo( mAddressList, page ); + topLayout->addMultiCellWidget( mTypeCombo, 0, 0, 0, 1 ); + + QLabel *label = new QLabel( i18n( "<streetLabel>:", "%1:" ).arg( KABC::Address::streetLabel() ), page ); + label->setAlignment( Qt::AlignTop | Qt::AlignLeft ); + topLayout->addWidget( label, 1, 0 ); + mStreetTextEdit = new QTextEdit( page ); + mStreetTextEdit->setTextFormat( Qt::PlainText ); + label->setBuddy( mStreetTextEdit ); + topLayout->addWidget( mStreetTextEdit, 1, 1 ); + + TabPressEater *eater = new TabPressEater( this ); + mStreetTextEdit->installEventFilter( eater ); + + label = new QLabel( i18n( "<postOfficeBoxLabel>:", "%1:" ).arg( KABC::Address::postOfficeBoxLabel() ), page ); + topLayout->addWidget( label, 2 , 0 ); + mPOBoxEdit = new KLineEdit( page ); + label->setBuddy( mPOBoxEdit ); + topLayout->addWidget( mPOBoxEdit, 2, 1 ); + + label = new QLabel( i18n( "<localityLabel>:", "%1:" ).arg( KABC::Address::localityLabel() ), page ); + topLayout->addWidget( label, 3, 0 ); + mLocalityEdit = new KLineEdit( page ); + label->setBuddy( mLocalityEdit ); + topLayout->addWidget( mLocalityEdit, 3, 1 ); + + label = new QLabel( i18n( "<regionLabel>:", "%1:" ).arg( KABC::Address::regionLabel() ), page ); + topLayout->addWidget( label, 4, 0 ); + mRegionEdit = new KLineEdit( page ); + label->setBuddy( mRegionEdit ); + topLayout->addWidget( mRegionEdit, 4, 1 ); + + label = new QLabel( i18n( "<postalCodeLabel>:", "%1:" ).arg( KABC::Address::postalCodeLabel() ), page ); + topLayout->addWidget( label, 5, 0 ); + mPostalCodeEdit = new KLineEdit( page ); + label->setBuddy( mPostalCodeEdit ); + topLayout->addWidget( mPostalCodeEdit, 5, 1 ); + + label = new QLabel( i18n( "<countryLabel>:", "%1:" ).arg( KABC::Address::countryLabel() ), page ); + topLayout->addWidget( label, 6, 0 ); + mCountryCombo = new KComboBox( page ); + mCountryCombo->setEditable( true ); + mCountryCombo->setDuplicatesEnabled( false ); + +#if KDE_IS_VERSION(3,3,0) + QPushButton *labelButton = new QPushButton( i18n( "Edit Label..." ), page ); + topLayout->addMultiCellWidget( labelButton, 7, 7, 0, 1 ); + connect( labelButton, SIGNAL( clicked() ), SLOT( editLabel() ) ); +#endif + + fillCountryCombo(); + label->setBuddy( mCountryCombo ); + topLayout->addWidget( mCountryCombo, 6, 1 ); + + mPreferredCheckBox = new QCheckBox( i18n( "street/postal", "This is the preferred address" ), page ); + topLayout->addMultiCellWidget( mPreferredCheckBox, 8, 8, 0, 1 ); + + KSeparator *sep = new KSeparator( KSeparator::HLine, page ); + topLayout->addMultiCellWidget( sep, 9, 9, 0, 1 ); + + QHBox *buttonBox = new QHBox( page ); + buttonBox->setSpacing( spacingHint() ); + topLayout->addMultiCellWidget( buttonBox, 10, 10, 0, 1 ); + + QPushButton *addButton = new QPushButton( i18n( "New..." ), buttonBox ); + connect( addButton, SIGNAL( clicked() ), SLOT( addAddress() ) ); + + mRemoveButton = new QPushButton( i18n( "Remove" ), buttonBox ); + connect( mRemoveButton, SIGNAL( clicked() ), SLOT( removeAddress() ) ); + + mChangeTypeButton = new QPushButton( i18n( "Change Type..." ), buttonBox ); + connect( mChangeTypeButton, SIGNAL( clicked() ), SLOT( changeType() ) ); + + mTypeCombo->updateTypes(); + mTypeCombo->setCurrentItem( selected ); + + updateAddressEdits(); + + connect( mTypeCombo, SIGNAL( activated( int ) ), + SLOT( updateAddressEdits() ) ); + connect( mStreetTextEdit, SIGNAL( textChanged() ), SLOT( modified() ) ); + connect( mPOBoxEdit, SIGNAL( textChanged( const QString& ) ), SLOT( modified() ) ); + connect( mLocalityEdit, SIGNAL( textChanged( const QString& ) ), SLOT( modified() ) ); + connect( mRegionEdit, SIGNAL( textChanged( const QString& ) ), SLOT( modified() ) ); + connect( mPostalCodeEdit, SIGNAL( textChanged( const QString& ) ), SLOT( modified() ) ); + connect( mCountryCombo, SIGNAL( textChanged( const QString& ) ), SLOT( modified() ) ); + connect( mPreferredCheckBox, SIGNAL( toggled( bool ) ), SLOT( modified() ) ); + + KAcceleratorManager::manage( this ); + + mChanged = false; + + bool state = (mAddressList.count() > 0); + mRemoveButton->setEnabled( state ); + mChangeTypeButton->setEnabled( state ); +} + +AddressEditDialog::~AddressEditDialog() +{ +} + +KABC::Address::List AddressEditDialog::addresses() +{ + saveAddress( *(mTypeCombo->selectedElement()) ); + + return mAddressList; +} + +bool AddressEditDialog::changed() const +{ + return mChanged; +} + +void AddressEditDialog::addAddress() +{ + AddressTypeDialog dlg( mTypeCombo->selectedType(), this ); + if ( dlg.exec() ) { + mAddressList.append( Address( dlg.type() ) ); + + mTypeCombo->updateTypes(); + mTypeCombo->setCurrentItem( mTypeCombo->count() - 1 ); + updateAddressEdits(); + + modified(); + + mRemoveButton->setEnabled( true ); + mChangeTypeButton->setEnabled( true ); + } +} + +void AddressEditDialog::removeAddress() +{ + if ( mAddressList.count() > 0 ) { + KABC::Address::List::Iterator it = mTypeCombo->selectedElement(); + if ( mPreviousAddress && mPreviousAddress->id() == (*it).id() ) + mPreviousAddress = 0; + + mAddressList.remove( it ); + mTypeCombo->updateTypes(); + updateAddressEdits(); + + modified(); + } + + bool state = ( mAddressList.count() > 0 ); + mRemoveButton->setEnabled( state ); + mChangeTypeButton->setEnabled( state ); +} + +void AddressEditDialog::changeType() +{ + KABC::Address::List::Iterator a = mTypeCombo->selectedElement(); + + AddressTypeDialog dlg( (*a).type(), this ); + if ( dlg.exec() ) { + (*a).setType( dlg.type() ); + + mTypeCombo->updateTypes(); + + modified(); + } +} + +void AddressEditDialog::editLabel() +{ +#if KDE_IS_VERSION(3,3,0) + bool ok = false; + QString result = KInputDialog::getMultiLineText( KABC::Address::labelLabel(), + KABC::Address::labelLabel(), + mLabel, &ok, this ); + if ( ok ) { + mLabel = result; + modified(); + } +#endif +} + +void AddressEditDialog::updateAddressEdits() +{ + if ( mPreviousAddress ) + saveAddress( *mPreviousAddress ); + + KABC::Address::List::Iterator it = mTypeCombo->selectedElement(); + KABC::Address a = *it; + mPreviousAddress = &(*it); + + bool tmp = mChanged; + + mStreetTextEdit->setText( a.street() ); + mRegionEdit->setText( a.region() ); + mLocalityEdit->setText( a.locality() ); + mPostalCodeEdit->setText( a.postalCode() ); + mPOBoxEdit->setText( a.postOfficeBox() ); + mCountryCombo->setCurrentText( a.country() ); + mLabel = a.label(); + + mPreferredCheckBox->setChecked( a.type() & KABC::Address::Pref ); + + if ( a.isEmpty() ) + mCountryCombo->setCurrentText( KGlobal::locale()->twoAlphaToCountryName( KGlobal::locale()->country() ) ); + + mStreetTextEdit->setFocus(); + + mChanged = tmp; +} + +void AddressEditDialog::modified() +{ + mChanged = true; +} + +void AddressEditDialog::saveAddress( KABC::Address &addr ) +{ + addr.setLocality( mLocalityEdit->text() ); + addr.setRegion( mRegionEdit->text() ); + addr.setPostalCode( mPostalCodeEdit->text() ); + addr.setCountry( mCountryCombo->currentText() ); + addr.setPostOfficeBox( mPOBoxEdit->text() ); + addr.setStreet( mStreetTextEdit->text() ); + addr.setLabel( mLabel ); + + + if ( mPreferredCheckBox->isChecked() ) { + KABC::Address::List::Iterator it; + for ( it = mAddressList.begin(); it != mAddressList.end(); ++it ) + (*it).setType( (*it).type() & ~( KABC::Address::Pref ) ); + + addr.setType( addr.type() | KABC::Address::Pref ); + } else + addr.setType( addr.type() & ~( KABC::Address::Pref ) ); +} + +void AddressEditDialog::fillCountryCombo() +{ + QString country[] = { + i18n( "Afghanistan" ), i18n( "Albania" ), i18n( "Algeria" ), + i18n( "American Samoa" ), i18n( "Andorra" ), i18n( "Angola" ), + i18n( "Anguilla" ), i18n( "Antarctica" ), i18n( "Antigua and Barbuda" ), + i18n( "Argentina" ), i18n( "Armenia" ), i18n( "Aruba" ), + i18n( "Ashmore and Cartier Islands" ), i18n( "Australia" ), + i18n( "Austria" ), i18n( "Azerbaijan" ), i18n( "Bahamas" ), + i18n( "Bahrain" ), i18n( "Bangladesh" ), i18n( "Barbados" ), + i18n( "Belarus" ), i18n( "Belgium" ), i18n( "Belize" ), + i18n( "Benin" ), i18n( "Bermuda" ), i18n( "Bhutan" ), + i18n( "Bolivia" ), i18n( "Bosnia and Herzegovina" ), i18n( "Botswana" ), + i18n( "Brazil" ), i18n( "Brunei" ), i18n( "Bulgaria" ), + i18n( "Burkina Faso" ), i18n( "Burundi" ), i18n( "Cambodia" ), + i18n( "Cameroon" ), i18n( "Canada" ), i18n( "Cape Verde" ), + i18n( "Cayman Islands" ), i18n( "Central African Republic" ), + i18n( "Chad" ), i18n( "Chile" ), i18n( "China" ), i18n( "Colombia" ), + i18n( "Comoros" ), i18n( "Congo" ), i18n( "Congo, Dem. Rep." ), + i18n( "Costa Rica" ), i18n( "Croatia" ), + i18n( "Cuba" ), i18n( "Cyprus" ), i18n( "Czech Republic" ), + i18n( "Denmark" ), i18n( "Djibouti" ), + i18n( "Dominica" ), i18n( "Dominican Republic" ), i18n( "Ecuador" ), + i18n( "Egypt" ), i18n( "El Salvador" ), i18n( "Equatorial Guinea" ), + i18n( "Eritrea" ), i18n( "Estonia" ), i18n( "England" ), + i18n( "Ethiopia" ), i18n( "European Union" ), i18n( "Faroe Islands" ), + i18n( "Fiji" ), i18n( "Finland" ), i18n( "France" ), + i18n( "French Polynesia" ), i18n( "Gabon" ), i18n( "Gambia" ), + i18n( "Georgia" ), i18n( "Germany" ), i18n( "Ghana" ), + i18n( "Greece" ), i18n( "Greenland" ), i18n( "Grenada" ), + i18n( "Guam" ), i18n( "Guatemala" ), i18n( "Guinea" ), + i18n( "Guinea-Bissau" ), i18n( "Guyana" ), i18n( "Haiti" ), + i18n( "Honduras" ), i18n( "Hong Kong" ), i18n( "Hungary" ), + i18n( "Iceland" ), i18n( "India" ), i18n( "Indonesia" ), + i18n( "Iran" ), i18n( "Iraq" ), i18n( "Ireland" ), + i18n( "Israel" ), i18n( "Italy" ), i18n( "Ivory Coast" ), + i18n( "Jamaica" ), i18n( "Japan" ), i18n( "Jordan" ), + i18n( "Kazakhstan" ), i18n( "Kenya" ), i18n( "Kiribati" ), + i18n( "Korea, North" ), i18n( "Korea, South" ), + i18n( "Kuwait" ), i18n( "Kyrgyzstan" ), i18n( "Laos" ), + i18n( "Latvia" ), i18n( "Lebanon" ), i18n( "Lesotho" ), + i18n( "Liberia" ), i18n( "Libya" ), i18n( "Liechtenstein" ), + i18n( "Lithuania" ), i18n( "Luxembourg" ), i18n( "Macau" ), + i18n( "Madagascar" ), i18n( "Malawi" ), i18n( "Malaysia" ), + i18n( "Maldives" ), i18n( "Mali" ), i18n( "Malta" ), + i18n( "Marshall Islands" ), i18n( "Martinique" ), i18n( "Mauritania" ), + i18n( "Mauritius" ), i18n( "Mexico" ), + i18n( "Micronesia, Federated States Of" ), i18n( "Moldova" ), + i18n( "Monaco" ), i18n( "Mongolia" ), i18n( "Montserrat" ), + i18n( "Morocco" ), i18n( "Mozambique" ), i18n( "Myanmar" ), + i18n( "Namibia" ), + i18n( "Nauru" ), i18n( "Nepal" ), i18n( "Netherlands" ), + i18n( "Netherlands Antilles" ), i18n( "New Caledonia" ), + i18n( "New Zealand" ), i18n( "Nicaragua" ), i18n( "Niger" ), + i18n( "Nigeria" ), i18n( "Niue" ), i18n( "North Korea" ), + i18n( "Northern Ireland" ), i18n( "Northern Mariana Islands" ), + i18n( "Norway" ), i18n( "Oman" ), i18n( "Pakistan" ), i18n( "Palau" ), + i18n( "Palestinian" ), i18n( "Panama" ), i18n( "Papua New Guinea" ), + i18n( "Paraguay" ), i18n( "Peru" ), i18n( "Philippines" ), + i18n( "Poland" ), i18n( "Portugal" ), i18n( "Puerto Rico" ), + i18n( "Qatar" ), i18n( "Romania" ), i18n( "Russia" ), i18n( "Rwanda" ), + i18n( "St. Kitts and Nevis" ), i18n( "St. Lucia" ), + i18n( "St. Vincent and the Grenadines" ), i18n( "San Marino" ), + i18n( "Sao Tome and Principe" ), i18n( "Saudi Arabia" ), + i18n( "Senegal" ), i18n( "Serbia & Montenegro" ), i18n( "Seychelles" ), + i18n( "Sierra Leone" ), i18n( "Singapore" ), i18n( "Slovakia" ), + i18n( "Slovenia" ), i18n( "Solomon Islands" ), i18n( "Somalia" ), + i18n( "South Africa" ), i18n( "South Korea" ), i18n( "Spain" ), + i18n( "Sri Lanka" ), i18n( "St. Kitts and Nevis" ), i18n( "Sudan" ), + i18n( "Suriname" ), i18n( "Swaziland" ), i18n( "Sweden" ), + i18n( "Switzerland" ), i18n( "Syria" ), i18n( "Taiwan" ), + i18n( "Tajikistan" ), i18n( "Tanzania" ), i18n( "Thailand" ), + i18n( "Tibet" ), i18n( "Togo" ), i18n( "Tonga" ), + i18n( "Trinidad and Tobago" ), i18n( "Tunisia" ), i18n( "Turkey" ), + i18n( "Turkmenistan" ), i18n( "Turks and Caicos Islands" ), + i18n( "Tuvalu" ), i18n( "Uganda" ), i18n( "Ukraine" ), + i18n( "United Arab Emirates" ), i18n( "United Kingdom" ), + i18n( "United States" ), i18n( "Uruguay" ), i18n( "Uzbekistan" ), + i18n( "Vanuatu" ), i18n( "Vatican City" ), i18n( "Venezuela" ), + i18n( "Vietnam" ), i18n( "Western Samoa" ), i18n( "Yemen" ), + i18n( "Yugoslavia" ), i18n( "Zaire" ), i18n( "Zambia" ), + i18n( "Zimbabwe" ), + "" + }; + + QStringList countries; + for ( int i = 0; !country[ i ].isEmpty(); ++i ) + countries.append( country[ i ] ); + + countries = sortLocaleAware( countries ); + + mCountryCombo->insertStringList( countries ); + mCountryCombo->completionObject()->setItems( countries ); + mCountryCombo->setAutoCompletion( true ); +} + + +AddressTypeDialog::AddressTypeDialog( int type, QWidget *parent ) + : KDialogBase( Plain, i18n( "street/postal", "Edit Address Type" ), Ok | Cancel, Ok, + parent, "AddressTypeDialog" ) +{ + QWidget *page = plainPage(); + QVBoxLayout *layout = new QVBoxLayout( page ); + + mGroup = new QButtonGroup( 2, Horizontal, i18n( "street/postal", "Address Types" ), page ); + layout->addWidget( mGroup ); + + mTypeList = KABC::Address::typeList(); + mTypeList.remove( KABC::Address::Pref ); + + KABC::Address::TypeList::ConstIterator it; + for ( it = mTypeList.begin(); it != mTypeList.end(); ++it ) + new QCheckBox( KABC::Address::typeLabel( *it ), mGroup ); + + for ( int i = 0; i < mGroup->count(); ++i ) { + QCheckBox *box = (QCheckBox*)mGroup->find( i ); + box->setChecked( type & mTypeList[ i ] ); + } +} + +AddressTypeDialog::~AddressTypeDialog() +{ +} + +int AddressTypeDialog::type() const +{ + int type = 0; + for ( int i = 0; i < mGroup->count(); ++i ) { + QCheckBox *box = (QCheckBox*)mGroup->find( i ); + if ( box->isChecked() ) + type += mTypeList[ i ]; + } + + return type; +} + +/** + Small helper class, I hope we can remove it as soon as a general solution has + been committed to kdelibs + */ +class LocaleAwareString : public QString +{ + public: + LocaleAwareString() : QString() + {} + + LocaleAwareString( const QString &str ) : QString( str ) + {} +}; + +static bool operator<( const LocaleAwareString &s1, const LocaleAwareString &s2 ) +{ + return ( QString::localeAwareCompare( s1, s2 ) < 0 ); +} + +QStringList AddressEditDialog::sortLocaleAware( const QStringList &list ) +{ + QValueList<LocaleAwareString> sortedList; + + QStringList::ConstIterator it; + for ( it = list.begin(); it != list.end(); ++it ) + sortedList.append( LocaleAwareString( *it ) ); + + qHeapSort( sortedList ); + + QStringList retval; + QValueList<LocaleAwareString>::ConstIterator retIt; + for ( retIt = sortedList.begin(); retIt != sortedList.end(); ++retIt ) + retval.append( *retIt ); + + return retval; +} + +#include "addresseditwidget.moc" diff --git a/kaddressbook/addresseditwidget.h b/kaddressbook/addresseditwidget.h new file mode 100644 index 000000000..cf7703156 --- /dev/null +++ b/kaddressbook/addresseditwidget.h @@ -0,0 +1,154 @@ +/* + This file is part of KAddressBook. + Copyright (c) 2002 Mike Pilone <mpilone@slac.com> + + 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 ADDRESSEDITWIDGET_H +#define ADDRESSEDITWIDGET_H + +#include <qwidget.h> + +#include <kdialogbase.h> +#include <kabc/address.h> +#include <kabc/addressee.h> + +#include "addresseeconfig.h" +#include "typecombo.h" + +class QButtonGroup; +class QCheckBox; +class QListView; +class QTextEdit; +class QToolButton; + +class KActiveLabel; +class KComboBox; +class KLineEdit; +class KListView; + +typedef TypeCombo<KABC::Address> AddressTypeCombo; + +/** + Editor widget for addresses. + */ +class AddressEditWidget : public QWidget +{ + Q_OBJECT + + public: + AddressEditWidget( QWidget *parent, const char *name = 0 ); + ~AddressEditWidget(); + + KABC::Address::List addresses(); + void setAddresses( const KABC::Addressee &addr, + const KABC::Address::List &list ); + void updateAddressee( const KABC::Addressee &addr ); + + void updateTypeCombo( const KABC::Address::List&, KComboBox* ); + KABC::Address currentAddress( KComboBox*, int ); + + void setReadOnly( bool readOnly ); + + signals: + void modified(); + + protected slots: + void updateAddressEdit(); + + void edit(); + + private: + AddressTypeCombo *mTypeCombo; + + QPushButton *mEditButton; + KActiveLabel *mAddressField; + + KABC::Address::List mAddressList; + KABC::Addressee mAddressee; + int mIndex; +}; + +/** + Dialog for editing address details. + */ +class AddressEditDialog : public KDialogBase +{ + Q_OBJECT + + public: + AddressEditDialog( const KABC::Address::List &list, int selected, + QWidget *parent, const char *name = 0 ); + ~AddressEditDialog(); + + KABC::Address::List addresses(); + bool changed() const; + + protected slots: + void addAddress(); + void removeAddress(); + void changeType(); + void editLabel(); + + void updateAddressEdits(); + void modified(); + + private: + void saveAddress( KABC::Address &addr ); + void fillCountryCombo(); + QStringList sortLocaleAware( const QStringList& ); + + AddressTypeCombo *mTypeCombo; + QTextEdit *mStreetTextEdit; + KComboBox *mCountryCombo; + KLineEdit *mRegionEdit; + KLineEdit *mLocalityEdit; + KLineEdit *mPostalCodeEdit; + KLineEdit *mPOBoxEdit; + QCheckBox *mPreferredCheckBox; + + QPushButton *mRemoveButton; + QPushButton *mChangeTypeButton; + + KABC::Address::List mAddressList; + KABC::Address *mPreviousAddress; + bool mChanged; + + QString mLabel; +}; + +/** + Dialog for selecting an address type. + */ +class AddressTypeDialog : public KDialogBase +{ + public: + AddressTypeDialog( int type, QWidget *parent ); + ~AddressTypeDialog(); + + int type() const; + + private: + QButtonGroup *mGroup; + + KABC::Address::TypeList mTypeList; +}; + +#endif diff --git a/kaddressbook/addresseeconfig.cpp b/kaddressbook/addresseeconfig.cpp new file mode 100644 index 000000000..830127ebe --- /dev/null +++ b/kaddressbook/addresseeconfig.cpp @@ -0,0 +1,99 @@ +/* + This file is part of KAddressBook. + Copyright (c) 2002 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 "addresseeconfig.h" +#include "kabprefs.h" + +using namespace KABC; + +AddresseeConfig::AddresseeConfig() +{ + mAddressee = Addressee(); +} + +AddresseeConfig::AddresseeConfig( const Addressee &addr ) +{ + mAddressee = addr; +} + +void AddresseeConfig::setAddressee( const Addressee &addr ) +{ + mAddressee = addr; +} + +Addressee AddresseeConfig::addressee() +{ + return mAddressee; +} + +void AddresseeConfig::setAutomaticNameParsing( bool value ) +{ + KConfig config( "kaddressbook_addrconfig" ); + config.setGroup( mAddressee.uid() ); + config.writeEntry( "AutomaticNameParsing", value ); + config.sync(); +} + +bool AddresseeConfig::automaticNameParsing() +{ + KConfig config( "kaddressbook_addrconfig" ); + config.setGroup( mAddressee.uid() ); + return config.readBoolEntry( "AutomaticNameParsing", + KABPrefs::instance()->automaticNameParsing() ); +} + +void AddresseeConfig::setNoDefaultAddrTypes( const QValueList<int> &types ) +{ + KConfig config( "kaddressbook_addrconfig" ); + config.setGroup( mAddressee.uid() ); + config.writeEntry( "NoDefaultAddrTypes", types ); + config.sync(); +} + +QValueList<int> AddresseeConfig::noDefaultAddrTypes() const +{ + KConfig config( "kaddressbook_addrconfig" ); + config.setGroup( mAddressee.uid() ); + return config.readIntListEntry( "NoDefaultAddrTypes" ); +} + +void AddresseeConfig::setCustomFields( const QStringList &fields ) +{ + KConfig config( "kaddressbook_addrconfig" ); + config.setGroup( mAddressee.uid() ); + config.writeEntry( "LocalCustomFields", fields ); + config.sync(); +} + +QStringList AddresseeConfig::customFields() const +{ + KConfig config( "kaddressbook_addrconfig" ); + config.setGroup( mAddressee.uid() ); + return config.readListEntry( "LocalCustomFields" ); +} + +void AddresseeConfig::remove() +{ + KConfig config( "kaddressbook_addrconfig" ); + config.deleteGroup( mAddressee.uid() ); +} diff --git a/kaddressbook/addresseeconfig.h b/kaddressbook/addresseeconfig.h new file mode 100644 index 000000000..798d35e5a --- /dev/null +++ b/kaddressbook/addresseeconfig.h @@ -0,0 +1,56 @@ +/* + This file is part of KAddressBook. + Copyright (c) 2002 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 ADDRESSEECONFIG_H +#define ADDRESSEECONFIG_H + +#include <kabc/addressee.h> +#include <kconfig.h> + +using namespace KABC; + +class AddresseeConfig +{ + public: + AddresseeConfig(); + AddresseeConfig( const Addressee &addr ); + + void setAddressee( const Addressee &addr ); + Addressee addressee(); + + void setAutomaticNameParsing( bool value ); + bool automaticNameParsing(); + + void setNoDefaultAddrTypes( const QValueList<int> &types ); + QValueList<int> noDefaultAddrTypes() const; + + void setCustomFields( const QStringList &fields ); + QStringList customFields() const; + + void remove(); + + private: + Addressee mAddressee; +}; + +#endif diff --git a/kaddressbook/addresseeeditorbase.cpp b/kaddressbook/addresseeeditorbase.cpp new file mode 100644 index 000000000..f0352a707 --- /dev/null +++ b/kaddressbook/addresseeeditorbase.cpp @@ -0,0 +1,24 @@ +/* + This file is part of KAddressBook. + Copyright (c) 2005 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 "addresseeeditorbase.moc" diff --git a/kaddressbook/addresseeeditorbase.h b/kaddressbook/addresseeeditorbase.h new file mode 100644 index 000000000..394223b13 --- /dev/null +++ b/kaddressbook/addresseeeditorbase.h @@ -0,0 +1,59 @@ +/* + This file is part of KAddressBook. + Copyright (c) 2004 Cornelius Schumacher <schumacher@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 ADDRESSEEEDITORBASE_H +#define ADDRESSEEEDITORBASE_H + +#include <kabc/addressee.h> + +#include <qwidget.h> + +class AddresseeEditorBase : public QWidget +{ + Q_OBJECT + + public: + AddresseeEditorBase( QWidget *parent, const char *name = 0 ) + : QWidget( parent, name ) + { + } + + ~AddresseeEditorBase() {} + + virtual void setAddressee( const KABC::Addressee& ) = 0; + virtual const KABC::Addressee &addressee() = 0; + + virtual void setInitialFocus() = 0; + + virtual void load() = 0; + virtual void save() = 0; + + virtual bool dirty() = 0; + + virtual bool readyToClose() { return true; } + + signals: + void modified(); +}; + +#endif diff --git a/kaddressbook/addresseeeditordialog.cpp b/kaddressbook/addresseeeditordialog.cpp new file mode 100644 index 000000000..8df8357a2 --- /dev/null +++ b/kaddressbook/addresseeeditordialog.cpp @@ -0,0 +1,153 @@ +/* + This file is part of KAddressBook. + Copyright (c) 2002 Mike Pilone <mpilone@slac.com> + + 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 <qapplication.h> +#include <qlayout.h> + +#include <kdebug.h> +#include <klocale.h> + +#include "core.h" +#include "addresseeeditorwidget.h" +#include "simpleaddresseeeditor.h" +#include "kabprefs.h" + +#include "addresseeeditordialog.h" + +AddresseeEditorDialog::AddresseeEditorDialog( KAB::Core *core, + QWidget *parent, const char *name ) + : KDialogBase( KDialogBase::Plain, i18n( "Edit Contact" ), + KDialogBase::Ok | KDialogBase::Cancel | KDialogBase::Apply, + KDialogBase::Ok, parent, name, false ) +{ + // Set this to be the group leader for all subdialogs - this means + // modal subdialogs will only affect this dialog, not the other windows + setWFlags( getWFlags() | WGroupLeader ); + + kdDebug(5720) << "AddresseeEditorDialog()" << endl; + + QWidget *page = plainPage(); + + QVBoxLayout *layout = new QVBoxLayout( page ); + + if ( KABPrefs::instance()->editorType() == KABPrefs::SimpleEditor ) { + mEditorWidget = new SimpleAddresseeEditor( page ); + } else { + mEditorWidget = new AddresseeEditorWidget( page ); + } + connect( mEditorWidget, SIGNAL( modified() ), SLOT( widgetModified() ) ); + layout->addWidget( mEditorWidget ); + + enableButton( KDialogBase::Apply, false ); + + KConfig config( "kaddressbookrc" ); + config.setGroup( "AddresseeEditor" ); + QSize defaultSize( 750, 570 ); + resize( config.readSizeEntry( "Size", &defaultSize ) ); +} + +AddresseeEditorDialog::~AddresseeEditorDialog() +{ + kdDebug(5720) << "~AddresseeEditorDialog()" << endl; + + KConfig config( "kaddressbookrc" ); + config.setGroup( "AddresseeEditor" ); + config.writeEntry( "Size", size() ); + + emit editorDestroyed( mEditorWidget->addressee().uid() ); +} + +void AddresseeEditorDialog::setAddressee( const KABC::Addressee &addr ) +{ + enableButton( KDialogBase::Apply, false ); + + setTitle( addr ); + + mEditorWidget->setAddressee( addr ); + mEditorWidget->setInitialFocus(); +} + +KABC::Addressee AddresseeEditorDialog::addressee() +{ + return mEditorWidget->addressee(); +} + +bool AddresseeEditorDialog::dirty() +{ + return mEditorWidget->dirty(); +} + +void AddresseeEditorDialog::slotApply() +{ + if ( !mEditorWidget->readyToClose() ) + return; + + if ( mEditorWidget->dirty() ) { + QApplication::setOverrideCursor( Qt::waitCursor ); + mEditorWidget->save(); + emit contactModified( mEditorWidget->addressee() ); + QApplication::restoreOverrideCursor(); + } + + enableButton( KDialogBase::Apply, false ); + + KDialogBase::slotApply(); +} + +void AddresseeEditorDialog::slotOk() +{ + if ( !mEditorWidget->readyToClose() ) + return; + + slotApply(); + + KDialogBase::slotOk(); + + // Destroy this dialog + delayedDestruct(); +} + +void AddresseeEditorDialog::widgetModified() +{ + const KABC::Addressee addressee = mEditorWidget->addressee(); + if ( !addressee.isEmpty() ) + setTitle( addressee ); + + enableButton( KDialogBase::Apply, true ); +} + +void AddresseeEditorDialog::slotCancel() +{ + KDialogBase::slotCancel(); + + // Destroy this dialog + delayedDestruct(); +} + +void AddresseeEditorDialog::setTitle( const KABC::Addressee &addr ) +{ + if ( !addr.realName().isEmpty() ) + setCaption( i18n( "Edit Contact '%1'" ).arg( addr.realName() ) ); +} + +#include "addresseeeditordialog.moc" diff --git a/kaddressbook/addresseeeditordialog.h b/kaddressbook/addresseeeditordialog.h new file mode 100644 index 000000000..889dd655f --- /dev/null +++ b/kaddressbook/addresseeeditordialog.h @@ -0,0 +1,65 @@ +/* + This file is part of KAddressBook. + Copyright (c) 2002 Mike Pilone <mpilone@slac.com> + + 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 ADDRESSEEEDITORDIALOG_H +#define ADDRESSEEEDITORDIALOG_H + +#include <kdialogbase.h> + +#include <kabc/addressbook.h> + +class AddresseeEditorBase; +class QWidget; +namespace KAB { class Core; } + +class AddresseeEditorDialog : public KDialogBase +{ + Q_OBJECT + + public: + AddresseeEditorDialog( KAB::Core *core, + QWidget *parent, const char *name = 0 ); + ~AddresseeEditorDialog(); + + void setAddressee( const KABC::Addressee& ); + KABC::Addressee addressee(); + + bool dirty(); + + signals: + void contactModified( const KABC::Addressee& ); + void editorDestroyed( const QString& ); + + protected slots: + virtual void slotApply(); + virtual void slotOk(); + virtual void slotCancel(); + void widgetModified(); + + private: + virtual void setTitle( const KABC::Addressee& ); + + AddresseeEditorBase *mEditorWidget; +}; + +#endif diff --git a/kaddressbook/addresseeeditorextension.cpp b/kaddressbook/addresseeeditorextension.cpp new file mode 100644 index 000000000..b98260a7e --- /dev/null +++ b/kaddressbook/addresseeeditorextension.cpp @@ -0,0 +1,76 @@ +/* + This file is part of KAddressBook. + Copyright (c) 2005 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 <qlayout.h> + +#include <klocale.h> + +#include "kabprefs.h" + +#include "addresseeeditorwidget.h" +#include "simpleaddresseeeditor.h" + +#include "addresseeeditorextension.h" + +AddresseeEditorExtension::AddresseeEditorExtension( KAB::Core *core, QWidget *parent, const char *name ) + : KAB::ExtensionWidget( core, parent, name ) +{ + QVBoxLayout *layout = new QVBoxLayout( this ); + + if ( KABPrefs::instance()->editorType() == KABPrefs::SimpleEditor ) + mAddresseeEditor = new SimpleAddresseeEditor( this ); + else + mAddresseeEditor = new AddresseeEditorWidget( this ); + + layout->addWidget( mAddresseeEditor ); +} + +AddresseeEditorExtension::~AddresseeEditorExtension() +{ +} + +void AddresseeEditorExtension::contactsSelectionChanged() +{ + const KABC::Addressee::List selectedAddressees = selectedContacts(); + KABC::Addressee::List addressees; + + if ( mAddresseeEditor->dirty() ) { + mAddresseeEditor->save(); + addressees.append( mAddresseeEditor->addressee() ); + emit modified( addressees ); + } + + mAddresseeEditor->setAddressee( selectedAddressees[ 0 ] ); +} + +QString AddresseeEditorExtension::title() const +{ + return i18n( "Contact Editor" ); +} + +QString AddresseeEditorExtension::identifier() const +{ + return "contact_editor"; +} + +#include "addresseeeditorextension.moc" diff --git a/kaddressbook/addresseeeditorextension.h b/kaddressbook/addresseeeditorextension.h new file mode 100644 index 000000000..3eab5c134 --- /dev/null +++ b/kaddressbook/addresseeeditorextension.h @@ -0,0 +1,59 @@ +/* + This file is part of KAddressBook. + Copyright (c) 2005 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 ADDRESSEEEDITOREXTENSION_H +#define ADDRESSEEEDITOREXTENSION_H + +#include "addresseeeditorbase.h" +#include "extensionwidget.h" + +class AddresseeEditorExtension : public KAB::ExtensionWidget +{ + Q_OBJECT + + public: + AddresseeEditorExtension( KAB::Core *core, QWidget *parent, const char *name = 0 ); + ~AddresseeEditorExtension(); + + /** + This method is called whenever the selection in the view changed. + */ + virtual void contactsSelectionChanged(); + + /** + This method should be reimplemented and return the i18ned title of this + widget. + */ + virtual QString title() const; + + /** + This method should be reimplemented and return a unique identifier. + */ + virtual QString identifier() const; + + private: + AddresseeEditorBase *mAddresseeEditor; + bool mDirty; +}; + +#endif diff --git a/kaddressbook/addresseeeditorwidget.cpp b/kaddressbook/addresseeeditorwidget.cpp new file mode 100644 index 000000000..253c3b45b --- /dev/null +++ b/kaddressbook/addresseeeditorwidget.cpp @@ -0,0 +1,909 @@ +/* + This file is part of KAddressBook. + Copyright (c) 2002 Mike Pilone <mpilone@slac.com> + + 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 <qhbox.h> +#include <qlabel.h> +#include <qlayout.h> +#include <qlistbox.h> +#include <qpushbutton.h> +#include <qtabwidget.h> +#include <qtextedit.h> +#include <qtoolbutton.h> +#include <qtooltip.h> + +#include <kabc/resource.h> +#include <kabc/stdaddressbook.h> +#include <kaccelmanager.h> +#include <kapplication.h> +#include <kconfig.h> +#include <kcombobox.h> +#include <kdebug.h> +#include <kdialogbase.h> +#include <kglobal.h> +#include <kiconloader.h> +#include <klineedit.h> +#include <klocale.h> +#include <kmessagebox.h> +#include <kseparator.h> +#include <ksqueezedtextlabel.h> +#include <kstandarddirs.h> + +#include <libkdepim/addresseelineedit.h> +#include <libkdepim/categoryeditdialog.h> +#include <libkdepim/categoryselectdialog.h> +#include <libkdepim/kdateedit.h> +#include <libkdepim/resourceabc.h> + +#include "addresseditwidget.h" +#include "advancedcustomfields.h" +#include "emaileditwidget.h" +#include "imeditwidget.h" +#include "kabprefs.h" +#include "keywidget.h" +#include "nameeditdialog.h" +#include "phoneeditwidget.h" +#include "secrecywidget.h" + +#include "addresseeeditorwidget.h" + +AddresseeEditorWidget::AddresseeEditorWidget( QWidget *parent, const char *name ) + : AddresseeEditorBase( parent, name ), + mBlockSignals( false ), mReadOnly( false ) +{ + kdDebug(5720) << "AddresseeEditorWidget()" << endl; + + initGUI(); + mCategorySelectDialog = 0; + mCategoryEditDialog = 0; + + // Load the empty addressee as defaults + load(); + + mDirty = false; +} + +AddresseeEditorWidget::~AddresseeEditorWidget() +{ + kdDebug(5720) << "~AddresseeEditorWidget()" << endl; +} + +void AddresseeEditorWidget::setAddressee( const KABC::Addressee &addr ) +{ + if ( mAddressee.uid() == addr.uid() ) + return; + mAddressee = addr; + + bool readOnly = false; + if ( KABC::Resource *res = addr.resource() ) { + if ( res->readOnly() ) { + readOnly = true; + + //Kolab resources have finer access control than planned in the overall design. + } else if ( res->inherits( "KPIM::ResourceABC" ) ) { + KPIM::ResourceABC *resAbc = static_cast<KPIM::ResourceABC *>( res ); + + QString subresource = resAbc->uidToResourceMap()[ addr.uid() ]; + if ( !subresource.isEmpty() ) + readOnly |= !resAbc->subresourceWritable( subresource ); + } + } + setReadOnly( readOnly ); + + load(); +} + +const KABC::Addressee &AddresseeEditorWidget::addressee() +{ + return mAddressee; +} + +void AddresseeEditorWidget::textChanged( const QString& ) +{ + emitModified(); +} + +void AddresseeEditorWidget::initGUI() +{ + QVBoxLayout *layout = new QVBoxLayout( this ); + + mTabWidget = new QTabWidget( this ); + layout->addWidget( mTabWidget ); + + setupTab1(); + setupTab2(); + setupAdditionalTabs(); + setupCustomFieldsTabs(); + + connect( mTabWidget, SIGNAL( currentChanged(QWidget*) ), + SLOT( pageChanged(QWidget*) ) ); +} + +void AddresseeEditorWidget::setupTab1() +{ + // This is the General tab + QWidget *tab1 = new QWidget( mTabWidget ); + + QGridLayout *layout = new QGridLayout( tab1, 11, 7 ); + layout->setMargin( KDialogBase::marginHint() ); + layout->setSpacing( KDialogBase::spacingHint() ); + + QLabel *label; + KSeparator* bar; + QPushButton *button; + + ////////////////////////////////// + // Upper left group (person info) + + // Person icon + label = new QLabel( tab1 ); + label->setPixmap( KGlobal::iconLoader()->loadIcon( "personal", KIcon::Desktop, + KIcon::SizeMedium ) ); + layout->addMultiCellWidget( label, 0, 1, 0, 0 ); + + // First name + button = new QPushButton( i18n( "Edit Name..." ), tab1 ); + QToolTip::add( button, i18n( "Edit the contact's name" ) ); + mNameEdit = new KLineEdit( tab1, "mNameEdit" ); + connect( mNameEdit, SIGNAL( textChanged( const QString& ) ), + SLOT( nameTextChanged( const QString& ) ) ); + connect( button, SIGNAL( clicked() ), SLOT( nameButtonClicked() ) ); + mNameLabel = new KSqueezedTextLabel( tab1 ); + + if ( KABPrefs::instance()->automaticNameParsing() ) { + mNameLabel->hide(); + mNameEdit->show(); + } else { + mNameEdit->hide(); + mNameLabel->show(); + } + + layout->addWidget( button, 0, 1 ); + layout->addWidget( mNameEdit, 0, 2 ); + layout->addWidget( mNameLabel, 0, 2 ); + label = new QLabel( i18n( "<roleLabel>:", "%1:" ).arg( KABC::Addressee::roleLabel() ), tab1 ); + mRoleEdit = new KLineEdit( tab1 ); + connect( mRoleEdit, SIGNAL( textChanged( const QString& ) ), + SLOT( textChanged( const QString& ) ) ); + label->setBuddy( mRoleEdit ); + layout->addWidget( label, 1, 1 ); + layout->addWidget( mRoleEdit, 1, 2 ); + + // Organization + label = new QLabel( i18n( "<organizationLabel>:", "%1:" ).arg( KABC::Addressee::organizationLabel() ), tab1 ); + mOrgEdit = new KLineEdit( tab1 ); + label->setBuddy( mOrgEdit ); + connect( mOrgEdit, SIGNAL( textChanged( const QString& ) ), + SLOT( organizationTextChanged( const QString& ) ) ); + layout->addWidget( label, 2, 1 ); + layout->addWidget( mOrgEdit, 2, 2 ); + + // File as (formatted name) + label = new QLabel( i18n( "Formatted name:" ), tab1 ); + mFormattedNameLabel = new KSqueezedTextLabel( tab1 ); + layout->addWidget( label, 3, 1 ); + layout->addWidget( mFormattedNameLabel, 3, 2 ); + + // Left hand separator. This separator doesn't go all the way + // across so the dialog still flows from top to bottom + bar = new KSeparator( KSeparator::HLine, tab1 ); + layout->addMultiCellWidget( bar, 4, 4, 0, 2 ); + + ////////////////////////////////////// + // Phone numbers (upper right) + label = new QLabel( tab1 ); + label->setPixmap( KGlobal::iconLoader()->loadIcon( "kaddressbook", + KIcon::Desktop, KIcon::SizeMedium ) ); + layout->addMultiCellWidget( label, 0, 1, 3, 3 ); + + mPhoneEditWidget = new PhoneEditWidget( tab1 ); + connect( mPhoneEditWidget, SIGNAL( modified() ), SLOT( emitModified() ) ); + layout->addMultiCellWidget( mPhoneEditWidget, 0, 3, 4, 6 ); + + bar = new KSeparator( KSeparator::HLine, tab1 ); + layout->addMultiCellWidget( bar, 4, 4, 3, 6 ); + + ////////////////////////////////////// + // Addresses (lower left) + label = new QLabel( tab1 ); + label->setPixmap( KGlobal::iconLoader()->loadIcon( "kfm_home", KIcon::Desktop, + KIcon::SizeMedium ) ); + layout->addMultiCellWidget( label, 5, 6, 0, 0 ); + + mAddressEditWidget = new AddressEditWidget( tab1 ); + connect( mAddressEditWidget, SIGNAL( modified() ), SLOT( emitModified() ) ); + layout->addMultiCellWidget( mAddressEditWidget, 5, 10, 1, 2 ); + + ////////////////////////////////////// + // Email / Web (lower right) + label = new QLabel( tab1 ); + label->setPixmap( KGlobal::iconLoader()->loadIcon( "email", KIcon::Desktop, + KIcon::SizeMedium ) ); + layout->addMultiCellWidget( label, 5, 6, 3, 3 ); + + mEmailWidget = new EmailEditWidget( tab1 ); + connect( mEmailWidget, SIGNAL( modified() ), SLOT( emitModified() ) ); + layout->addMultiCellWidget( mEmailWidget, 5, 6, 4, 6 ); + + // add the separator + bar = new KSeparator( KSeparator::HLine, tab1 ); + layout->addMultiCellWidget( bar, 7, 7, 3, 6 ); + + QHBoxLayout *homePageLayout = new QHBoxLayout( 0, 11, 7 ); + + label = new QLabel( tab1 ); + label->setPixmap( KGlobal::iconLoader()->loadIcon( "homepage", KIcon::Desktop, + KIcon::SizeMedium ) ); + homePageLayout->addWidget( label ); + + label = new QLabel( i18n( "<urlLabel>:", "%1:" ).arg( KABC::Addressee::urlLabel() ), tab1 ); + mURLEdit = new KLineEdit( tab1 ); + connect( mURLEdit, SIGNAL( textChanged( const QString& ) ), + SLOT( textChanged( const QString& ) ) ); + label->setBuddy( mURLEdit ); + homePageLayout->addWidget( label ); + homePageLayout->addWidget( mURLEdit ); + layout->addMultiCellLayout( homePageLayout, 8, 8, 3, 6 ); + + QHBoxLayout *blogLayout = new QHBoxLayout( 0, 11, 7 ); + label = new QLabel( i18n("Blog feed:"), tab1 ); + blogLayout->addWidget( label ); + mBlogEdit = new KLineEdit( tab1 ); + blogLayout->addWidget( mBlogEdit ); + connect( mBlogEdit, SIGNAL( textChanged( const QString & ) ), + SLOT( textChanged( const QString & ) ) ); + label->setBuddy( mBlogEdit ); + layout->addMultiCellLayout( blogLayout, 9, 9, 4, 6 ); + + mIMWidget = new IMEditWidget( tab1, mAddressee ); + connect( mIMWidget, SIGNAL( modified() ), SLOT( emitModified() ) ); + layout->addMultiCellWidget( mIMWidget, 10, 10, 4, 6 ); + + layout->addColSpacing( 6, 50 ); + + bar = new KSeparator( KSeparator::HLine, tab1 ); + layout->addMultiCellWidget( bar, 11, 11, 0, 6 ); + + /////////////////////////////////////// + QHBox *categoryBox = new QHBox( tab1 ); + categoryBox->setSpacing( KDialogBase::spacingHint() ); + + // Categories + mCategoryButton = new QPushButton( i18n( "Select Categories..." ), categoryBox ); + connect( mCategoryButton, SIGNAL( clicked() ), SLOT( selectCategories() ) ); + + mCategoryEdit = new KLineEdit( categoryBox ); + mCategoryEdit->setReadOnly( true ); + connect( mCategoryEdit, SIGNAL( textChanged( const QString& ) ), + SLOT( textChanged( const QString& ) ) ); + + mSecrecyWidget = new SecrecyWidget( categoryBox ); + connect( mSecrecyWidget, SIGNAL( changed() ), SLOT( emitModified() ) ); + + layout->addMultiCellWidget( categoryBox, 12, 12, 0, 6 ); + + // Build the layout and add to the tab widget + layout->activate(); // required + + mTabWidget->addTab( tab1, i18n( "&General" ) ); +} + +void AddresseeEditorWidget::setupTab2() +{ + // This is the Details tab + QWidget *tab2 = new QWidget( mTabWidget ); + + QGridLayout *layout = new QGridLayout( tab2, 6, 6 ); + layout->setMargin( KDialogBase::marginHint() ); + layout->setSpacing( KDialogBase::spacingHint() ); + + QLabel *label; + KSeparator* bar; + + /////////////////////// + // Office info + + // Department + label = new QLabel( tab2 ); + label->setPixmap( KGlobal::iconLoader()->loadIcon( "folder", KIcon::Desktop, + KIcon::SizeMedium ) ); + layout->addMultiCellWidget( label, 0, 1, 0, 0 ); + + label = new QLabel( i18n( "Department:" ), tab2 ); + layout->addWidget( label, 0, 1 ); + mDepartmentEdit = new KLineEdit( tab2 ); + connect( mDepartmentEdit, SIGNAL( textChanged( const QString& ) ), + SLOT( textChanged( const QString& ) ) ); + label->setBuddy( mDepartmentEdit ); + layout->addWidget( mDepartmentEdit, 0, 2 ); + + label = new QLabel( i18n( "Office:" ), tab2 ); + layout->addWidget( label, 1, 1 ); + mOfficeEdit = new KLineEdit( tab2 ); + connect( mOfficeEdit, SIGNAL( textChanged( const QString& ) ), + SLOT( textChanged( const QString& ) ) ); + label->setBuddy( mOfficeEdit ); + layout->addWidget( mOfficeEdit, 1, 2 ); + + label = new QLabel( i18n( "Profession:" ), tab2 ); + layout->addWidget( label, 2, 1 ); + mProfessionEdit = new KLineEdit( tab2 ); + connect( mProfessionEdit, SIGNAL( textChanged( const QString& ) ), + SLOT( textChanged( const QString& ) ) ); + label->setBuddy( mProfessionEdit ); + layout->addWidget( mProfessionEdit, 2, 2 ); + + label = new QLabel( i18n( "Manager\'s name:" ), tab2 ); + layout->addWidget( label, 0, 3 ); + mManagerEdit = new KPIM::AddresseeLineEdit( tab2 ); + connect( mManagerEdit, SIGNAL( textChanged( const QString& ) ), + SLOT( textChanged( const QString& ) ) ); + label->setBuddy( mManagerEdit ); + layout->addMultiCellWidget( mManagerEdit, 0, 0, 4, 5 ); + + label = new QLabel( i18n( "Assistant's name:" ), tab2 ); + layout->addWidget( label, 1, 3 ); + mAssistantEdit = new KPIM::AddresseeLineEdit( tab2 ); + connect( mAssistantEdit, SIGNAL( textChanged( const QString& ) ), + SLOT( textChanged( const QString& ) ) ); + label->setBuddy( mAssistantEdit ); + layout->addMultiCellWidget( mAssistantEdit, 1, 1, 4, 5 ); + + label = new QLabel( i18n( "<titleLabel>:", "%1:" ).arg( KABC::Addressee::titleLabel() ), tab2 ); + layout->addWidget( label, 2, 3 ); + mTitleEdit = new KLineEdit( tab2 ); + connect( mTitleEdit, SIGNAL( textChanged( const QString& ) ), + SLOT( textChanged( const QString& ) ) ); + label->setBuddy( mTitleEdit ); + layout->addMultiCellWidget( mTitleEdit, 2, 2, 4, 5 ); + + bar = new KSeparator( KSeparator::HLine, tab2 ); + layout->addMultiCellWidget( bar, 3, 3, 0, 5 ); + + ///////////////////////////////////////////////// + // Personal info + + label = new QLabel( tab2 ); + label->setPixmap( KGlobal::iconLoader()->loadIcon( "personal", KIcon::Desktop, + KIcon::SizeMedium ) ); + layout->addMultiCellWidget( label, 4, 5, 0, 0 ); + + label = new QLabel( i18n( "Nickname:" ), tab2 ); + layout->addWidget( label, 4, 1 ); + mNicknameEdit = new KLineEdit( tab2 ); + connect( mNicknameEdit, SIGNAL( textChanged( const QString& ) ), + SLOT( textChanged( const QString& ) ) ); + label->setBuddy( mNicknameEdit ); + layout->addWidget( mNicknameEdit, 4, 2 ); + + label = new QLabel( i18n( "Partner's name:" ), tab2 ); + layout->addWidget( label, 5, 1 ); + mSpouseEdit = new KPIM::AddresseeLineEdit( tab2 ); + connect( mSpouseEdit, SIGNAL( textChanged( const QString& ) ), + SLOT( textChanged( const QString& ) ) ); + label->setBuddy( mSpouseEdit ); + layout->addWidget( mSpouseEdit, 5, 2 ); + + label = new QLabel( i18n( "Birthdate:" ), tab2 ); + layout->addWidget( label, 4, 3 ); + mBirthdayPicker = new KDateEdit( tab2 ); + connect( mBirthdayPicker, SIGNAL( dateChanged( const QDate& ) ), + SLOT( dateChanged( const QDate& ) ) ); + connect( mBirthdayPicker, SIGNAL( textChanged( const QString& ) ), + SLOT( emitModified() ) ); + label->setBuddy( mBirthdayPicker ); + layout->addWidget( mBirthdayPicker, 4, 4 ); + + label = new QLabel( i18n( "Anniversary:" ), tab2 ); + layout->addWidget( label, 5, 3 ); + mAnniversaryPicker = new KDateEdit( tab2 ); + connect( mAnniversaryPicker, SIGNAL( dateChanged( const QDate& ) ), + SLOT( dateChanged( const QDate& ) ) ); + connect( mAnniversaryPicker, SIGNAL( textChanged( const QString& ) ), + SLOT( emitModified() ) ); + label->setBuddy( mAnniversaryPicker ); + layout->addWidget( mAnniversaryPicker, 5, 4 ); + + bar = new KSeparator( KSeparator::HLine, tab2 ); + layout->addMultiCellWidget( bar, 6, 6, 0, 5 ); + + ////////////////////////////////////// + // Notes + label = new QLabel( i18n( "Note:" ), tab2 ); + label->setAlignment( Qt::AlignTop | Qt::AlignLeft ); + layout->addWidget( label, 7, 0 ); + mNoteEdit = new QTextEdit( tab2 ); + mNoteEdit->setWordWrap( QTextEdit::WidgetWidth ); + mNoteEdit->setMinimumSize( mNoteEdit->sizeHint() ); + connect( mNoteEdit, SIGNAL( textChanged() ), SLOT( emitModified() ) ); + label->setBuddy( mNoteEdit ); + layout->addMultiCellWidget( mNoteEdit, 7, 7, 1, 5 ); + + // Build the layout and add to the tab widget + layout->activate(); // required + + mTabWidget->addTab( tab2, i18n( "&Details" ) ); +} + +void AddresseeEditorWidget::setupAdditionalTabs() +{ + ContactEditorWidgetManager *manager = ContactEditorWidgetManager::self(); + + // create all tab pages and add the widgets + for ( int i = 0; i < manager->count(); ++i ) { + QString pageIdentifier = manager->factory( i )->pageIdentifier(); + QString pageTitle = manager->factory( i )->pageTitle(); + + if ( pageIdentifier == "misc" ) + pageTitle = i18n( "Misc" ); + + ContactEditorTabPage *page = mTabPages[ pageIdentifier ]; + if ( page == 0 ) { // tab not yet available, create one + page = new ContactEditorTabPage( mTabWidget ); + mTabPages.insert( pageIdentifier, page ); + + mTabWidget->addTab( page, pageTitle ); + + connect( page, SIGNAL( changed() ), SLOT( emitModified() ) ); + } + + KAB::ContactEditorWidget *widget + = manager->factory( i )->createWidget( KABC::StdAddressBook::self( true ), + page ); + if ( widget ) + page->addWidget( widget ); + } + + // query the layout update + QDictIterator<ContactEditorTabPage> it( mTabPages ); + for ( ; it.current(); ++it ) + it.current()->updateLayout(); +} + +void AddresseeEditorWidget::setupCustomFieldsTabs() +{ + QStringList activePages = KABPrefs::instance()->advancedCustomFields(); + + const QStringList list = KGlobal::dirs()->findAllResources( "data", "kaddressbook/contacteditorpages/*.ui", true, true ); + for ( QStringList::ConstIterator it = list.begin(); it != list.end(); ++it ) { + if ( activePages.find( (*it).mid( (*it).findRev('/') + 1 ) ) == activePages.end() ) + continue; + + ContactEditorTabPage *page = new ContactEditorTabPage( mTabWidget ); + AdvancedCustomFields *wdg = new AdvancedCustomFields( *it, KABC::StdAddressBook::self( true ), page ); + if ( wdg ) { + mTabPages.insert( wdg->pageIdentifier(), page ); + mTabWidget->addTab( page, wdg->pageTitle() ); + + page->addWidget( wdg ); + page->updateLayout(); + + connect( page, SIGNAL( changed() ), SLOT( emitModified() ) ); + } else + delete page; + } +} + +void AddresseeEditorWidget::load() +{ + kdDebug(5720) << "AddresseeEditorWidget::load()" << endl; + + // Block signals in case anything tries to emit modified + // CS: This doesn't seem to work. + bool block = signalsBlocked(); + blockSignals( true ); + mBlockSignals = true; // used for internal signal blocking + + mNameEdit->blockSignals( true ); + mNameEdit->setText( mAddressee.assembledName() ); + mNameEdit->blockSignals( false ); + + if ( mAddressee.formattedName().isEmpty() ) { + KConfig config( "kaddressbookrc" ); + config.setGroup( "General" ); + mFormattedNameType = config.readNumEntry( "FormattedNameType", 1 ); + mAddressee.setFormattedName( NameEditDialog::formattedName( mAddressee, mFormattedNameType ) ); + } else { + if ( mAddressee.formattedName() == NameEditDialog::formattedName( mAddressee, NameEditDialog::SimpleName ) ) + mFormattedNameType = NameEditDialog::SimpleName; + else if ( mAddressee.formattedName() == NameEditDialog::formattedName( mAddressee, NameEditDialog::FullName ) ) + mFormattedNameType = NameEditDialog::FullName; + else if ( mAddressee.formattedName() == NameEditDialog::formattedName( mAddressee, NameEditDialog::ReverseNameWithComma ) ) + mFormattedNameType = NameEditDialog::ReverseNameWithComma; + else if ( mAddressee.formattedName() == NameEditDialog::formattedName( mAddressee, NameEditDialog::ReverseName ) ) + mFormattedNameType = NameEditDialog::ReverseName; + else if ( mAddressee.formattedName() == NameEditDialog::formattedName( mAddressee, NameEditDialog::Organization ) ) + mFormattedNameType = NameEditDialog::Organization; + else + mFormattedNameType = NameEditDialog::CustomName; + } + + mFormattedNameLabel->setText( mAddressee.formattedName() ); + + mRoleEdit->setText( mAddressee.role() ); + mOrgEdit->setText( mAddressee.organization() ); +#if KDE_IS_VERSION(3,5,8) + mDepartmentEdit->setText( mAddressee.department() ); + // compatibility with older versions + if ( mAddressee.department().isEmpty() ) +#endif + mDepartmentEdit->setText( mAddressee.custom( "KADDRESSBOOK", "X-Department" ) ); + mURLEdit->setURL( mAddressee.url() ); + mURLEdit->home( false ); + mBlogEdit->setURL( mAddressee.custom( "KADDRESSBOOK", "BlogFeed" ) ); + mNoteEdit->setText( mAddressee.note() ); + mEmailWidget->setEmails( mAddressee.emails() ); + mPhoneEditWidget->setPhoneNumbers( mAddressee.phoneNumbers() ); + mAddressEditWidget->setAddresses( mAddressee, mAddressee.addresses() ); + mBirthdayPicker->setDate( mAddressee.birthday().date() ); + + QString anniversaryStr = mAddressee.custom( "KADDRESSBOOK", "X-Anniversary" ); + QDate anniversary = (anniversaryStr.isEmpty() ? QDate() : QDate::fromString( anniversaryStr, Qt::ISODate )); + mAnniversaryPicker->setDate( anniversary ); + mNicknameEdit->setText( mAddressee.nickName() ); + mCategoryEdit->setText( mAddressee.categories().join( "," ) ); + + mSecrecyWidget->setSecrecy( mAddressee.secrecy() ); + + // Load customs + mIMWidget->setPreferredIM( mAddressee.custom( "KADDRESSBOOK", "X-IMAddress" ) ); + mSpouseEdit->setText( mAddressee.custom( "KADDRESSBOOK", "X-SpousesName" ) ); + mManagerEdit->setText( mAddressee.custom( "KADDRESSBOOK", "X-ManagersName" ) ); + mAssistantEdit->setText( mAddressee.custom( "KADDRESSBOOK", "X-AssistantsName" ) ); + mOfficeEdit->setText( mAddressee.custom( "KADDRESSBOOK", "X-Office" ) ); + mProfessionEdit->setText( mAddressee.custom( "KADDRESSBOOK", "X-Profession" ) ); + mTitleEdit->setText( mAddressee.title() ); + + QDictIterator<ContactEditorTabPage> it( mTabPages ); + for ( ; it.current(); ++it ) + it.current()->loadContact( &mAddressee ); + + blockSignals( block ); + mBlockSignals = false; + + mDirty = false; +} + +void AddresseeEditorWidget::save() +{ + if ( !mDirty ) return; + + mAddressee.setRole( mRoleEdit->text() ); + mAddressee.setOrganization( mOrgEdit->text() ); +#if KDE_IS_VERSION(3,5,8) + mAddressee.setDepartment( mDepartmentEdit->text() ); +#else + if ( !mDepartmentEdit->text().isEmpty() ) + mAddressee.insertCustom( "KADDRESSBOOK", "X-Department", mDepartmentEdit->text() ); + else + mAddressee.removeCustom( "KADDRESSBOOK", "X-Department" ); +#endif + + QString homepage = mURLEdit->text().stripWhiteSpace(); + if ( homepage.isEmpty() ) + mAddressee.setUrl( KURL() ); + else { + if( !homepage.startsWith("http") ) + homepage = "http://" + homepage; + mAddressee.setUrl( KURL( homepage ) ); + } + if ( !mBlogEdit->text().isEmpty() ) + mAddressee.insertCustom( "KADDRESSBOOK", "BlogFeed", mBlogEdit->text() ); + else + mAddressee.removeCustom( "KADDRESSBOOK", "BlogFeed" ); + + mAddressee.setNote( mNoteEdit->text() ); + if ( mBirthdayPicker->date().isValid() ) + mAddressee.setBirthday( QDateTime( mBirthdayPicker->date() ) ); + else + mAddressee.setBirthday( QDateTime() ); + + mAddressee.setNickName( mNicknameEdit->text() ); + mAddressee.setCategories( QStringList::split( ",", mCategoryEdit->text() ) ); + + mAddressee.setSecrecy( mSecrecyWidget->secrecy() ); + + // save custom fields + if ( !mIMWidget->preferredIM().isEmpty() ) + mAddressee.insertCustom( "KADDRESSBOOK", "X-IMAddress", mIMWidget->preferredIM() ); + else + mAddressee.removeCustom( "KADDRESSBOOK", "X-IMAddress" ); + if ( !mSpouseEdit->text().isEmpty() ) + mAddressee.insertCustom( "KADDRESSBOOK", "X-SpousesName", mSpouseEdit->text() ); + else + mAddressee.removeCustom( "KADDRESSBOOK", "X-SpousesName" ); + if ( !mManagerEdit->text().isEmpty() ) + mAddressee.insertCustom( "KADDRESSBOOK", "X-ManagersName", mManagerEdit->text() ); + else + mAddressee.removeCustom( "KADDRESSBOOK", "X-ManagersName" ); + if ( !mAssistantEdit->text().isEmpty() ) + mAddressee.insertCustom( "KADDRESSBOOK", "X-AssistantsName", mAssistantEdit->text() ); + else + mAddressee.removeCustom( "KADDRESSBOOK", "X-AssistantsName" ); + + if ( !mOfficeEdit->text().isEmpty() ) + mAddressee.insertCustom( "KADDRESSBOOK", "X-Office", mOfficeEdit->text() ); + else + mAddressee.removeCustom( "KADDRESSBOOK", "X-Office" ); + if ( !mProfessionEdit->text().isEmpty() ) + mAddressee.insertCustom( "KADDRESSBOOK", "X-Profession", mProfessionEdit->text() ); + else + mAddressee.removeCustom( "KADDRESSBOOK", "X-Profession" ); + + if ( mAnniversaryPicker->date().isValid() ) + mAddressee.insertCustom( "KADDRESSBOOK", "X-Anniversary", + mAnniversaryPicker->date().toString( Qt::ISODate ) ); + else + mAddressee.removeCustom( "KADDRESSBOOK", "X-Anniversary" ); + + mAddressee.setTitle( mTitleEdit->text() ); + + // Save the email addresses + mAddressee.setEmails( mEmailWidget->emails() ); + + // Save the phone numbers + KABC::PhoneNumber::List phoneNumbers; + KABC::PhoneNumber::List::ConstIterator phoneIter; + phoneNumbers = mAddressee.phoneNumbers(); + for ( phoneIter = phoneNumbers.begin(); phoneIter != phoneNumbers.end(); + ++phoneIter ) + mAddressee.removePhoneNumber( *phoneIter ); + + phoneNumbers = mPhoneEditWidget->phoneNumbers(); + for ( phoneIter = phoneNumbers.begin(); phoneIter != phoneNumbers.end(); + ++phoneIter ) + mAddressee.insertPhoneNumber( *phoneIter ); + + // Save the addresses + KABC::Address::List addresses; + KABC::Address::List::ConstIterator addressIter; + addresses = mAddressee.addresses(); + for ( addressIter = addresses.begin(); addressIter != addresses.end(); + ++addressIter ) + mAddressee.removeAddress( *addressIter ); + + addresses = mAddressEditWidget->addresses(); + for ( addressIter = addresses.begin(); addressIter != addresses.end(); + ++addressIter ) + mAddressee.insertAddress( *addressIter ); + + QDictIterator<ContactEditorTabPage> it( mTabPages ); + for ( ; it.current(); ++it ) + it.current()->storeContact( &mAddressee ); + + mDirty = false; +} + +bool AddresseeEditorWidget::dirty() +{ + return mDirty; +} + +void AddresseeEditorWidget::nameTextChanged( const QString &text ) +{ + // use the addressee class to parse the name for us + AddresseeConfig config( mAddressee ); + if ( config.automaticNameParsing() ) { + if ( !mAddressee.formattedName().isEmpty() ) { + QString fn = mAddressee.formattedName(); + mAddressee.setNameFromString( text ); + mAddressee.setFormattedName( fn ); + } else { + // use extra addressee to avoid a formatted name assignment + Addressee addr; + addr.setNameFromString( text ); + mAddressee.setPrefix( addr.prefix() ); + mAddressee.setGivenName( addr.givenName() ); + mAddressee.setAdditionalName( addr.additionalName() ); + mAddressee.setFamilyName( addr.familyName() ); + mAddressee.setSuffix( addr.suffix() ); + } + } + + nameBoxChanged(); + + emitModified(); +} + +void AddresseeEditorWidget::organizationTextChanged( const QString &text ) +{ + + AddresseeConfig config( mAddressee ); + if ( config.automaticNameParsing() ) + mAddressee.setOrganization( text ); + + nameBoxChanged(); + + mAddressEditWidget->updateAddressee( mAddressee ); + + emitModified(); +} + +void AddresseeEditorWidget::nameBoxChanged() +{ + KABC::Addressee addr; + AddresseeConfig config( mAddressee ); + if ( config.automaticNameParsing() ) { + addr.setNameFromString( mNameEdit->text() ); + mNameLabel->hide(); + mNameEdit->show(); + } else { + addr = mAddressee; + mNameEdit->hide(); + mNameLabel->setText( mNameEdit->text() ); + mNameLabel->show(); + } + + if ( mFormattedNameType != NameEditDialog::CustomName ) { + mFormattedNameLabel->setText( NameEditDialog::formattedName( mAddressee, mFormattedNameType ) ); + mAddressee.setFormattedName( NameEditDialog::formattedName( mAddressee, mFormattedNameType ) ); + } + + mAddressEditWidget->updateAddressee( mAddressee ); +} + +void AddresseeEditorWidget::nameButtonClicked() +{ + // show the name dialog. + NameEditDialog dialog( mAddressee, mFormattedNameType, mReadOnly, this ); + + if ( dialog.exec() ) { + if ( dialog.changed() ) { + mAddressee.setFamilyName( dialog.familyName() ); + mAddressee.setGivenName( dialog.givenName() ); + mAddressee.setPrefix( dialog.prefix() ); + mAddressee.setSuffix( dialog.suffix() ); + mAddressee.setAdditionalName( dialog.additionalName() ); + mFormattedNameType = dialog.formattedNameType(); + if ( mFormattedNameType == NameEditDialog::CustomName ) { + mFormattedNameLabel->setText( dialog.customFormattedName() ); + mAddressee.setFormattedName( dialog.customFormattedName() ); + } + // Update the name edit. + bool block = mNameEdit->signalsBlocked(); + mNameEdit->blockSignals( true ); + mNameEdit->setText( mAddressee.assembledName() ); + mNameEdit->blockSignals( block ); + + // Update the combo box. + nameBoxChanged(); + + emitModified(); + } + } +} + +void AddresseeEditorWidget::selectCategories() +{ + // Show the category dialog + if ( mCategorySelectDialog == 0 ) { + mCategorySelectDialog = new KPIM::CategorySelectDialog( KABPrefs::instance(), this ); + connect( mCategorySelectDialog, SIGNAL( categoriesSelected( const QStringList& ) ), + this, SLOT( categoriesSelected( const QStringList& ) ) ); + connect( mCategorySelectDialog, SIGNAL( editCategories() ), + this, SLOT( editCategories() ) ); + } + + mCategorySelectDialog->setSelected( QStringList::split( ",", mCategoryEdit->text() ) ); + mCategorySelectDialog->exec(); +} + +void AddresseeEditorWidget::categoriesSelected( const QStringList &list ) +{ + mCategoryEdit->setText( list.join( "," ) ); +} + +void AddresseeEditorWidget::editCategories() +{ + if ( mCategoryEditDialog == 0 ) { + mCategoryEditDialog = new KPIM::CategoryEditDialog( KABPrefs::instance(), this ); + connect( mCategoryEditDialog, SIGNAL( categoryConfigChanged() ), + mCategorySelectDialog, SLOT( updateCategoryConfig() ) ); + } + + mCategoryEditDialog->exec(); +} + +void AddresseeEditorWidget::emitModified() +{ + if ( mBlockSignals ) + return; + + mDirty = true; + + emit modified(); +} + +void AddresseeEditorWidget::dateChanged( const QDate& ) +{ + emitModified(); +} + +void AddresseeEditorWidget::invalidDate() +{ + KMessageBox::sorry( this, i18n( "You must specify a valid date" ) ); +} + +void AddresseeEditorWidget::pageChanged( QWidget *wdg ) +{ + if ( wdg ) + KAcceleratorManager::manage( wdg ); +} + +void AddresseeEditorWidget::setInitialFocus() +{ + mNameEdit->setFocus(); +} + +bool AddresseeEditorWidget::readyToClose() +{ + bool ok = true; + + QDate date = mBirthdayPicker->date(); + if ( !date.isValid() && !mBirthdayPicker->currentText().isEmpty() ) { + KMessageBox::error( this, i18n( "You have to enter a valid birthdate." ) ); + ok = false; + } + + date = mAnniversaryPicker->date(); + if ( !date.isValid() && !mAnniversaryPicker->currentText().isEmpty() ) { + KMessageBox::error( this, i18n( "You have to enter a valid anniversary." ) ); + ok = false; + } + + return ok; +} + +void AddresseeEditorWidget::setReadOnly( bool readOnly ) +{ + mReadOnly = readOnly; + + mNameEdit->setReadOnly( readOnly ); + mRoleEdit->setReadOnly( readOnly ); + mOrgEdit->setReadOnly( readOnly ); + mPhoneEditWidget->setReadOnly( readOnly ); + mAddressEditWidget->setReadOnly( readOnly ); + mEmailWidget->setReadOnly( readOnly ); + mURLEdit->setReadOnly( readOnly ); + mBlogEdit->setReadOnly( readOnly ); + mIMWidget->setReadOnly( readOnly ); + mCategoryButton->setEnabled( !readOnly ); + mSecrecyWidget->setReadOnly( readOnly ); + mDepartmentEdit->setReadOnly( readOnly ); + mOfficeEdit->setReadOnly( readOnly ); + mProfessionEdit->setReadOnly( readOnly ); + mManagerEdit->setReadOnly( readOnly ); + mAssistantEdit->setReadOnly( readOnly ); + mTitleEdit->setReadOnly( readOnly ); + mNicknameEdit->setReadOnly( readOnly ); + mSpouseEdit->setReadOnly( readOnly ); + mBirthdayPicker->setEnabled( !readOnly ); + mAnniversaryPicker->setEnabled( !readOnly ); + mNoteEdit->setReadOnly( mReadOnly ); + + QDictIterator<ContactEditorTabPage> it( mTabPages ); + for ( ; it.current(); ++it ) + it.current()->setReadOnly( readOnly ); +} + +#include "addresseeeditorwidget.moc" diff --git a/kaddressbook/addresseeeditorwidget.h b/kaddressbook/addresseeeditorwidget.h new file mode 100644 index 000000000..93917245b --- /dev/null +++ b/kaddressbook/addresseeeditorwidget.h @@ -0,0 +1,167 @@ +/* + This file is part of KAddressBook. + Copyright (c) 2002 Mike Pilone <mpilone@slac.com> + + 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 ADDRESSEEEDITORWIDGET_H +#define ADDRESSEEEDITORWIDGET_H + +#include <qdatetime.h> + +#include <kabc/addressee.h> +#include <kdialogbase.h> +#include <kjanuswidget.h> + +#include "addresseeeditorbase.h" +#include "contacteditorwidgetmanager.h" +#include "extensionwidget.h" + +class QCheckBox; +class QSpinBox; +class QTabWidget; +class QTextEdit; + +class KComboBox; +class KDateEdit; +class KLineEdit; +class KSqueezedTextLabel; + +class AddressEditWidget; +class EmailEditWidget; +class IMEditWidget; +class KeyWidget; +class PhoneEditWidget; +class SecrecyWidget; + +namespace KAB { +class Core; +} + +namespace KPIM { +class AddresseeLineEdit; +class CategorySelectDialog; +class CategoryEditDialog; +} + +namespace KABC { class AddressBook; } + +class AddresseeEditorWidget : public AddresseeEditorBase +{ + Q_OBJECT + + public: + AddresseeEditorWidget( QWidget *parent, const char *name = 0 ); + ~AddresseeEditorWidget(); + + void setAddressee( const KABC::Addressee& ); + const KABC::Addressee &addressee(); + + void load(); + void save(); + + bool dirty(); + + void setInitialFocus(); + + bool readyToClose(); + + protected slots: + void textChanged( const QString& ); + void pageChanged( QWidget *wdg ); + + /** + Emits the modified signal and sets the dirty flag. Any slot + that modifies data should use this method instead of calling emit + modified() directly. + */ + void emitModified(); + + void dateChanged( const QDate& ); + void invalidDate(); + void nameTextChanged( const QString& ); + void organizationTextChanged( const QString& ); + void nameBoxChanged(); + void nameButtonClicked(); + void selectCategories(); + + /** + Called whenever the categories change in the categories dialog. + */ + void categoriesSelected( const QStringList& ); + + /** + Edits which categories are available in the CategorySelectDialog. + */ + void editCategories(); + + private: + void initGUI(); + void setupTab1(); + void setupTab2(); + void setupAdditionalTabs(); + void setupCustomFieldsTabs(); + + void setReadOnly( bool ); + + KABC::Addressee mAddressee; + int mFormattedNameType; + bool mDirty; + bool mBlockSignals; + bool mReadOnly; + + // GUI + KPIM::CategorySelectDialog *mCategorySelectDialog; + KPIM::CategoryEditDialog *mCategoryEditDialog; + QTabWidget *mTabWidget; + + // Tab1 + KLineEdit *mNameEdit; + KLineEdit *mRoleEdit; + KLineEdit *mOrgEdit; + KSqueezedTextLabel *mFormattedNameLabel; + AddressEditWidget *mAddressEditWidget; + EmailEditWidget *mEmailWidget; + IMEditWidget *mIMWidget; + PhoneEditWidget *mPhoneEditWidget; + KLineEdit *mURLEdit; + KLineEdit *mBlogEdit; + QPushButton *mCategoryButton; + KLineEdit *mCategoryEdit; + SecrecyWidget *mSecrecyWidget; + KSqueezedTextLabel *mNameLabel; + + // Tab2 + KLineEdit *mDepartmentEdit; + KLineEdit *mOfficeEdit; + KLineEdit *mProfessionEdit; + KLineEdit *mTitleEdit; + KPIM::AddresseeLineEdit *mManagerEdit; + KPIM::AddresseeLineEdit *mAssistantEdit; + KLineEdit *mNicknameEdit; + KPIM::AddresseeLineEdit *mSpouseEdit; + KDateEdit *mBirthdayPicker; + KDateEdit *mAnniversaryPicker; + QTextEdit *mNoteEdit; + + QDict<ContactEditorTabPage> mTabPages; +}; + +#endif diff --git a/kaddressbook/addresseeutil.cpp b/kaddressbook/addresseeutil.cpp new file mode 100644 index 000000000..e84cfea09 --- /dev/null +++ b/kaddressbook/addresseeutil.cpp @@ -0,0 +1,55 @@ +/* + This file is part of KAddressBook. + Copyright (c) 2002 Mike Pilone <mpilone@slac.com> + + 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 <kabc/stdaddressbook.h> +#include <kabc/vcardconverter.h> +#include <kdebug.h> +#include <klocale.h> +#include <kmessagebox.h> + +#include "addresseeutil.h" + +QString AddresseeUtil::addresseesToClipboard( const KABC::Addressee::List &list ) +{ + KABC::VCardConverter converter; + + return converter.createVCards( list ); +} + +KABC::Addressee::List AddresseeUtil::clipboardToAddressees( const QString &data ) +{ + KABC::VCardConverter converter; + + return converter.parseVCards( data ); +} + +QString AddresseeUtil::addresseesToEmails( const KABC::Addressee::List &addrList ) +{ + QStringList emails; + + KABC::Addressee::List::ConstIterator it; + for ( it = addrList.begin(); it != addrList.end(); ++it ) + emails.append( (*it).fullEmail() ); + + return emails.join( "," ); +} diff --git a/kaddressbook/addresseeutil.h b/kaddressbook/addresseeutil.h new file mode 100644 index 000000000..1b67fcf35 --- /dev/null +++ b/kaddressbook/addresseeutil.h @@ -0,0 +1,66 @@ +/* + This file is part of KAddressBook. + Copyright (c) 2002 Mike Pilone <mpilone@slac.com> + + 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 ADDRESSEEUTIL_H +#define ADDRESSEEUTIL_H + +#include <qstring.h> +#include <kabc/addressee.h> + +/** + This class provides some utility methods for transposing an + addressee to different types (ie: clipboard). This class + is probably just temporary until these function stablize and move + to KABC. + + NOTE: Currently these methods are not implemented properly. The + vCard parser in KABC needs to be updated and there is no way to get from + KABC::Addressee to vCard. +*/ +class AddresseeUtil +{ + public: + /** + Same as above function, except that an entire list of KABC::Addressee + objects will be converted to vCard and put in the string. + */ + static QString addresseesToClipboard( const KABC::Addressee::List &addrList ); + + /** + Convert a string from the clipboard into a list of addressee objects. + If the clipboard text was not a valid vcard, an empty list + will be returned. + */ + static KABC::Addressee::List clipboardToAddressees( const QString &clipboard ); + + /** + Converts the list of addressee objects into a list of email addresses. + */ + static QString addresseesToEmails( const KABC::Addressee::List &addrList ); + + private: + AddresseeUtil() {} + ~AddresseeUtil() {} +}; + +#endif diff --git a/kaddressbook/addviewdialog.cpp b/kaddressbook/addviewdialog.cpp new file mode 100644 index 000000000..68046359d --- /dev/null +++ b/kaddressbook/addviewdialog.cpp @@ -0,0 +1,110 @@ +/* + This file is part of KAddressBook. + Copyright (c) 2002 Mike Pilone <mpilone@slac.com> + + 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 <qbuttongroup.h> +#include <qlabel.h> +#include <qlayout.h> +#include <qlineedit.h> +#include <qradiobutton.h> + +#include <klocale.h> + +#include "kaddressbookview.h" + +#include "addviewdialog.h" + +AddViewDialog::AddViewDialog( QDict<ViewFactory> *viewFactoryDict, + QWidget *parent, const char *name ) + : KDialogBase( KDialogBase::Plain, i18n( "Add View" ), + KDialogBase::Ok | KDialogBase::Cancel, KDialogBase::Ok, + parent, name ), + mViewFactoryDict( viewFactoryDict ) +{ + mTypeId = 0; + + QWidget *page = plainPage(); + + QGridLayout *layout = new QGridLayout( page, 2, 2 ); + layout->setSpacing( spacingHint() ); + layout->setRowStretch( 1, 1 ); + layout->setColStretch( 1, 1 ); + + QLabel *label = new QLabel( i18n( "View name:" ), page ); + layout->addWidget( label, 0, 0 ); + + mViewNameEdit = new QLineEdit( page ); + connect( mViewNameEdit, SIGNAL( textChanged( const QString& ) ), + SLOT( textChanged( const QString& ) ) ); + layout->addWidget( mViewNameEdit, 0, 1 ); + + mTypeGroup = new QButtonGroup( 0, Qt::Horizontal, i18n( "View Type" ), page ); + connect( mTypeGroup, SIGNAL( clicked( int ) ), this, SLOT( clicked( int ) ) ); + layout->addMultiCellWidget( mTypeGroup, 1, 1, 0, 1 ); + QGridLayout *groupLayout = new QGridLayout( mTypeGroup->layout(), 3, 2 ); + groupLayout->setSpacing( spacingHint() ); + + int row = 0; + QDictIterator<ViewFactory> iter( *mViewFactoryDict ); + for ( iter.toFirst(); iter.current(); ++iter ) { + QRadioButton *button = new QRadioButton( i18n((*iter)->type().utf8()), + mTypeGroup, (*iter)->type().latin1() ); + label = new QLabel( (*iter)->description(), mTypeGroup ); + label->setAlignment( Qt::WordBreak ); + + groupLayout->addWidget( button, row, 0, Qt::AlignTop ); + groupLayout->addWidget( label, row, 1, Qt::AlignTop ); + + row++; + } + + mTypeGroup->setButton( 0 ); + mViewNameEdit->setFocus(); + enableButton( KDialogBase::Ok, false ); +} + +AddViewDialog::~AddViewDialog() +{ +} + +QString AddViewDialog::viewName()const +{ + return mViewNameEdit->text(); +} + +QString AddViewDialog::viewType()const +{ + // we missuse the name property for storing the type + return mTypeGroup->find( mTypeId )->name(); +} + +void AddViewDialog::clicked( int id ) +{ + mTypeId = id; +} + +void AddViewDialog::textChanged( const QString &text ) +{ + enableButton( KDialogBase::Ok, !text.isEmpty() ); +} + +#include "addviewdialog.moc" diff --git a/kaddressbook/addviewdialog.h b/kaddressbook/addviewdialog.h new file mode 100644 index 000000000..972f6ef3a --- /dev/null +++ b/kaddressbook/addviewdialog.h @@ -0,0 +1,73 @@ +/* + This file is part of KAddressBook. + Copyright (c) 2002 Mike Pilone <mpilone@slac.com> + + 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 ADDVIEWDIALOG_H +#define ADDVIEWDIALOG_H + +#include <kdialogbase.h> +#include <qdict.h> +#include <qstring.h> + +class QButtonGroup; +class QLineEdit; +class ViewFactory; + + +/** + Modal dialog used for adding a new view. The dialog asks for the name of + the view as well as the type. Someday it would be nice for this to be a + wizard. + */ +class AddViewDialog : public KDialogBase +{ + Q_OBJECT + + public: + AddViewDialog( QDict<ViewFactory> *viewFactoryDict, QWidget *parent, + const char *name = 0 ); + ~AddViewDialog(); + + QString viewName()const; + + QString viewType()const ; + + protected slots: + /** + Called when the user selects a type radio button. + */ + void clicked( int id ); + + /** + Called when the user changes the text in the name of the view. + */ + void textChanged( const QString &text ); + + private: + QDict<ViewFactory> *mViewFactoryDict; + QLineEdit *mViewNameEdit; + QButtonGroup *mTypeGroup; + + int mTypeId; +}; + +#endif diff --git a/kaddressbook/advancedcustomfields.cpp b/kaddressbook/advancedcustomfields.cpp new file mode 100644 index 000000000..ad630835f --- /dev/null +++ b/kaddressbook/advancedcustomfields.cpp @@ -0,0 +1,148 @@ +/* + This file is part of KAddressbook. + + Copyright (c) 2004 Tobias Koenig <tokoe@kde.org> + Copyright (c) 2004 Cornelius Schumacher <schumacher@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 <qcombobox.h> +#include <qdatetimeedit.h> +#include <qlayout.h> +#include <qobjectlist.h> +#include <qspinbox.h> +#include <qregexp.h> +#include <qtextedit.h> +#include <qwidgetfactory.h> + +#include <kdatepicker.h> +#include <kdatetimewidget.h> +#include <kdialog.h> +#include <klineedit.h> +#include <kstandarddirs.h> + +#include <libkdepim/designerfields.h> + +#include "customfieldswidget.h" + +#include "advancedcustomfields.h" + +class KABCStorage : public KPIM::DesignerFields::Storage +{ + public: + KABCStorage( KABC::Addressee *a, const QString &ns ) + : mAddressee( a ), mNs( ns ) + { + } + + QStringList keys() + { + QStringList keys; + + const QStringList customs = mAddressee->customs(); + QStringList::ConstIterator it; + for ( it = customs.begin(); it != customs.end(); ++it ) { + QString app, name, value; + splitField( *it, app, name, value ); + if ( app == mNs ) keys.append( name ); + } + + return keys; + } + + QString read( const QString &key ) + { + return mAddressee->custom( mNs, key ); + } + + void write( const QString &key, const QString &value ) + { + mAddressee->insertCustom( mNs, key, value ); + } + + private: + KABC::Addressee *mAddressee; + QString mNs; +}; + + +AdvancedCustomFields::AdvancedCustomFields( const QString &uiFile, KABC::AddressBook *ab, + QWidget *parent, const char *name ) + : KAB::ContactEditorWidget( ab, parent, name ) +{ + initGUI( uiFile ); +} + +void AdvancedCustomFields::loadContact( KABC::Addressee *addr ) +{ + QString ns; + if ( mFields->identifier().upper() == "KADDRESSBOOK" || + QRegExp( "^Form\\d\\d?$" ).search( mFields->identifier() ) >= 0 ) { + ns = "KADDRESSBOOK"; + } else { + ns = mFields->identifier(); + } + + KABCStorage storage( addr, ns ); + mFields->load( &storage ); +} + +void AdvancedCustomFields::storeContact( KABC::Addressee *addr ) +{ + QString ns; + if ( mFields->identifier().upper() == "KADDRESSBOOK" || + QRegExp( "^Form\\d\\d?$" ).search( mFields->identifier() ) >= 0 ) { + ns = "KADDRESSBOOK"; + } else { + ns = mFields->identifier(); + } + + KABCStorage storage( addr, ns ); + mFields->save( &storage ); +} + +void AdvancedCustomFields::setReadOnly( bool readOnly ) +{ + mFields->setReadOnly( readOnly ); +} + +void AdvancedCustomFields::initGUI( const QString &uiFile ) +{ + QVBoxLayout *layout = new QVBoxLayout( this, KDialog::marginHint(), + KDialog::spacingHint() ); + + mFields = new KPIM::DesignerFields( uiFile, this ); + layout->addWidget( mFields ); + + connect( mFields, SIGNAL( modified() ), SLOT( setModified() ) ); +} + +QString AdvancedCustomFields::pageIdentifier() const +{ + return mFields->identifier(); +} + +QString AdvancedCustomFields::pageTitle() const +{ + return mFields->title(); +} + +#include "advancedcustomfields.moc" diff --git a/kaddressbook/advancedcustomfields.h b/kaddressbook/advancedcustomfields.h new file mode 100644 index 000000000..b997ffb9f --- /dev/null +++ b/kaddressbook/advancedcustomfields.h @@ -0,0 +1,60 @@ +/* + This file is part of KAddressbook. + + Copyright (c) 2004 Tobias Koenig <tokoe@kde.org> + Copyright (c) 2004 Cornelius Schumacher <schumacher@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 ADVANCEDCUSTOMFIELDS_H +#define ADVANCEDCUSTOMFIELDS_H + +#include <klocale.h> + +#include <qmap.h> +#include <qpair.h> +#include <qstringlist.h> + +#include <libkdepim/designerfields.h> + +#include "contacteditorwidget.h" + +class AdvancedCustomFields : public KAB::ContactEditorWidget +{ + Q_OBJECT + + public: + AdvancedCustomFields( const QString &uiFile, KABC::AddressBook *ab, + QWidget *parent, const char *name = 0 ); + + void loadContact( KABC::Addressee *addr ); + void storeContact( KABC::Addressee *addr ); + void setReadOnly( bool readOnly ); + + QString pageIdentifier() const; + QString pageTitle() const; + + private: + void initGUI( const QString& ); + + KPIM::DesignerFields *mFields; +}; + +#endif diff --git a/kaddressbook/common/Makefile.am b/kaddressbook/common/Makefile.am new file mode 100644 index 000000000..63a0951d8 --- /dev/null +++ b/kaddressbook/common/Makefile.am @@ -0,0 +1,12 @@ +INCLUDES= -I$(top_srcdir)/kaddressbook/interfaces \ + -I$(top_srcdir) \ + $(all_includes) + +METASOURCES = AUTO + +noinst_LTLIBRARIES = libkabcommon.la +libkabcommon_la_SOURCES = kabprefs.cpp kabprefs_base.kcfgc locationmap.cpp filter.cpp +libkabcommon_la_LDFLAGS = $(all_libraries) $(KDE_RPATH) -no-undefined +libkabcommon_la_LIBADD = $(top_builddir)/kaddressbook/interfaces/libkabinterfaces.la \ + $(top_builddir)/libkdepim/libkdepim.la +noinst_HEADERS = filter.h kabprefs.h diff --git a/kaddressbook/common/filter.cpp b/kaddressbook/common/filter.cpp new file mode 100644 index 000000000..ccac46ef8 --- /dev/null +++ b/kaddressbook/common/filter.cpp @@ -0,0 +1,219 @@ +/* + This file is part of KAddressBook. + Copyright (c) 2002 Mike Pilone <mpilone@slac.com> + + 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 <kconfig.h> +#include <kdebug.h> + +#include "kabprefs.h" + +#include "filter.h" + +Filter::Filter() + : mName( QString::null ), mMatchRule( Matching ), mEnabled( true ), + mInternal( false ), mIsEmpty( true ) +{ +} + +Filter::Filter( const QString &name ) + : mName( name ), mMatchRule( Matching ), mEnabled( true ), + mInternal( false ), mIsEmpty( false ) +{ +} + +Filter::~Filter() +{ +} + +void Filter::setName( const QString &name ) +{ + mName = name; + + mIsEmpty = false; +} + +const QString &Filter::name() const +{ + return mName; +} + +bool Filter::isInternal() const +{ + return mInternal; +} + +void Filter::apply( KABC::Addressee::List &addresseeList ) +{ + KABC::Addressee::List::Iterator iter; + for ( iter = addresseeList.begin(); iter != addresseeList.end(); ) { + if ( filterAddressee( *iter ) ) + ++iter; + else + iter = addresseeList.erase( iter ); + } +} + +bool Filter::filterAddressee( const KABC::Addressee &a ) const +{ + QStringList::ConstIterator iter; + iter = mCategoryList.begin(); + // empty filter always matches + + if ( iter == mCategoryList.end() ) { + if ( mMatchRule == Matching ) + return true; + else { + if ( a.categories().empty() ) + return true; + else + return false; + } + } + + for ( ; iter != mCategoryList.end(); ++iter ) { + if ( a.hasCategory( *iter ) ) + return ( mMatchRule == Matching ); + } + + return !( mMatchRule == Matching ); +} + +void Filter::setEnabled( bool on ) +{ + mEnabled = on; + + mIsEmpty = false; +} + +bool Filter::isEnabled() const +{ + return mEnabled; +} + +void Filter::setCategories( const QStringList &list ) +{ + mCategoryList = list; + + mIsEmpty = false; +} + +const QStringList &Filter::categories() const +{ + return mCategoryList; +} + +void Filter::save( KConfig *config ) +{ + config->writeEntry( "Name", mName ); + config->writeEntry( "Enabled", mEnabled ); + config->writeEntry( "Categories", mCategoryList ); + config->writeEntry( "MatchRule", (int)mMatchRule ); +} + +void Filter::restore( KConfig *config ) +{ + mName = config->readEntry( "Name", "<internal error>" ); + mEnabled = config->readBoolEntry( "Enabled", true ); + mCategoryList = config->readListEntry( "Categories" ); + mMatchRule = (MatchRule)config->readNumEntry( "MatchRule", Matching ); + + mIsEmpty = false; +} + +void Filter::save( KConfig *config, const QString &baseGroup, Filter::List &list ) +{ + { + KConfigGroupSaver s( config, baseGroup ); + + // remove the old filters + uint count = config->readNumEntry( "Count" ); + for ( uint i = 0; i < count; ++i ) + config->deleteGroup( QString( "%1_%2" ).arg( baseGroup ).arg( i ) ); + + } + + int index = 0; + Filter::List::Iterator iter; + for ( iter = list.begin(); iter != list.end(); ++iter ) { + if ( !(*iter).mInternal ) { + KConfigGroupSaver s( config, QString( "%1_%2" ).arg( baseGroup ) + .arg( index ) ); + (*iter).save( config ); + index++; + } + } + + KConfigGroupSaver s( config, baseGroup ); + config->writeEntry( "Count", index ); +} + +Filter::List Filter::restore( KConfig *config, const QString &baseGroup ) +{ + Filter::List list; + int count = 0; + Filter f; + + { + KConfigGroupSaver s( config, baseGroup ); + count = config->readNumEntry( "Count", 0 ); + } + + for ( int i = 0; i < count; i++ ) { + { + KConfigGroupSaver s( config, QString( "%1_%2" ).arg( baseGroup ).arg( i ) ); + f.restore( config ); + } + + list.append( f ); + } + + const QStringList cats = KABPrefs::instance()->customCategories(); + for ( QStringList::ConstIterator it = cats.begin(); it != cats.end(); ++it ) { + Filter filter; + filter.mName = *it; + filter.mEnabled = true; + filter.mCategoryList = *it; + filter.mMatchRule = Matching; + filter.mInternal = true; + filter.mIsEmpty = false; + list.append( filter ); + } + + return list; +} + +void Filter::setMatchRule( MatchRule rule ) +{ + mMatchRule = rule; + + mIsEmpty = false; +} + +Filter::MatchRule Filter::matchRule() const +{ + return mMatchRule; +} + +bool Filter::isEmpty() const +{ + return mIsEmpty; +} diff --git a/kaddressbook/common/filter.h b/kaddressbook/common/filter.h new file mode 100644 index 000000000..9251c5c17 --- /dev/null +++ b/kaddressbook/common/filter.h @@ -0,0 +1,160 @@ +/* + This file is part of KAddressBook. + Copyright (c) 2002 Mike Pilone <mpilone@slac.com> + + 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 FILTER_H +#define FILTER_H + +#include <qstring.h> +#include <qstringlist.h> +#include <qvaluelist.h> + +#include <kabc/addressee.h> +#include <kconfig.h> + +/** + Filter for AddressBook related objects (Addressees) + + @todo This class should be switched to use shared data. + */ +class Filter +{ + public: + typedef QValueList<Filter> List; + + enum MatchRule { Matching = 0, NotMatching = 1 }; + + Filter(); + Filter( const QString& name ); + ~Filter(); + + /** + Set the name of the filter. + */ + void setName( const QString &name ); + + /** + @return The name of the filter. + */ + const QString &name() const; + + /** + @return Whether the filter is an internal one. + */ + bool isInternal() const; + + /** + Apply the filter to the addressee list. All addressees not passing + the filter criterias will be removed from the list. + + If the MatchRule is NotMatch, then all the addressees matching the + filter will be removed from the list. + */ + void apply( KABC::Addressee::List &addresseeList ); + + /** + Apply the filter to the addressee. + + @return True if the addressee passes the criteria, false otherwise. + The return values are opposite if the MatchRule is NotMatch. + */ + bool filterAddressee( const KABC::Addressee &a ) const; + + /** + Enable or disable the filter + */ + void setEnabled( bool on ); + + /** + @return True if this filter is enabled, false otherwise. + */ + bool isEnabled() const; + + /** + Set the list of categories. This list is used to filter addressees. + */ + void setCategories( const QStringList &list ); + + /** + @return The list of categories. + */ + const QStringList &categories() const; + + /** + Saves the filter to the config file. The group should already be set. + */ + void save( KConfig *config ); + + /** + Loads the filter from the config file. The group should already be set. + */ + void restore( KConfig *config ); + + /** + Saves a list of filters to the config file. + + @param config The config file to use + @param baseGroup The base groupname to use. The number of filters + will be written to this group, then a _1, _2, etc + will be append for each filter saved. + @param list The list of filters to be saved. + */ + static void save( KConfig *config, const QString &baseGroup, Filter::List &list ); + + /** + Restores a list of filters from a config file. + + @param config The config file to read from. + @param baseGroup The base group name to be used to find the filters + + @return The list of filters. + */ + static Filter::List restore( KConfig *config, const QString &baseGroup ); + + /** + Sets the filter rule. If the rule is Filter::Matching (default), + then the filter will return true on items that match the filter. + If the rule is Filter::NotMatching, then the filter will return + true on items that do not match the filter. + */ + void setMatchRule( MatchRule rule ); + + /** + @return The current match rule. + */ + MatchRule matchRule() const; + + /** + @return true if the category list is empty. + */ + bool isEmpty() const; + + private: + QString mName; + QStringList mCategoryList; + MatchRule mMatchRule; + bool mEnabled; + bool mInternal; + bool mIsEmpty; +}; + +#endif diff --git a/kaddressbook/common/kabprefs.cpp b/kaddressbook/common/kabprefs.cpp new file mode 100644 index 000000000..e8402d562 --- /dev/null +++ b/kaddressbook/common/kabprefs.cpp @@ -0,0 +1,82 @@ +/* + This file is part of KAddressBook. + Copyright (c) 2002 Mike Pilone <mpilone@slac.com> + + 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 <kconfig.h> +#include <klocale.h> +#include <kstaticdeleter.h> + +#include "kabprefs.h" + +KABPrefs *KABPrefs::mInstance = 0; +static KStaticDeleter<KABPrefs> staticDeleter; + +KABPrefs::KABPrefs() + : KABPrefsBase() +{ + KConfigSkeleton::setCurrentGroup( "General" ); + + QStringList defaultMap; + defaultMap << "http://maps.google.com/maps?f=q&hl=%1&q=%n,%l,%s"; + addItemString( "LocationMapURL", mLocationMapURL, defaultMap[ 0 ] ); + addItemStringList( "LocationMapURLs", mLocationMapURLs, defaultMap ); +} + +KABPrefs::~KABPrefs() +{ +} + +KABPrefs *KABPrefs::instance() +{ + if ( !mInstance ) { + staticDeleter.setObject( mInstance, new KABPrefs() ); + mInstance->readConfig(); + } + + return mInstance; +} + +void KABPrefs::setCategoryDefaults() +{ + mCustomCategories.clear(); + mCustomCategories << i18n( "Business" ) << i18n( "Family" ) << i18n( "School" ) + << i18n( "Customer" ) << i18n( "Friend" ); +} + +void KABPrefs::usrReadConfig() +{ + config()->setGroup( "General" ); + mCustomCategories = config()->readListEntry( "Custom Categories" ); + if ( mCustomCategories.isEmpty() ) + setCategoryDefaults(); + + KPimPrefs::usrReadConfig(); +} + + +void KABPrefs::usrWriteConfig() +{ + config()->setGroup( "General" ); + config()->writeEntry( "Custom Categories", mCustomCategories ); + + KPimPrefs::usrWriteConfig(); +} diff --git a/kaddressbook/common/kabprefs.h b/kaddressbook/common/kabprefs.h new file mode 100644 index 000000000..3c2db1522 --- /dev/null +++ b/kaddressbook/common/kabprefs.h @@ -0,0 +1,86 @@ +/* + This file is part of KAddressBook. + Copyright (c) 2002 Mike Pilone <mpilone@slac.com> + + 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 KABPREFS_H +#define KABPREFS_H + +#include <qstringlist.h> +#include <kdepimmacros.h> +#include "kabprefs_base.h" + +class KConfig; + +class KDE_EXPORT KABPrefs : public KABPrefsBase +{ + public: + virtual ~KABPrefs(); + + static KABPrefs *instance(); + + void usrReadConfig(); + void usrWriteConfig(); + + void setLocationMapURL( const QString &locationMapURL ) + { + if ( !isImmutable( QString::fromLatin1( "LocationMapURL" ) ) ) + mLocationMapURL = locationMapURL; + } + + QString locationMapURL() const + { + return mLocationMapURL; + } + + void setLocationMapURLs( const QStringList &locationMapURLs ) + { + if ( !isImmutable( QString::fromLatin1( "LocationMapURLs" ) ) ) + mLocationMapURLs = locationMapURLs; + } + + QStringList locationMapURLs() const + { + return mLocationMapURLs; + } + + QStringList customCategories() const + { + return mCustomCategories; + } + + void setCustomCategories(const QStringList & s) + { + mCustomCategories = s; + } + + void setCategoryDefaults(); + + private: + KABPrefs(); + + static KABPrefs *mInstance; + + QString mLocationMapURL; + QStringList mLocationMapURLs; +}; + +#endif diff --git a/kaddressbook/common/kabprefs_base.kcfgc b/kaddressbook/common/kabprefs_base.kcfgc new file mode 100644 index 000000000..cca2c9337 --- /dev/null +++ b/kaddressbook/common/kabprefs_base.kcfgc @@ -0,0 +1,11 @@ +# Code generation options for kconfig_compiler +File=kaddressbook.kcfg +ClassName=KABPrefsBase +Singleton=false +Mutators=true +Inherits=KPimPrefs +IncludeFiles=libkdepim/kpimprefs.h +MemberVariables=public +GlobalEnums=true +ItemAccessors=true +SetUserTexts=true diff --git a/kaddressbook/common/kaddressbook.kcfg b/kaddressbook/common/kaddressbook.kcfg new file mode 100644 index 000000000..37e6ff0a6 --- /dev/null +++ b/kaddressbook/common/kaddressbook.kcfg @@ -0,0 +1,93 @@ +<?xml version="1.0" encoding="UTF-8"?> +<kcfg xmlns="http://www.kde.org/standards/kcfg/1.0" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://www.kde.org/standards/kcfg/1.0 + http://www.kde.org/standards/kcfg/1.0/kcfg.xsd" > + <kcfgfile name="kaddressbookrc"/> + + <group name="General"> + <entry type="Bool" name="AutomaticNameParsing"> + <label>Automatic name parsing for new addressees</label> + <whatsthis></whatsthis> + <default>true</default> + </entry> + <entry type="Int" name="CurrentIncSearchField"> + <default>0</default> + </entry> + <entry type="String" name="PhoneHookApplication"> + <label>Phone</label> + <whatsthis></whatsthis> + </entry> + <entry type="String" name="FaxHookApplication"> + <label>Fax</label> + <whatsthis></whatsthis> + <default>kdeprintfax --phone %N</default> + </entry> + <entry type="String" name="SMSHookApplication"> + <label>SMS</label> + <whatsthis>The script used to send a GSM SMS text message to the mobile phone</whatsthis> + </entry> + </group> + + <group name="Views"> + <entry type="Bool" name="HonorSingleClick"> + <label>Honor KDE single click</label> + <whatsthis></whatsthis> + <default>false</default> + </entry> + <entry type="String" name="CurrentView"> + <default>Default Table View</default> + </entry> + <entry type="StringList" name="ViewNames"> + <default>Default Table View</default> + </entry> + </group> + + <group name="MainWindow"> + <entry type="Bool" name="JumpButtonBarVisible"> + <default>false</default> + </entry> + <entry type="Bool" name="DetailsPageVisible"> + <default>true</default> + </entry> + <entry type="IntList" name="DetailsSplitter"> + </entry> + <entry type="IntList" name="LeftSplitter"> + </entry> + <entry type="Bool" name="ContactListAboveExtensions"> + <default>true</default> + <whatsthis>If true, the contact list will be placed above the extensions on the left (distribution list editor etc.) instead of in the middle of the main window</whatsthis> + + </entry> + </group> + + <group name="ExtensionsGeneral"> + <entry type="String" name="CurrentExtension"> + <default>resourceselection</default> + </entry> + <entry type="StringList" name="activeExtensions"> + <default>distribution_list_editor_ng,resourceselection</default> + </entry> + <entry type="IntList" name="ExtensionsSplitterSizes"/> + </group> + + <group name="Filters"> + <entry type="Int" name="CurrentFilter"> + <default>0</default> + </entry> + </group> + + <group name="AddresseeEditor"> + <entry type="Enum" name="EditorType"> + <choices> + <choice name="FullEditor"/> + <choice name="SimpleEditor"/> + </choices> + <default>FullEditor</default> + </entry> + <entry type="StringList" name="GlobalCustomFields"> + </entry> + <entry type="StringList" name="AdvancedCustomFields"> + </entry> + </group> +</kcfg> diff --git a/kaddressbook/common/locationmap.cpp b/kaddressbook/common/locationmap.cpp new file mode 100644 index 000000000..92bdfaab1 --- /dev/null +++ b/kaddressbook/common/locationmap.cpp @@ -0,0 +1,96 @@ +/* + This file is part of KAddressbook. + Copyright (c) 2004 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 <kapplication.h> +#include <kconfig.h> +#include <kdeversion.h> +#include <kglobal.h> +#include <klocale.h> +#include <kmessagebox.h> +#include <kstaticdeleter.h> +#include <kurl.h> + +#include "kabprefs.h" +#include "locationmap.h" + +LocationMap *LocationMap::mSelf = 0; +static KStaticDeleter<LocationMap> locationMapDeleter; + +LocationMap::LocationMap() +{ +} + +LocationMap::~LocationMap() +{ +} + +LocationMap *LocationMap::instance() +{ + if ( !mSelf ) + locationMapDeleter.setObject( mSelf, new LocationMap ); + + return mSelf; +} + +void LocationMap::showAddress( const KABC::Address &addr ) +{ + KURL url( createUrl( addr ) ); + if ( url.isEmpty() ) + return; + + kapp->invokeBrowser( url.url() ); +} + +QString LocationMap::createUrl( const KABC::Address &addr ) +{ + /** + This method makes substitutions for the following place holders: + %s street + %r region + %l locality + %z zip code + %c country (in ISO format) + */ + + QString urlTemplate = KABPrefs::instance()->locationMapURL().arg( KGlobal::locale()->country() ); + if ( urlTemplate.isEmpty() ) { + KMessageBox::error( 0, i18n( "No service provider available for map lookup!\nPlease add one in the configuration dialog." ) ); + return QString::null; + } + +#if KDE_VERSION >= 319 + return urlTemplate.replace( "%s", addr.street() ). + replace( "%r", addr.region() ). + replace( "%l", addr.locality() ). + replace( "%z", addr.postalCode() ). + replace( "%c", addr.countryToISO( addr.country() ) ); +#else + return urlTemplate.replace( "%s", addr.street() ). + replace( "%r", addr.region() ). + replace( "%l", addr.locality() ). + replace( "%z", addr.postalCode() ). + replace( "%c", "" ); +#endif +} + +#include "locationmap.moc" diff --git a/kaddressbook/common/locationmap.h b/kaddressbook/common/locationmap.h new file mode 100644 index 000000000..82300d9df --- /dev/null +++ b/kaddressbook/common/locationmap.h @@ -0,0 +1,51 @@ +/* + This file is part of KAddressbook. + Copyright (c) 2004 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 LOCATIONMAP_H +#define LOCATIONMAP_H + +#include <kabc/address.h> +#include <qobject.h> +#include <qstring.h> + +class LocationMap : public QObject +{ + Q_OBJECT + + public: + static LocationMap *instance(); + ~LocationMap(); + + public slots: + void showAddress( const KABC::Address& ); + + protected: + LocationMap(); + + private: + QString createUrl( const KABC::Address& ); + + static LocationMap *mSelf; +}; + +#endif diff --git a/kaddressbook/contacteditorwidgetmanager.cpp b/kaddressbook/contacteditorwidgetmanager.cpp new file mode 100644 index 000000000..de21528cd --- /dev/null +++ b/kaddressbook/contacteditorwidgetmanager.cpp @@ -0,0 +1,217 @@ +/* + This file is part of KAddressBook. + Copyright (c) 2004 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 <qlayout.h> + +#include <kapplication.h> +#include <kdialog.h> +#include <klibloader.h> +#include <ktrader.h> + +// include non-plugin contact editor widgets +#include "customfieldswidget.h" +#include "freebusywidget.h" +#include "geowidget.h" +#include "imagewidget.h" +#include "soundwidget.h" + +#include "contacteditorwidget.h" +#include "contacteditorwidgetmanager.h" + +ContactEditorWidgetManager *ContactEditorWidgetManager::mSelf = 0; + +ContactEditorWidgetManager::ContactEditorWidgetManager() + : QObject( qApp ) +{ + reload(); +} + +ContactEditorWidgetManager::~ContactEditorWidgetManager() +{ + mFactories.clear(); +} + +ContactEditorWidgetManager *ContactEditorWidgetManager::self() +{ + kdWarning( !kapp, 7520 ) << "No QApplication object available!" << endl; + + if ( !mSelf ) + mSelf = new ContactEditorWidgetManager(); + + return mSelf; +} + +int ContactEditorWidgetManager::count() const +{ + return mFactories.count(); +} + +KAB::ContactEditorWidgetFactory *ContactEditorWidgetManager::factory( int pos ) const +{ + return mFactories[ pos ]; +} + +void ContactEditorWidgetManager::reload() +{ + mFactories.clear(); + kdDebug(5720) << "ContactEditorWidgetManager::reload()" << endl; + const KTrader::OfferList plugins = KTrader::self()->query( "KAddressBook/ContactEditorWidget", + QString( "[X-KDE-KAddressBook-CEWPluginVersion] == %1" ).arg( KAB_CEW_PLUGIN_VERSION ) ); + + KTrader::OfferList::ConstIterator it; + for ( it = plugins.begin(); it != plugins.end(); ++it ) { + KLibFactory *factory = KLibLoader::self()->factory( (*it)->library().latin1() ); + if ( !factory ) { + kdDebug(5720) << "ContactEditorWidgetManager::reload(): Factory creation failed" << endl; + continue; + } + + KAB::ContactEditorWidgetFactory *pageFactory = + static_cast<KAB::ContactEditorWidgetFactory*>( factory ); + + if ( !pageFactory ) { + kdDebug(5720) << "ContactEditorWidgetManager::reload(): Cast failed" << endl; + continue; + } + + mFactories.append( pageFactory ); + } + + // add all non-plugin contact editor factories + mFactories.append( new FreeBusyWidgetFactory ); + mFactories.append( new ImageWidgetFactory ); + mFactories.append( new SoundWidgetFactory ); + mFactories.append( new GeoWidgetFactory ); + mFactories.append( new CustomFieldsWidgetFactory ); +} + +/////////////////////////////////////////////////////////////////////////////// + +ContactEditorTabPage::ContactEditorTabPage( QWidget *parent, const char *name ) + : QWidget( parent, name ) +{ + mLayout = new QGridLayout( this, 0, 2, KDialog::marginHint(), + KDialog::spacingHint() ); +} + +void ContactEditorTabPage::addWidget( KAB::ContactEditorWidget *widget ) +{ + if ( widget->logicalWidth() == 2 ) { + mWidgets.prepend( widget ); + connect( widget, SIGNAL( changed() ), SIGNAL( changed() ) ); + return; + } + + // insert it in descending order + KAB::ContactEditorWidget::List::Iterator it; + for ( it = mWidgets.begin(); it != mWidgets.end(); ++it ) { + if ( widget->logicalHeight() > (*it)->logicalHeight() && + (*it)->logicalWidth() == 1 ) { + --it; + break; + } + } + mWidgets.insert( ++it, widget ); + + connect( widget, SIGNAL( changed() ), SIGNAL( changed() ) ); +} + +void ContactEditorTabPage::loadContact( KABC::Addressee *addr ) +{ + KAB::ContactEditorWidget::List::Iterator it; + for ( it = mWidgets.begin(); it != mWidgets.end(); ++it ) { + (*it)->setModified( false ); + (*it)->loadContact( addr ); + } +} + +void ContactEditorTabPage::storeContact( KABC::Addressee *addr ) +{ + KAB::ContactEditorWidget::List::Iterator it; + for ( it = mWidgets.begin(); it != mWidgets.end(); ++it ) { + if ( (*it)->modified() ) { + (*it)->storeContact( addr ); + (*it)->setModified( false ); + } + } +} + +void ContactEditorTabPage::setReadOnly( bool readOnly ) +{ + KAB::ContactEditorWidget::List::Iterator it; + for ( it = mWidgets.begin(); it != mWidgets.end(); ++it ) + (*it)->setReadOnly( readOnly ); +} + +void ContactEditorTabPage::updateLayout() +{ + KAB::ContactEditorWidget::List::ConstIterator it; + + int row = 0; + for ( it = mWidgets.begin(); it != mWidgets.end(); ++it ) { + if ( (*it)->logicalWidth() == 2 ) { + mLayout->addMultiCellWidget( *it, row, row + (*it)->logicalHeight() - 1, 0, 1 ); + row += (*it)->logicalHeight(); + + if ( it != mWidgets.fromLast() ) { + QFrame *frame = new QFrame( this ); + frame->setFrameStyle( QFrame::HLine | QFrame::Sunken ); + mLayout->addMultiCellWidget( frame, row, row, 0, 1 ); + row++; + } + continue; + } + + // fill left side + int leftHeight = (*it)->logicalHeight(); + + if ( it == mWidgets.fromLast() ) { // last widget gets full width + mLayout->addMultiCellWidget( *it, row, row + leftHeight - 1, 0, 1 ); + return; + } else { + mLayout->addMultiCellWidget( *it, row, row + leftHeight - 1, 0, 0 ); + QFrame *frame = new QFrame( this ); + frame->setFrameStyle( QFrame::HLine | QFrame::Sunken ); + mLayout->addMultiCellWidget( frame, row + leftHeight, row + leftHeight, 0, 1 ); + } + + // fill right side + for ( int i = 0; i < leftHeight; ++i ) { + ++it; + if ( it == mWidgets.end() ) + break; + + int rightHeight = (*it)->logicalHeight(); + if ( rightHeight + i <= leftHeight ) + mLayout->addMultiCellWidget( *it, row + i, row + i + rightHeight - 1, 1, 1 ); + else { + --i; + break; + } + } + + row += 2; + } +} + +#include "contacteditorwidgetmanager.moc" diff --git a/kaddressbook/contacteditorwidgetmanager.h b/kaddressbook/contacteditorwidgetmanager.h new file mode 100644 index 000000000..9b0efbc15 --- /dev/null +++ b/kaddressbook/contacteditorwidgetmanager.h @@ -0,0 +1,113 @@ +/* + This file is part of KAddressBook. + Copyright (c) 2004 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 CONTACTEDITORWIDGETMANAGER_H +#define CONTACTEDITORWIDGETMANAGER_H + +#include <qwidget.h> + +#include "contacteditorwidget.h" + +namespace KABC { +class Addressee; +} + +class QGridLayout; + +class ContactEditorWidgetManager : public QObject +{ + Q_OBJECT + + public: + static ContactEditorWidgetManager *self(); + + /** + Returns the number of available Contact Editor Page factories. + */ + int count() const; + + /** + Returns a factory. + */ + KAB::ContactEditorWidgetFactory *factory( int pos ) const; + + protected: + ContactEditorWidgetManager(); + ~ContactEditorWidgetManager(); + + private: + void reload(); + + QValueList<KAB::ContactEditorWidgetFactory*> mFactories; + + static ContactEditorWidgetManager *mSelf; +}; + +class ContactEditorTabPage : public QWidget +{ + Q_OBJECT + + public: + ContactEditorTabPage( QWidget *parent, const char *name = 0 ); + + /** + Adds a widget to the tab. + */ + void addWidget( KAB::ContactEditorWidget *widget ); + + /** + Load the contacts data into the GUI. + */ + void loadContact( KABC::Addressee *addr ); + + /** + Save the data from the GUI into the passed contact + object. + */ + void storeContact( KABC::Addressee *addr ); + + /** + Sets whether the contact should be presented as + read-only. You should update your GUI in the reimplemented + method. + */ + void setReadOnly( bool readOnly ); + + /** + Calculates the layout of the widgets and moves them to the + correct position. + */ + void updateLayout(); + + signals: + /** + Emitted whenever the page has changed. + */ + void changed(); + + private: + QGridLayout *mLayout; + KAB::ContactEditorWidget::List mWidgets; +}; + +#endif diff --git a/kaddressbook/csv-templates/Makefile.am b/kaddressbook/csv-templates/Makefile.am new file mode 100644 index 000000000..e92e5d2c2 --- /dev/null +++ b/kaddressbook/csv-templates/Makefile.am @@ -0,0 +1,2 @@ +templatedir = $(kde_datadir)/kaddressbook/csv-templates +template_DATA = kaddressbook.desktop outlook2000.desktop yahoo.desktop diff --git a/kaddressbook/csv-templates/README b/kaddressbook/csv-templates/README new file mode 100644 index 000000000..befe2ab4c --- /dev/null +++ b/kaddressbook/csv-templates/README @@ -0,0 +1,49 @@ +Here are listed all fields kaddressbook can import via csv. If you want +to create a new csv import template, you have to create a file like +'kaddressbook.desktop', but with the correct column mapping. + +--- + +00 "Formatted Name" +01 "Family Name" +02 "Given Name" +03 "Additional Names" +04 "Honorific Prefixes" +05 "Honorific Suffixes" +06 "Nick Name" +07 "Birthday" +08 "Home Address Street" +09 "Home Address Locality" +10 "Home Address Region" +11 "Home Address Postal Code" +12 "Home Address Country" +13 "Home Address Label" +14 "Business Address Street" +15 "Business Address Locality" +16 "Business Address Region" +17 "Business Address Postal Code" +18 "Business Address Country" +19 "Business Address Label" +20 "Home Phone" +21 "Business Phone" +22 "Mobile Phone" +23 "Home Fax" +24 "Business Fax" +25 "Car Phone" +26 "Isdn" +27 "Pager" +28 "Email Address" +29 "Mail Client" +30 "Title" +31 "Role" +32 "Organization" +33 "Note" +34 "URL" +35 "Department" +36 "Profession" +37 "Assistant's Name" +38 "Manager's Name" +39 "Partner's Name" +40 "Office" +41 "IM Address" +42 "Anniversary" diff --git a/kaddressbook/csv-templates/kaddressbook.desktop b/kaddressbook/csv-templates/kaddressbook.desktop new file mode 100644 index 000000000..a5b9c4066 --- /dev/null +++ b/kaddressbook/csv-templates/kaddressbook.desktop @@ -0,0 +1,83 @@ +[General] +Columns=43 +DatePattern=Y-M-D +DelimiterOther= +DelimiterType=0 +QuoteType=0 + +[Misc] +Name=KAddressBook (KDE 3.1) +Name[af]=K-adresboek (Kde 3.1) +Name[ar]=دفتر العناوين KAddressBook (KDE 3.1( +Name[ca]=Llibreta d'adreces (KDE 3.1) +Name[cs]=Kniha adres (KDE 3.1) +Name[cy]=KLlyfrCyfeiriadau (KDE 3.1) +Name[de]=Adressbuch (KDE 3.1) +Name[et]=KDE aadressiraamat (KDE 3.1) +Name[fo]=KAdressubók (KDE 3.1) +Name[hi]=केडीईएड्रेसबुक (केडीई 3.1) +Name[hr]=KAdressBook (KDE 3.1) +Name[hu]=Címjegyzék (KDE 3.1) +Name[it]=Rubrica indirizzi (KDE 3.1) +Name[ka]=წიგნაკი (KDE 3.1) +Name[mk]=КАдресар (KDE 3.1) +Name[nb]=Adressebok (KDE 3.1) +Name[nds]=KAdressbook (KDE 3.1) +Name[ne]=केडीई ठेगाना पुस्तिका (केडीई ३.१) +Name[nn]=KDE-adressebok (KDE 3.1) +Name[nso]=KBuka ya Diaterese (KDE 3.1) +Name[pl]=Książka adresowa (KDE 3.1) +Name[ro]=Cartea de adrese (KDE 3.1) +Name[ru]=Адресная книга (KDE 3.1) +Name[se]=KDE-čujuhusgirji (KDE 3.3) +Name[sl]=Adresar (KDE 3.1) +Name[sv]=Kadressbok (KDE 3.1) +Name[ta]=கேமுகவரிப்புத்தகம் (KDE 3.1) +Name[tg]=Китоби адрес (KDE 3.1) +Name[tr]=KDE Adres Defteri (KDE 3.1) +Name[ven]=Bugu ya diresi ya K (KDE 3.1) + +[csv column map] +0=1 +1=2 +10=11 +11=12 +12=13 +13=14 +14=15 +15=16 +16=17 +17=18 +18=19 +19=20 +2=3 +20=21 +21=22 +22=23 +23=24 +24=25 +25=26 +26=27 +27=28 +28=29 +29=30 +3=4 +30=31 +31=32 +32=33 +33=34 +34=35 +35=36 +36=37 +37=38 +38=39 +39=40 +4=5 +40=41 +41=42 +42=43 +5=6 +6=7 +7=8 +8=9 +9=10 diff --git a/kaddressbook/csv-templates/outlook2000.desktop b/kaddressbook/csv-templates/outlook2000.desktop new file mode 100644 index 000000000..d5c6a4b28 --- /dev/null +++ b/kaddressbook/csv-templates/outlook2000.desktop @@ -0,0 +1,109 @@ +[General] +Columns=92 +DelimiterOther= +DelimiterType=0 +QuoteType=0 + +[Misc] +Name=Outlook 2000 +Name[ar]=برنامج Outlook 2000 +Name[eo]=Redmondo 2000 +Name[fa]=اوت لوک ۲۰۰۰ +Name[hi]=आउटलुक 2000 +Name[ne]=आउटलुक २००० +Name[nso]=Bokantle 2000 +Name[ta]=அவுட்லுக் 2000 + +[csv column map] +0=5 +1=3 +10=0 +11=16 +12=17 +13=18 +14=19 +15=9 +16=0 +17=0 +18=10 +19=11 +2=4 +20=12 +21=13 +22=0 +23=0 +24=0 +25=0 +26=0 +27=0 +28=0 +29=0 +3=2 +30=25 +31=22 +32=0 +33=0 +34=26 +35=0 +36=24 +37=21 +38=0 +39=27 +4=6 +40=23 +41=0 +42=0 +43=28 +44=0 +45=0 +46=0 +47=0 +48=0 +49=43 +5=33 +50=38 +51=0 +52=8 +53=0 +54=0 +55=0 +56=0 +57=29 +58=0 +59=1 +6=36 +60=0 +61=0 +62=0 +63=0 +64=0 +65=0 +66=0 +67=0 +68=0 +69=0 +7=31 +70=0 +71=0 +72=0 +73=0 +74=0 +75=39 +76=0 +77=34 +78=0 +79=0 +8=15 +80=0 +81=0 +82=0 +83=37 +84=0 +85=0 +86=40 +87=0 +88=0 +89=0 +9=0 +90=0 +91=35 diff --git a/kaddressbook/csv-templates/yahoo.desktop b/kaddressbook/csv-templates/yahoo.desktop new file mode 100644 index 000000000..b365365c8 --- /dev/null +++ b/kaddressbook/csv-templates/yahoo.desktop @@ -0,0 +1,105 @@ +[General] +Columns=39 +DatePattern=M/D/Y +DelimiterOther= +DelimiterType=0 +QuoteType=0 + +[Misc] +Name=Yahoo! AddressBook +Name[af]=Yahoo! Adresboek +Name[ar]=دفتر العناوين Yahoo! +Name[be]=Адрасная кніга Yahoo! +Name[br]=Karned chomlec'hioù Yahoo ! +Name[bs]=Yahoo! Adresar +Name[ca]=Llibreta d'adreces Yahoo! +Name[cs]=Kniha adres Yahoo! +Name[cy]=Llyfr Cyfeiriadau Yahoo! +Name[da]=Yahoo! adressebog +Name[de]=Yahoo!-Adressbuch +Name[el]=Βιβλίο διευθύνσεων Yahoo! +Name[eo]=Yahoo! Adresaro +Name[es]=Libreta de direcciones de Yahoo! +Name[et]=Yahoo! aadressiraamat +Name[eu]=Yahoo! helbide-liburua +Name[fa]=کتاب نشانی یاهو! +Name[fi]=Yahoo-osoitekirja +Name[fr]=Carnet d'adresses Yahoo! +Name[fy]=Yahoo!-adresboek +Name[he]=פנקס כתובת של Yahoo! +Name[hi]=याहू! पता पुस्तिका +Name[hu]=Yahoo! címjegyzék +Name[is]=Yahoo! póstfangaskrá +Name[it]=Rubrica indirizzi Yahoo! +Name[ja]=Yahoo! アドレス帳 +Name[ka]=წიგნაკი Yahoo! +Name[kk]=Yahoo! адрестік кітапшасы +Name[km]=សៀវភៅអាសយដ្ឋានរបស់យ៉ាហ៊ូ +Name[ko]=Yahoo! 주소록 +Name[lt]=Yahoo! Adresų knygutė +Name[mk]=Адресар од Yahoo! +Name[nb]=Yahoo! adressebok +Name[nds]=Yahoo!-Adressbook +Name[ne]=याहू! ठेगाना पुस्तिका +Name[nl]=Yahoo!-adresboek +Name[nn]=Yahoo! Adressebok +Name[pa]=Yahoo! ਸਿਰਨਾਵਾਂ ਕਿਤਾਬ +Name[pl]=Książka adresowa Yahoo! +Name[pt]=Livro de Endereços do Yahoo! +Name[pt_BR]=Livro de Endereços do Yahoo! +Name[ru]=Адресная книга Yahoo! +Name[se]=Yahoo! čujuhusgirji +Name[sk]=Yahoo! kniha adries +Name[sl]=Adresar Yahoo! +Name[sr]=Yahoo! адресар +Name[sr@Latn]=Yahoo! adresar +Name[sv]=Yahoo!-adressbok +Name[ta]=யாஹூ! முகவரிப் புத்தகம் +Name[tg]=Китоби адресии Yahoo! +Name[tr]=Yahoo! Adres Defteri +Name[uk]=Адресна книга Yahoo +Name[uz]=Yahoo! manzillar daftari +Name[uz@cyrillic]=Yahoo! манзиллар дафтари +Name[zh_CN]=Yahoo! 地址簿 +Name[zh_TW]=Yahoo! 通訊錄 + +[csv column map] +0=3 +1=4 +10=28 +11=24 +12=23 +13=0 +14=0 +15=0 +16=0 +17=0 +18=35 +19=0 +2=2 +20=31 +21=33 +22=15 +23=16 +24=17 +25=18 +26=19 +27=9 +28=10 +29=11 +3=7 +30=12 +31=13 +32=8 +33=43 +34=0 +35=0 +36=0 +37=0 +38=34 +4=29 +5=0 +6=0 +7=0 +8=21 +9=22 diff --git a/kaddressbook/customfieldswidget.cpp b/kaddressbook/customfieldswidget.cpp new file mode 100644 index 000000000..a2a6e7011 --- /dev/null +++ b/kaddressbook/customfieldswidget.cpp @@ -0,0 +1,535 @@ +/* + This file is part of KAddressbook. + Copyright (c) 2004 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 <qdatetimeedit.h> +#include <qframe.h> +#include <qlabel.h> +#include <qlayout.h> +#include <qpushbutton.h> +#include <qvalidator.h> +#include <qspinbox.h> + +#include <kaccelmanager.h> +#include <kcombobox.h> +#include <kinputdialog.h> +#include <klineedit.h> +#include <kmessagebox.h> + +#include "addresseeconfig.h" +#include "kabprefs.h" + +#include "customfieldswidget.h" + + +AddFieldDialog::AddFieldDialog( QWidget *parent, const char *name ) + : KDialogBase( Plain, i18n( "Add Field" ), Ok | Cancel, + Ok, parent, name, true, true ) +{ + QWidget *page = plainPage(); + + QGridLayout *layout = new QGridLayout( page, 3, 2, marginHint(), spacingHint() ); + + QLabel *label = new QLabel( i18n( "Title:" ), page ); + layout->addWidget( label, 0, 0 ); + + mTitle = new KLineEdit( page ); + mTitle->setValidator( new QRegExpValidator( QRegExp( "([a-zA-Z]|\\d|-)+" ), mTitle ) ); + label->setBuddy( mTitle ); + layout->addWidget( mTitle, 0, 1 ); + + label = new QLabel( i18n( "Type:" ), page ); + layout->addWidget( label, 1, 0 ); + + mType = new KComboBox( page ); + label->setBuddy( mType ); + layout->addWidget( mType, 1, 1 ); + + mGlobal = new QCheckBox( i18n( "Is available for all contacts" ), page ); + mGlobal->setChecked( true ); + layout->addMultiCellWidget( mGlobal, 2, 2, 0, 1 ); + + connect( mTitle, SIGNAL( textChanged( const QString& ) ), + this, SLOT( nameChanged( const QString& ) ) ); + + KAcceleratorManager::manage( this ); + + mTypeList.append( "text" ); + mTypeName.append( i18n( "Text" ) ); + mTypeList.append( "integer" ); + mTypeName.append( i18n( "Numeric Value" ) ); + mTypeList.append( "boolean" ); + mTypeName.append( i18n( "Boolean" ) ); + mTypeList.append( "date" ); + mTypeName.append( i18n( "Date" ) ); + mTypeList.append( "time" ); + mTypeName.append( i18n( "Time" ) ); + mTypeList.append( "datetime" ); + mTypeName.append( i18n( "Date & Time" ) ); + + for ( uint i = 0; i < mTypeName.count(); ++i ) + mType->insertItem( mTypeName[ i ] ); + + nameChanged( "" ); + + mTitle->setFocus(); +} + +QString AddFieldDialog::title() const +{ + return mTitle->text(); +} + +QString AddFieldDialog::identifier() const +{ + QString id = mTitle->text().lower(); + return id.replace( ",", "_" ).replace( " ", "_" ); +} + +QString AddFieldDialog::type() const +{ + return mTypeList[ mType->currentItem() ]; +} + +bool AddFieldDialog::isGlobal() const +{ + return mGlobal->isChecked(); +} + +void AddFieldDialog::nameChanged( const QString &name ) +{ + enableButton( Ok, !name.isEmpty() ); +} + +FieldWidget::FieldWidget( QWidget *parent, const char *name ) + : QWidget( parent, name ) +{ + QVBoxLayout *layout = new QVBoxLayout( this, KDialog::marginHint(), + KDialog::spacingHint() ); + + mGlobalLayout = new QVBoxLayout( layout, KDialog::spacingHint() ); + mGlobalLayout->setAlignment( Qt::AlignTop ); + + mSeparator = new QFrame( this ); + mSeparator->setFrameStyle( QFrame::HLine | QFrame::Sunken ); + mSeparator->hide(); + layout->addWidget( mSeparator ); + + mLocalLayout = new QVBoxLayout( layout, KDialog::spacingHint() ); + mLocalLayout->setAlignment( Qt::AlignTop ); +} + +void FieldWidget::addField( const QString &identifier, const QString &title, + const QString &type, bool isGlobal ) +{ + FieldRecord record; + + record.mIdentifier = identifier; + record.mTitle = title; + record.mLabel = new QLabel( title + ":", this ); + record.mGlobal = isGlobal; + if ( type == "integer" ) { + QSpinBox *wdg = new QSpinBox( 0, 1000, 1, this ); + record.mWidget = wdg; + connect( wdg, SIGNAL( valueChanged( int ) ), + this, SIGNAL( changed() ) ); + } else if ( type == "boolean" ) { + QCheckBox *wdg = new QCheckBox( this ); + record.mWidget = wdg; + connect( wdg, SIGNAL( toggled( bool ) ), + this, SIGNAL( changed() ) ); + } else if ( type == "date" ) { + QDateEdit *wdg = new QDateEdit( this ); + record.mWidget = wdg; + connect( wdg, SIGNAL( valueChanged( const QDate& ) ), + this, SIGNAL( changed() ) ); + } else if ( type == "time" ) { + QTimeEdit *wdg = new QTimeEdit( this ); + record.mWidget = wdg; + connect( wdg, SIGNAL( valueChanged( const QTime& ) ), + this, SIGNAL( changed() ) ); + } else if ( type == "datetime" ) { + QDateTimeEdit *wdg = new QDateTimeEdit( this ); + record.mWidget = wdg; + connect( wdg, SIGNAL( valueChanged( const QDateTime& ) ), + this, SIGNAL( changed() ) ); + } else if ( type == "text" ) { + QLineEdit *wdg = new QLineEdit( this ); + record.mWidget = wdg; + connect( wdg, SIGNAL( textChanged( const QString& ) ), + this, SIGNAL( changed() ) ); + } + + record.mLabel->show(); + record.mWidget->show(); + + if ( isGlobal ) { + record.mLayout = new QHBoxLayout( mGlobalLayout ); + record.mLayout->addWidget( record.mLabel ); + record.mLayout->addWidget( record.mWidget, Qt::AlignLeft ); + } else { + record.mLayout = new QHBoxLayout( mLocalLayout ); + record.mLayout->addWidget( record.mLabel ); + record.mLayout->addWidget( record.mWidget, Qt::AlignLeft ); + mSeparator->show(); + } + + mFieldList.append( record ); + + recalculateLayout(); +} + +void FieldWidget::removeField( const QString &identifier ) +{ + FieldRecordList::Iterator it; + for ( it = mFieldList.begin(); it != mFieldList.end(); ++it ) { + if ( (*it).mIdentifier == identifier ) { + delete (*it).mLabel; + delete (*it).mWidget; + delete (*it).mLayout; + + mFieldList.remove( it ); + recalculateLayout(); + + bool hasLocal = false; + for ( it = mFieldList.begin(); it != mFieldList.end(); ++it ) + hasLocal = hasLocal || !(*it).mGlobal; + + if ( !hasLocal ) + mSeparator->hide(); + + return; + } + } +} + +void FieldWidget::clearFields() +{ + FieldRecordList::ConstIterator fieldIt; + for ( fieldIt = mFieldList.begin(); fieldIt != mFieldList.end(); ++fieldIt ) { + if ( (*fieldIt).mWidget->isA( "QLineEdit" ) ) { + QLineEdit *wdg = static_cast<QLineEdit*>( (*fieldIt).mWidget ); + wdg->setText( QString() ); + } else if ( (*fieldIt).mWidget->isA( "QSpinBox" ) ) { + QSpinBox *wdg = static_cast<QSpinBox*>( (*fieldIt).mWidget ); + wdg->setValue( 0 ); + } else if ( (*fieldIt).mWidget->isA( "QCheckBox" ) ) { + QCheckBox *wdg = static_cast<QCheckBox*>( (*fieldIt).mWidget ); + wdg->setChecked( true ); + } else if ( (*fieldIt).mWidget->isA( "QDateEdit" ) ) { + QDateEdit *wdg = static_cast<QDateEdit*>( (*fieldIt).mWidget ); + wdg->setDate( QDate::currentDate() ); + } else if ( (*fieldIt).mWidget->isA( "QTimeEdit" ) ) { + QTimeEdit *wdg = static_cast<QTimeEdit*>( (*fieldIt).mWidget ); + wdg->setTime( QTime::currentTime() ); + } else if ( (*fieldIt).mWidget->isA( "QDateTimeEdit" ) ) { + QDateTimeEdit *wdg = static_cast<QDateTimeEdit*>( (*fieldIt).mWidget ); + wdg->setDateTime( QDateTime::currentDateTime() ); + } + } +} + +void FieldWidget::loadContact( KABC::Addressee *addr ) +{ + const QStringList customs = addr->customs(); + + clearFields(); + + QStringList::ConstIterator it; + for ( it = customs.begin(); it != customs.end(); ++it ) { + QString app, name, value; + splitField( *it, app, name, value ); + if ( app != "KADDRESSBOOK" ) + continue; + + FieldRecordList::ConstIterator fieldIt; + for ( fieldIt = mFieldList.begin(); fieldIt != mFieldList.end(); ++fieldIt ) { + if ( (*fieldIt).mIdentifier == name ) { + if ( (*fieldIt).mWidget->isA( "QLineEdit" ) ) { + QLineEdit *wdg = static_cast<QLineEdit*>( (*fieldIt).mWidget ); + wdg->setText( value ); + } else if ( (*fieldIt).mWidget->isA( "QSpinBox" ) ) { + QSpinBox *wdg = static_cast<QSpinBox*>( (*fieldIt).mWidget ); + wdg->setValue( value.toInt() ); + } else if ( (*fieldIt).mWidget->isA( "QCheckBox" ) ) { + QCheckBox *wdg = static_cast<QCheckBox*>( (*fieldIt).mWidget ); + wdg->setChecked( value == "true" || value == "1" ); + } else if ( (*fieldIt).mWidget->isA( "QDateEdit" ) ) { + QDateEdit *wdg = static_cast<QDateEdit*>( (*fieldIt).mWidget ); + wdg->setDate( QDate::fromString( value, Qt::ISODate ) ); + } else if ( (*fieldIt).mWidget->isA( "QTimeEdit" ) ) { + QTimeEdit *wdg = static_cast<QTimeEdit*>( (*fieldIt).mWidget ); + wdg->setTime( QTime::fromString( value, Qt::ISODate ) ); + } else if ( (*fieldIt).mWidget->isA( "QDateTimeEdit" ) ) { + QDateTimeEdit *wdg = static_cast<QDateTimeEdit*>( (*fieldIt).mWidget ); + wdg->setDateTime( QDateTime::fromString( value, Qt::ISODate ) ); + } + } + } + } +} + +void FieldWidget::storeContact( KABC::Addressee *addr ) +{ + FieldRecordList::ConstIterator it; + for ( it = mFieldList.begin(); it != mFieldList.end(); ++it ) { + QString value; + if ( (*it).mWidget->isA( "QLineEdit" ) ) { + QLineEdit *wdg = static_cast<QLineEdit*>( (*it).mWidget ); + value = wdg->text(); + } else if ( (*it).mWidget->isA( "QSpinBox" ) ) { + QSpinBox *wdg = static_cast<QSpinBox*>( (*it).mWidget ); + value = QString::number( wdg->value() ); + } else if ( (*it).mWidget->isA( "QCheckBox" ) ) { + QCheckBox *wdg = static_cast<QCheckBox*>( (*it).mWidget ); + value = ( wdg->isChecked() ? "true" : "false" ); + } else if ( (*it).mWidget->isA( "QDateEdit" ) ) { + QDateEdit *wdg = static_cast<QDateEdit*>( (*it).mWidget ); + value = wdg->date().toString( Qt::ISODate ); + } else if ( (*it).mWidget->isA( "QTimeEdit" ) ) { + QTimeEdit *wdg = static_cast<QTimeEdit*>( (*it).mWidget ); + value = wdg->time().toString( Qt::ISODate ); + } else if ( (*it).mWidget->isA( "QDateTimeEdit" ) ) { + QDateTimeEdit *wdg = static_cast<QDateTimeEdit*>( (*it).mWidget ); + value = wdg->dateTime().toString( Qt::ISODate ); + } + + if ( value.isEmpty() ) + addr->removeCustom( "KADDRESSBOOK", (*it).mIdentifier ); + else + addr->insertCustom( "KADDRESSBOOK", (*it).mIdentifier, value ); + } +} + +void FieldWidget::removeLocalFields() +{ + FieldRecordList::Iterator it; + for ( it = mFieldList.begin(); it != mFieldList.end(); ++it ) { + if ( !(*it).mGlobal ) { + delete (*it).mLabel; + delete (*it).mWidget; + delete (*it).mLayout; + + it = mFieldList.remove( it ); + it--; + recalculateLayout(); + } + } +} + +void FieldWidget::recalculateLayout() +{ + int maxWidth = 0; + + FieldRecordList::ConstIterator it; + for ( it = mFieldList.begin(); it != mFieldList.end(); ++it ) + maxWidth = QMAX( maxWidth, (*it).mLabel->minimumSizeHint().width() ); + + for ( it = mFieldList.begin(); it != mFieldList.end(); ++it ) + (*it).mLabel->setMinimumWidth( maxWidth ); +} + +CustomFieldsWidget::CustomFieldsWidget( KABC::AddressBook *ab, + QWidget *parent, const char *name ) + : KAB::ContactEditorWidget( ab, parent, name ) +{ + initGUI(); + + connect( mAddButton, SIGNAL( clicked() ), this, SLOT( addField() ) ); + connect( mRemoveButton, SIGNAL( clicked() ), this, SLOT( removeField() ) ); + + connect( mFieldWidget, SIGNAL( changed() ), this, SLOT( setModified() ) ); +} + +void CustomFieldsWidget::loadContact( KABC::Addressee *addr ) +{ + mAddressee = *addr; + + mFieldWidget->removeLocalFields(); + + AddresseeConfig addrConfig( mAddressee ); + QStringList fields = addrConfig.customFields(); + + if ( !fields.isEmpty() ) { + for ( uint i = 0; i < fields.count(); i += 3 ) { + mFieldWidget->addField( fields[ i ], fields[ i + 1 ], + fields[ i + 2 ] , false ); + mRemoveButton->setEnabled( true ); + } + } + + mFieldWidget->loadContact( addr ); +} + +void CustomFieldsWidget::storeContact( KABC::Addressee *addr ) +{ + mFieldWidget->storeContact( addr ); +} + +void CustomFieldsWidget::setReadOnly( bool readOnly ) +{ + mAddButton->setEnabled( !readOnly ); + mRemoveButton->setEnabled( !readOnly && !mFieldWidget->fields().isEmpty() ); +} + +void CustomFieldsWidget::addField() +{ + AddFieldDialog dlg( this ); + + if ( dlg.exec() ) { + FieldRecordList list = mFieldWidget->fields(); + + FieldRecordList::ConstIterator it; + for ( it = list.begin(); it != list.end(); ++it ) + if ( (*it).mIdentifier == dlg.identifier() ) { + KMessageBox::sorry( this, i18n( "A field with the same name already exists, please choose another one." ) ); + return; + } + + mFieldWidget->addField( dlg.identifier(), dlg.title(), + dlg.type(), dlg.isGlobal() ); + + if ( dlg.isGlobal() ) { + KABPrefs::instance()->setGlobalCustomFields( marshallFields( true ) ); + } else { + AddresseeConfig addrConfig( mAddressee ); + addrConfig.setCustomFields( marshallFields( false ) ); + } + + mRemoveButton->setEnabled( true ); + } +} + +void CustomFieldsWidget::removeField() +{ + const FieldRecordList list = mFieldWidget->fields(); + + QStringList fields; + + FieldRecordList::ConstIterator it; + for ( it = list.begin(); it != list.end(); ++it ) + fields.append( (*it).mTitle ); + + bool ok; + QString title = KInputDialog::getItem( i18n( "Remove Field" ), + i18n( "Select the field you want to remove:" ), + fields, 0, false, &ok, this ); + + if ( ok ) { + for ( it = list.begin(); it != list.end(); ++it ) + if ( (*it).mTitle == title ) { + mFieldWidget->removeField( (*it).mIdentifier ); + + if ( list.count() == 1 ) + mRemoveButton->setEnabled( false ); + + if ( (*it).mGlobal ) { + KABPrefs::instance()->setGlobalCustomFields( marshallFields( true ) ); + } else { + AddresseeConfig addrConfig( mAddressee ); + addrConfig.setCustomFields( marshallFields( false ) ); + } + + return; + } + } +} + +void CustomFieldsWidget::initGUI() +{ + QGridLayout *layout = new QGridLayout( this, 2, 3, KDialog::marginHint(), + KDialog::spacingHint() ); + + mFieldWidget = new FieldWidget( this ); + layout->addMultiCellWidget( mFieldWidget, 0, 0, 0, 2 ); + + mAddButton = new QPushButton( i18n( "Add Field..." ), this ); + layout->addWidget( mAddButton, 1, 1, Qt::AlignRight ); + + mRemoveButton = new QPushButton( i18n( "Remove Field..." ), this ); + mRemoveButton->setEnabled( false ); + layout->addWidget( mRemoveButton, 1, 2, Qt::AlignRight ); + + // load global fields + QStringList globalFields = KABPrefs::instance()->globalCustomFields(); + + if ( globalFields.isEmpty() ) + return; + + for ( uint i = 0; i < globalFields.count(); i += 3 ) { + mFieldWidget->addField( globalFields[ i ], globalFields[ i + 1 ], + globalFields[ i + 2 ] , true ); + mRemoveButton->setEnabled( true ); + } +} + +QStringList CustomFieldsWidget::marshallFields( bool global ) const +{ + QStringList retval; + + const FieldRecordList list = mFieldWidget->fields(); + FieldRecordList::ConstIterator it; + for ( it = list.begin(); it != list.end(); ++it ) { + if ( (*it).mGlobal == global ) { + retval.append( (*it).mIdentifier ); + retval.append( (*it).mTitle ); + + QString type = "text"; + if ( (*it).mWidget->isA( "QSpinBox" ) ) { + type = "integer"; + } else if ( (*it).mWidget->isA( "QCheckBox" ) ) { + type = "boolean"; + } else if ( (*it).mWidget->isA( "QDateEdit" ) ) { + type = "date"; + } else if ( (*it).mWidget->isA( "QTimeEdit" ) ) { + type = "time"; + } else if ( (*it).mWidget->isA( "QDateTimeEdit" ) ) { + type = "datetime"; + } else if ( (*it).mWidget->isA( "QLineEdit" ) ) { + type = "text"; + } + + retval.append( type ); + } + } + + return retval; +} + + +void splitField( const QString &str, QString &app, QString &name, QString &value ) +{ + int colon = str.find( ':' ); + if ( colon != -1 ) { + QString tmp = str.left( colon ); + value = str.mid( colon + 1 ); + + int dash = tmp.find( '-' ); + if ( dash != -1 ) { + app = tmp.left( dash ); + name = tmp.mid( dash + 1 ); + } + } +} + +#include "customfieldswidget.moc" diff --git a/kaddressbook/customfieldswidget.h b/kaddressbook/customfieldswidget.h new file mode 100644 index 000000000..6ee10a39a --- /dev/null +++ b/kaddressbook/customfieldswidget.h @@ -0,0 +1,162 @@ +/* + This file is part of KAddressbook. + Copyright (c) 2004 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 CUSTOMFIELDSWIDGET_H +#define CUSTOMFIELDSWIDGET_H + +#include <kabc/addressee.h> +#include <kdialogbase.h> +#include <klocale.h> + +#include <qmap.h> +#include <qpair.h> +#include <qstringlist.h> +#include <qvaluevector.h> +#include <qwidget.h> + +#include "contacteditorwidget.h" + +class QCheckBox; +class QGridLayout; +class QLabel; +class QPushButton; +class QVBoxLayout; +class QWidget; + +class KComboBox; +class KLineEdit; + +typedef struct { + QString mIdentifier; + QString mTitle; + bool mGlobal; + + QLabel *mLabel; + QWidget *mWidget; + QHBoxLayout *mLayout; +} FieldRecord; + +typedef QValueList<FieldRecord> FieldRecordList; + +class AddFieldDialog : public KDialogBase +{ + Q_OBJECT + + public: + AddFieldDialog( QWidget *parent, const char *name = 0 ); + + QString title() const; + QString identifier() const; + QString type() const; + bool isGlobal() const; + + private slots: + void nameChanged( const QString& ); + + private: + KLineEdit *mTitle; + KComboBox *mType; + QCheckBox *mGlobal; + + QValueVector<QString> mTypeList; + QValueVector<QString> mTypeName; +}; + +class FieldWidget : public QWidget +{ + Q_OBJECT + + public: + FieldWidget( QWidget *parent, const char *name = 0 ); + + void addField( const QString &identifier, const QString &title, + const QString &type, bool isGlobal ); + + void removeField( const QString &identifier ); + + void loadContact( KABC::Addressee *addr ); + void storeContact( KABC::Addressee *addr ); + void setReadOnly( bool readOnly ); + + FieldRecordList fields() const { return mFieldList; } + + void removeLocalFields(); + void clearFields(); + + signals: + void changed(); + + private: + void recalculateLayout(); + + QVBoxLayout *mGlobalLayout; + QVBoxLayout *mLocalLayout; + QFrame *mSeparator; + + FieldRecordList mFieldList; +}; + +class CustomFieldsWidget : public KAB::ContactEditorWidget +{ + Q_OBJECT + + public: + CustomFieldsWidget( KABC::AddressBook *ab, QWidget *parent, const char *name = 0 ); + + void loadContact( KABC::Addressee *addr ); + void storeContact( KABC::Addressee *addr ); + void setReadOnly( bool readOnly ); + + private slots: + void addField(); + void removeField(); + + private: + void initGUI(); + + QStringList marshallFields( bool ) const; + + QPushButton *mAddButton; + QPushButton *mRemoveButton; + QGridLayout *mLayout; + + FieldWidget *mFieldWidget; + + KABC::Addressee mAddressee; +}; + +class CustomFieldsWidgetFactory : public KAB::ContactEditorWidgetFactory +{ + public: + KAB::ContactEditorWidget *createWidget( KABC::AddressBook *ab, QWidget *parent, const char *name ) + { + return new CustomFieldsWidget( ab, parent, name ); + } + + QString pageTitle() const { return i18n( "Custom Fields" ); } + QString pageIdentifier() const { return "custom_fields"; } +}; + +void splitField( const QString&, QString&, QString&, QString& ); + +#endif diff --git a/kaddressbook/dcopaddressbook.desktop b/kaddressbook/dcopaddressbook.desktop new file mode 100644 index 000000000..50ee3455d --- /dev/null +++ b/kaddressbook/dcopaddressbook.desktop @@ -0,0 +1,60 @@ +[Desktop Entry] +Type=ServiceType +X-KDE-ServiceType=DCOP/AddressBook +Comment=Address Book with a DCOP interface +Comment[af]=Adres boek met 'n DCOP koppelvlak +Comment[ar]=دفتر عناوين مع واجهة DCOP +Comment[be]=Адрасная кніга з DCOP інтэрфэйсам +Comment[bg]=Адресник с интерфейс DCOP +Comment[bs]=Adresar sa DCOP interfejsom +Comment[ca]=Llibreta d'adreces amb una interfície DCOP +Comment[cs]=Kniha adres s DCOP rozhraním +Comment[cy]=Llyfr Cyfeiriadau gyda Rhyngwyneb DCOP +Comment[da]=Adressebog med en DCOP-grænseflade +Comment[de]=Adressbuch mit DCOP-Schnittstelle +Comment[el]=Βιβλίο διευθύνσεων με ένα περιβάλλον χρήσης DCOP +Comment[eo]=Adresaro kun DCOP-interfaco +Comment[es]=Libreta de direcciones con un interfaz DCOP +Comment[et]=Aadressiraamat DCOP-liidesega +Comment[eu]=DCOP interfazedun helbide-liburua +Comment[fa]=کتاب نشانی با یک واسط DCOP +Comment[fi]=Osoitekirja DCOP-rajapinnalla +Comment[fr]=Carnet d'adresses avec une interface DCOP +Comment[fy]=Adresboek mei DCOP-ynterface +Comment[gl]=Libro de enderezos con interface DCOP +Comment[he]=פנקס כתובת עם ממשק DCOP +Comment[hi]=डीकॉप इंटरफेस सहित एक पता पुस्तिका +Comment[hu]=Címjegyzék DCOP-felülettel +Comment[is]=Vistfangaskrá með DCOP tengingu +Comment[it]=Rubrica indirizzi con un'interfaccia DCOP +Comment[ja]=DCOP インターフェースを持つアドレス帳 +Comment[ka]=წიგნაკი DCOP-ის ინტერფეისით +Comment[kk]=DCOP интерфейсті адрестік кітапшасы +Comment[km]=សៀវភៅអាសយដ្ឋានដែលមានចំណុចប្រទាក់ DCOP +Comment[ko]=DCOP 인터페이스를 사용하는 주소록 +Comment[lt]=Adresų knygelė su DCOP sąsaja +Comment[mk]=Адресар со DCOP-интерфејс +Comment[nb]=Adressebok med DCOP-grensesnitt +Comment[nds]=Adressbook mit DCOP-Koppelsteed +Comment[ne]=डीसीओपी ईन्टरफेससँगको ठेगाना पुस्तिका +Comment[nl]=Adresboek met DCOP-interface +Comment[nn]=Adressebok med DCOP-grensesnitt +Comment[pl]=Książka adresowa z interfejsem DCOP +Comment[pt]=Livro de Endereços com uma Interface de DCOP +Comment[pt_BR]=Livro de Endereços com uma interface DCOP +Comment[ro]=Carte de adrese cu interfaţă DCOP +Comment[ru]=Адресная книга с интерфейсом DCOP +Comment[se]=Čujuhusgirji mas lea DCOP-lákta +Comment[sk]=Kniha adries s DCOP rozhraním +Comment[sl]=Adresar z vmesnikom DCOP +Comment[sr]=Адресар са DCOP интерфејсом +Comment[sr@Latn]=Adresar sa DCOP interfejsom +Comment[sv]=Adressbok med DCOP-gränssnitt +Comment[ta]=முகவரிப்புத்தகத்துடன் DCOP முகப்பு +Comment[tg]=Китоби адрес бо интерфейси DCOP +Comment[tr]=DCOP Arayüzü Olan Adres Defteri +Comment[uk]=Адресна книга з інтерфейсом DCOP +Comment[uz]=DCOP interfeysli manzillar daftari +Comment[uz@cyrillic]=DCOP интерфейсли манзиллар дафтари +Comment[zh_CN]=具有 DCOP 接口的地址簿 +Comment[zh_TW]=有 DCOP 介面的通訊錄 diff --git a/kaddressbook/distributionlisteditor.cpp b/kaddressbook/distributionlisteditor.cpp new file mode 100644 index 000000000..a18b5493f --- /dev/null +++ b/kaddressbook/distributionlisteditor.cpp @@ -0,0 +1,284 @@ +/* + This file is part of KAddressBook. + Copyright (c) 2007 Klaralvdalens Datakonsult AB <frank@kdab.net> + + 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 "distributionlisteditor.h" +#include "distributionlisteditor_p.h" + +#include <libkdepim/addresseelineedit.h> +#include <libkdepim/distributionlist.h> +#include <libemailfunctions/email.h> + +#include <kabc/addressbook.h> + +#include <kapplication.h> +#include <kdialogbase.h> +#include <kglobal.h> +#include <kiconloader.h> +#include <klineedit.h> +#include <klocale.h> +#include <kmessagebox.h> + +#include <qlabel.h> +#include <qlayout.h> +#include <qsignalmapper.h> +#include <qtoolbutton.h> + +class KPIM::DistributionListEditor::EditorWidgetPrivate +{ +public: + QScrollView* scrollView; + QSignalMapper* mapper; + KABC::AddressBook* addressBook; + QString distListUid; + QLabel* nameLabel; + QLabel* memberListLabel; + KLineEdit* nameLineEdit; + QWidget* memberListWidget; + QVBoxLayout* addresseeLayout; + QValueList<KPIM::DistributionListEditor::Line*> addressees; + KPIM::DistributionList distributionList; + KPIM::DistributionListEditor::Line* addLineForEntry( const KPIM::DistributionList::Entry& entry ); + int lastLineId; +}; + + +KPIM::DistributionListEditor::Line::Line( KABC::AddressBook* book, QWidget* parent ) : QWidget( parent ), m_addressBook( book ) +{ + Q_ASSERT( m_addressBook ); + QBoxLayout* layout = new QHBoxLayout( this ); + layout->setSpacing( KDialog::spacingHint() ); + m_lineEdit = new KPIM::DistributionListEditor::LineEdit( this ); + connect( m_lineEdit, SIGNAL( textChanged( const QString& ) ), + this, SLOT( textChanged( const QString& ) ) ); + layout->addWidget( m_lineEdit ); + m_clearButton = new QToolButton( this ); + m_clearButton->setIconSet( KApplication::reverseLayout() ? SmallIconSet("locationbar_erase") : SmallIconSet( "clear_left" ) ); + m_clearButton->setEnabled( false ); + layout->addWidget( m_clearButton ); + connect( m_clearButton, SIGNAL( clicked() ), m_lineEdit, SLOT( clear() ) ); +} + +void KPIM::DistributionListEditor::Line::textChanged( const QString& text ) +{ + m_clearButton->setEnabled( !text.isEmpty() ); + if ( text.isEmpty() ) + emit cleared(); + emit textChanged(); +} + +void KPIM::DistributionListEditor::Line::setFocusToLineEdit() +{ + m_lineEdit->setFocus(); +} + +void KPIM::DistributionListEditor::Line::setEntry( const KPIM::DistributionList::Entry& entry ) +{ + m_uid = entry.addressee.uid(); + m_initialText = entry.addressee.fullEmail( entry.email ); + m_lineEdit->setText( m_initialText ); +} + +KABC::Addressee KPIM::DistributionListEditor::Line::findAddressee( const QString& name, const QString& email ) const +{ + if ( name.isEmpty() && email.isEmpty() ) + return KABC::Addressee(); + + typedef KABC::Addressee::List List; + const List byEmail = m_addressBook->findByEmail( email ); + if ( !byEmail.isEmpty() ) + { + const List::ConstIterator end = byEmail.end(); + for ( List::ConstIterator it = byEmail.begin(); it != end; ++it ) + { + if ( (*it).formattedName() == name ) + return *it; + } + return byEmail.first(); + } + // no entry found, create new addressee: + KABC::Addressee addressee; + addressee.setUid( KApplication::randomString( 10 ) ); + addressee.setFormattedName( name ); + addressee.setEmails( email ); + m_addressBook->insertAddressee( addressee ); + return addressee; +} + +KPIM::DistributionList::Entry KPIM::DistributionListEditor::Line::entry() const +{ + const QString text = m_lineEdit->text(); + QString name; + QString email; + KPIM::getNameAndMail(m_lineEdit->text(), name, email ); + + KPIM::DistributionList::Entry res; + if ( !m_uid.isNull() ) + { + const KABC::Addressee addr = m_addressBook->findByUid( m_uid ); + if ( m_initialText == text || addr.formattedName() == name ) + res.addressee = addr; + } + if ( res.addressee.isEmpty() ) + res.addressee = findAddressee( name, email ); + res.email = res.addressee.preferredEmail() != email ? email : QString(); + return res; +} + + +KPIM::DistributionListEditor::LineEdit::LineEdit( QWidget* parent ) : KPIM::AddresseeLineEdit( parent ) +{ +} + + +KPIM::DistributionListEditor::EditorWidget::EditorWidget( KABC::AddressBook* book, QWidget* parent ) + : KDialogBase( parent, /*name=*/0, /*modal=*/ true, /*caption=*/QString(), KDialogBase::Ok|KDialogBase::Cancel ), d( new DistributionListEditor::EditorWidgetPrivate ) +{ + d->addressBook = book; + Q_ASSERT( d->addressBook ); + d->lastLineId = 0; + d->mapper = new QSignalMapper( this ); + connect( d->mapper, SIGNAL( mapped( int ) ), + this, SLOT( lineTextChanged( int ) ) ); + setCaption( i18n( "Edit Distribution List" ) ); + QWidget* main = new QWidget( this ); + QVBoxLayout* mainLayout = new QVBoxLayout( main ); + mainLayout->setMargin( KDialog::marginHint() ); + mainLayout->setSpacing( KDialog::spacingHint() ); + + QHBoxLayout* nameLayout = new QHBoxLayout; + nameLayout->setSpacing( KDialog::spacingHint() ); + d->nameLabel = new QLabel( main ); + d->nameLabel->setText( i18n( "Name:" ) ); + nameLayout->addWidget( d->nameLabel ); + + d->nameLineEdit = new KLineEdit( main ); + nameLayout->addWidget( d->nameLineEdit ); + + mainLayout->addLayout( nameLayout ); + mainLayout->addSpacing( 30 ); + + d->memberListLabel = new QLabel( main ); + d->memberListLabel->setText( i18n( "Distribution list members:" ) ); + mainLayout->addWidget( d->memberListLabel ); + + d->scrollView = new QScrollView( main ); + d->scrollView->setFrameShape( QFrame::NoFrame ); + mainLayout->addWidget( d->scrollView ); + d->memberListWidget = new QWidget( d->scrollView->viewport() ); + d->memberListWidget->setSizePolicy( QSizePolicy::MinimumExpanding, QSizePolicy::MinimumExpanding ); + QVBoxLayout* memberLayout = new QVBoxLayout( d->memberListWidget ); + d->addresseeLayout = new QVBoxLayout; + d->addresseeLayout->setSpacing( KDialog::spacingHint() ); + memberLayout->addItem( d->addresseeLayout ); + memberLayout->addStretch(); + d->scrollView->addChild( d->memberListWidget ); + d->scrollView->setResizePolicy( QScrollView::AutoOneFit ); + + setMainWidget( main ); + + KPIM::DistributionListEditor::Line* const last = d->addLineForEntry( KPIM::DistributionList::Entry() ); + const QSize hint = sizeHint(); + resize( hint.width() * 1.5, hint.height() ); +} + +KPIM::DistributionListEditor::EditorWidget::~EditorWidget() +{ + delete d; +} + +void KPIM::DistributionListEditor::EditorWidget::lineTextChanged( int id ) +{ + if ( id != d->lastLineId ) + return; + d->addLineForEntry( KPIM::DistributionList::Entry() ); + d->scrollView->updateContents(); +} + +void KPIM::DistributionListEditor::EditorWidget::setDistributionList( const KPIM::DistributionList& list ) +{ + d->distListUid = list.uid(); + d->nameLineEdit->setText( list.name() ); + + using KPIM::DistributionListEditor::Line; + typedef QValueList<Line*>::ConstIterator ListIterator; + for ( ListIterator it = d->addressees.begin(), end = d->addressees.end(); it != end; ++it ) + { + delete *it; + } + d->addressees.clear(); + + typedef KPIM::DistributionList::Entry Entry; + const Entry::List entries = list.entries( d->addressBook ); + + for ( Entry::List::ConstIterator it = entries.begin(), end = entries.end(); it != end; ++it ) + { + d->addLineForEntry( *it ); + } + KPIM::DistributionListEditor::Line* const last = d->addLineForEntry( Entry() ); + last->setFocusToLineEdit(); +} + +KPIM::DistributionListEditor::Line* KPIM::DistributionListEditor::EditorWidgetPrivate::addLineForEntry( const KPIM::DistributionList::Entry& entry ) +{ + KPIM::DistributionListEditor::Line* line = new KPIM::DistributionListEditor::Line( addressBook, memberListWidget ); + line->setEntry( entry ); + addresseeLayout->addWidget( line ); + addressees.append( line ); + QObject::connect( line, SIGNAL( textChanged() ), + mapper, SLOT( map() ) ); + mapper->setMapping( line, ++lastLineId ); + line->setShown( true ); + return line; +} + +void KPIM::DistributionListEditor::EditorWidget::slotOk() +{ + const QString name = d->nameLineEdit->text(); + const KPIM::DistributionList existing = KPIM::DistributionList::findByName( d->addressBook, name ); + if ( !existing.isEmpty() && existing.uid() != d->distListUid ) + { + KMessageBox::error( this, i18n( "A distribution list with the name %1 already exists. Please choose another name." ).arg( name ), i18n( "Name in Use" ) ); + return; + } + + KPIM::DistributionList list; + list.setUid( d->distListUid.isNull() ? KApplication::randomString( 10 ) :d->distListUid ); + list.setName( name ); + typedef QValueList<KPIM::DistributionListEditor::Line*>::ConstIterator ListIterator; + for ( ListIterator it = d->addressees.begin(), end = d->addressees.end(); it != end; ++it ) + { + const KPIM::DistributionList::Entry entry = (*it)->entry(); + if ( entry.addressee.isEmpty() ) + continue; + list.insertEntry( entry.addressee, entry.email ); + } + d->distributionList = list; + accept(); +} + +KPIM::DistributionList KPIM::DistributionListEditor::EditorWidget::distributionList() const +{ + return d->distributionList; +} + +#include "distributionlisteditor.moc" +#include "distributionlisteditor_p.moc" diff --git a/kaddressbook/distributionlisteditor.h b/kaddressbook/distributionlisteditor.h new file mode 100644 index 000000000..193ff83f1 --- /dev/null +++ b/kaddressbook/distributionlisteditor.h @@ -0,0 +1,62 @@ +/* + This file is part of KAddressBook. + Copyright (c) 2007 Klaralvdalens Datakonsult AB <frank@kdab.net> + + 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 KPIM_DISTRIBUTIONLISTEDITOR_H +#define KPIM_DISTRIBUTIONLISTEDITOR_H + +#include <kdialogbase.h> + +namespace KABC { + class AddressBook; +} + +namespace KPIM { + +class DistributionList; + +namespace DistributionListEditor { + +class EditorWidgetPrivate; +class EditorWidget : public KDialogBase +{ + Q_OBJECT +public: + explicit EditorWidget( KABC::AddressBook* book, QWidget* parent = 0 ); + ~EditorWidget(); + + void setDistributionList( const KPIM::DistributionList& list ); + KPIM::DistributionList distributionList() const; + +private slots: + + //override + void slotOk(); + void lineTextChanged( int id ); + +private: + EditorWidgetPrivate* const d; +}; + +} // namespace DisributionListEditor +} // namespace KPIM + +#endif // KPIM_DISTRIBUTIONLISTEDITOR_H diff --git a/kaddressbook/distributionlisteditor_p.h b/kaddressbook/distributionlisteditor_p.h new file mode 100644 index 000000000..e8708698f --- /dev/null +++ b/kaddressbook/distributionlisteditor_p.h @@ -0,0 +1,83 @@ +/* + This file is part of KAddressBook. + Copyright (c) 2007 Klaralvdalens Datakonsult AB <frank@kdab.net> + + 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 KPIM_DISTRIBUTIONLISTEDITOR_P_H +#define KPIM_DISTRIBUTIONLISTEDITOR_P_H + +#include <libkdepim/addresseelineedit.h> +#include <libkdepim/distributionlist.h> + +#include <qpushbutton.h> +#include <qstring.h> + +class QToolButton; + +namespace KABC { + class Addressee; + class AddressBook; +} + +namespace KPIM { +namespace DistributionListEditor { + +class LineEdit : public KPIM::AddresseeLineEdit +{ + Q_OBJECT +public: + explicit LineEdit( QWidget* parent = 0 ); +}; + + +class Line : public QWidget +{ + Q_OBJECT +public: + explicit Line( KABC::AddressBook* book, QWidget* parent = 0 ); + + void setEntry( const KPIM::DistributionList::Entry& entry ); + KPIM::DistributionList::Entry entry() const; + void setFocusToLineEdit(); + +signals: + void cleared(); + void textChanged(); + +private: + KABC::Addressee findAddressee( const QString& name, const QString& email ) const; + +private slots: + void textChanged( const QString& ); + +private: + QString m_uid; + QString m_initialText; + LineEdit* m_lineEdit; + QToolButton* m_clearButton; + KABC::AddressBook* m_addressBook; +}; + +} // namespace DisributionListEditor +} // namespace KPIM + +#endif // KPIM_DISTRIBUTIONLISTEDITOR_P_H + + diff --git a/kaddressbook/distributionlistentryview.cpp b/kaddressbook/distributionlistentryview.cpp new file mode 100644 index 000000000..2db13f808 --- /dev/null +++ b/kaddressbook/distributionlistentryview.cpp @@ -0,0 +1,140 @@ +#include "distributionlistentryview.h" +#include "imagewidget.h" +#include <interfaces/core.h> + +#include <libkdepim/resourceabc.h> + +#include <kabc/addressbook.h> +#include <kabc/resource.h> + +#include <kdialog.h> +#include <kiconloader.h> +#include <klocale.h> +#include <kurllabel.h> + +#include <qbuttongroup.h> +#include <qcombobox.h> +#include <qlabel.h> +#include <qlayout.h> +#include <qradiobutton.h> +#include <qstringlist.h> +#include <qvbuttongroup.h> + +KAB::DistributionListEntryView::DistributionListEntryView( KAB::Core* core, QWidget* parent ) : QWidget( parent ), m_core( core ), m_emailGroup( 0 ) +{ + m_mainLayout = new QVBoxLayout( this ); + m_mainLayout->setSpacing( KDialog::spacingHint() ); + m_mainLayout->setMargin( KDialog::marginHint() ); + + QBoxLayout* headerLayout = new QHBoxLayout; + headerLayout->setSpacing( KDialog::spacingHint() * 3 ); + + m_imageLabel = new QLabel( this ); + m_imageLabel->setAutoResize( true ); + headerLayout->addWidget( m_imageLabel, 0, Qt::AlignTop ); + + m_addresseeLabel = new QLabel( this ); + headerLayout->addWidget( m_addresseeLabel, 0, Qt::AlignTop ); + headerLayout->addStretch(); + + m_mainLayout->addItem( headerLayout ); + + QBoxLayout* distLayout = new QHBoxLayout; + distLayout->setSpacing( KDialog::spacingHint() ); + + QLabel* distLabel = new QLabel( this ); + distLabel->setText( i18n( "<b>Distribution list:</b>" ) ); + distLabel->setAlignment( Qt::SingleLine ); + distLayout->addWidget( distLabel ); + + m_distListLabel = new KURLLabel( this ); + distLabel->setBuddy( m_distListLabel ); + connect( m_distListLabel, SIGNAL( leftClickedURL( const QString& ) ), + this, SIGNAL( distributionListClicked( const QString& ) ) ); + distLayout->addWidget( m_distListLabel ); + distLayout->addStretch(); + m_mainLayout->addItem( distLayout ); + + QLabel* emailLabel = new QLabel( this ); + emailLabel->setText( i18n( "<b>Email address to use in this list:</b>" ) ); + emailLabel->setAlignment( Qt::SingleLine ); + m_mainLayout->addWidget( emailLabel ); + + QBoxLayout* emailLayout = new QHBoxLayout; + emailLayout->setSpacing( KDialog::spacingHint() ); + emailLayout->addSpacing( 30 ); + + m_radioLayout = new QGridLayout; + emailLayout->addItem( m_radioLayout ); + emailLayout->addStretch(); + m_mainLayout->addItem( emailLayout ); + + QBoxLayout* resourceLayout = new QHBoxLayout; + resourceLayout->setSpacing( KDialog::spacingHint() ); + m_resourceLabel = new QLabel( this ); + resourceLayout->addWidget( m_resourceLabel ); + resourceLayout->addStretch(); + + m_mainLayout->addItem( resourceLayout ); + m_mainLayout->addStretch(); +} + +void KAB::DistributionListEntryView::emailButtonClicked( int id ) +{ + const QString email = m_idToEmail[ id ]; + if ( m_entry.email == email ) + return; + m_list.removeEntry( m_entry.addressee, m_entry.email ); + m_entry.email = email; + m_list.insertEntry( m_entry.addressee, m_entry.email ); + m_core->addressBook()->insertAddressee( m_list ); +} + +void KAB::DistributionListEntryView::clear() +{ + setEntry( KPIM::DistributionList(), KPIM::DistributionList::Entry() ); +} + +void KAB::DistributionListEntryView::setEntry( const KPIM::DistributionList& list, const KPIM::DistributionList::Entry& entry ) +{ + m_list = list; + m_entry = entry; + + delete m_emailGroup; + m_emailGroup = 0; + + QPixmap pixmap; + pixmap.convertFromImage( m_entry.addressee.photo().data() ); + m_imageLabel->setPixmap( pixmap.isNull() ? KGlobal::iconLoader()->loadIcon( "personal", KIcon::Desktop ) : pixmap ); + m_addresseeLabel->setText( i18n( "Formatted name, role, organization", "<qt><h2>%1</h2><p>%2<br/>%3</p></qt>" ).arg( m_entry.addressee.formattedName(), m_entry.addressee.role(), m_entry.addressee.organization() ) ); + m_distListLabel->setURL( m_list.name() ); + m_distListLabel->setText( m_list.name() ); + m_resourceLabel->setText( i18n( "<b>Address book:</b> %1" ).arg( m_entry.addressee.resource() ? m_entry.addressee.resource()->resourceName() : QString() ) ); + m_resourceLabel->setAlignment( Qt::SingleLine ); + + m_emailGroup = new QVButtonGroup( this ); + m_emailGroup->setFlat( true ); + m_emailGroup->setExclusive( true ); + m_emailGroup->setFrameShape( QFrame::NoFrame ); + + const QString preferred = m_entry.email.isNull() ? m_entry.addressee.preferredEmail() : m_entry.email; + const QStringList mails = m_entry.addressee.emails(); + m_idToEmail.clear(); + for ( QStringList::ConstIterator it = mails.begin(); it != mails.end(); ++it ) + { + QRadioButton* button = new QRadioButton( m_emailGroup ); + button->setText( *it ); + m_idToEmail.insert( m_emailGroup->insert( button ), *it ); + if ( *it == preferred ) + button->setChecked( true ); + button->setShown( true ); + } + connect( m_emailGroup, SIGNAL( clicked( int ) ), + this, SLOT( emailButtonClicked( int ) ) ); + m_radioLayout->addWidget( m_emailGroup, 0, 0 ); + m_emailGroup->setShown( true ); + m_mainLayout->invalidate(); +} + + +#include "distributionlistentryview.moc" diff --git a/kaddressbook/distributionlistentryview.h b/kaddressbook/distributionlistentryview.h new file mode 100644 index 000000000..1fbf9f2d7 --- /dev/null +++ b/kaddressbook/distributionlistentryview.h @@ -0,0 +1,58 @@ +#ifndef KAB_DISTRIBUTIONLISTENTRYVIEW_H +#define KAB_DISTRIBUTIONLISTENTRYVIEW_H + +#include <libkdepim/distributionlist.h> + +#include <qmap.h> +#include <qstring.h> +#include <qwidget.h> + +class QBoxLayout; +class QButtonGroup; +class QComboBox; +class QGridLayout; +class QLabel; + +class KURLLabel; + +class ImageButton; + +namespace KAB { + +class Core; + +class DistributionListEntryView : public QWidget +{ + Q_OBJECT + +public: + explicit DistributionListEntryView( KAB::Core* core, QWidget* parent = 0 ); + void setEntry( const KPIM::DistributionList& list, const KPIM::DistributionList::Entry& entry ); + +public slots: + void clear(); + +signals: + void distributionListClicked( const QString& ); + +private slots: + void emailButtonClicked( int id ); + +private: + QMap<int, QString> m_idToEmail; + KAB::Core* m_core; + KPIM::DistributionList m_list; + KPIM::DistributionList::Entry m_entry; + QGridLayout* m_radioLayout; + QBoxLayout* m_mainLayout; + QButtonGroup* m_emailGroup; + QLabel* m_addresseeLabel; + KURLLabel* m_distListLabel; + QLabel* m_imageLabel; + QLabel* m_resourceLabel; + QMap<int, QString> m_indexToIdentifier; +}; + +} + +#endif // KAB_DISTRIBUTIONLISTENTRYVIEW_H diff --git a/kaddressbook/distributionlistpicker.cpp b/kaddressbook/distributionlistpicker.cpp new file mode 100644 index 000000000..c2eb3ee00 --- /dev/null +++ b/kaddressbook/distributionlistpicker.cpp @@ -0,0 +1,142 @@ +/* + This file is part of KAddressBook. + Copyright (c) 2007 Klaralvdalens Datakonsult AB <frank@kdab.net> + + 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 "distributionlistpicker.h" +#include "config.h" + +#ifdef KDEPIM_NEW_DISTRLISTS +#include <libkdepim/distributionlist.h> +#endif + +#include <kabc/addressbook.h> + +#include <kapplication.h> +#include <kinputdialog.h> +#include <klistbox.h> +#include <klocale.h> +#include <kmessagebox.h> + +#include <qlabel.h> +#include <qlayout.h> +#include <qpushbutton.h> +#include <qregexp.h> +#include <qvalidator.h> + +KPIM::DistributionListPickerDialog::DistributionListPickerDialog( KABC::AddressBook* book, QWidget* parent ) : KDialogBase( parent, 0, true, QString(), Ok | Cancel | User1 ), m_book( book ) +{ + Q_ASSERT( m_book ); + setModal( true ); + enableButton( Ok, false ); + setButtonText( User1, i18n( "Add New Distribution List" ) ); + QWidget* main = new QWidget( this ); + QGridLayout* layout = new QGridLayout( main ); + layout->setSpacing( KDialog::spacingHint() ); + m_label = new QLabel( main ); + layout->addWidget( m_label, 0, 0 ); + m_listBox = new KListBox( main ); + layout->addWidget( m_listBox, 1, 0 ); + connect( m_listBox, SIGNAL( highlighted( const QString& ) ), + this, SLOT( entrySelected( const QString& ) ) ); + connect( m_listBox, SIGNAL( selected( const QString& ) ), + this, SLOT( entrySelected( const QString& ) ) ); + setMainWidget( main ); +#ifdef KDEPIM_NEW_DISTRLISTS + typedef QValueList<KPIM::DistributionList> DistListList; + const DistListList lists = KPIM::DistributionList::allDistributionLists( m_book ); + for ( DistListList::ConstIterator it = lists.begin(); it != lists.end(); ++it ) + { + m_listBox->insertItem ( (*it).name() ); + } +#endif +} + +void KPIM::DistributionListPickerDialog::entrySelected( const QString& name ) +{ + actionButton( Ok )->setEnabled( !name.isNull() ); +} + +void KPIM::DistributionListPickerDialog::setLabelText( const QString& text ) +{ + m_label->setText( text ); +} + +void KPIM::DistributionListPickerDialog::slotUser1() +{ +#ifdef KDEPIM_NEW_DISTRLISTS + const QValueList<KPIM::DistributionList> lists = KPIM::DistributionList::allDistributionLists( m_book ); + QStringList listNames; + for ( QValueList<KPIM::DistributionList>::ConstIterator it = lists.begin(); it != lists.end(); ++it ) + { + listNames += (*it).name(); + } + + bool validName = false; + do + { + QRegExpValidator validator( QRegExp( "\\S+.*" ), 0 ); + const QString name = KInputDialog::getText( i18n( "Enter Name" ), i18n( "Enter a name for the new distribution list:" ), QString(), 0, this, 0, &validator ).stripWhiteSpace(); + if ( name.isEmpty() ) + return; + + validName = !listNames.contains( name ); + + if ( validName ) + { + KPIM::DistributionList list; + list.setName( name ); + list.setUid( KApplication::randomString( 10 ) ); + m_book->insertAddressee( list ); + + m_listBox->insertItem( name ); + QListBoxItem* item = m_listBox->findItem( name ); + m_listBox->setSelected( item, true ); + } + else + { + KMessageBox::error( this, i18n( "A distribution list with the the name %1 already exists. Please choose another name" ).arg( name ), i18n( "Name Exists" ) ); + } + } + while ( !validName ); +#endif +} + + +void KPIM::DistributionListPickerDialog::slotOk() +{ + QListBoxItem* item = m_listBox->selectedItem(); + m_selectedDistributionList = item ? item->text() : QString(); + KDialogBase::slotOk(); +} + +void KPIM::DistributionListPickerDialog::slotCancel() +{ + m_selectedDistributionList = QString(); + KDialogBase::slotCancel(); +} + +QString KPIM::DistributionListPickerDialog::selectedDistributionList() const +{ + return m_selectedDistributionList; +} + +#include "distributionlistpicker.moc" + diff --git a/kaddressbook/distributionlistpicker.h b/kaddressbook/distributionlistpicker.h new file mode 100644 index 000000000..0081fc62f --- /dev/null +++ b/kaddressbook/distributionlistpicker.h @@ -0,0 +1,69 @@ +/* + This file is part of KAddressBook. + Copyright (c) 2007 Klaralvdalens Datakonsult AB <frank@kdab.net> + + 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 KPIM_DISTRIBUTIONLISTPICKER_H +#define KPIM_DISTRIBUTIONLISTPICKER_H + +#include <kdialogbase.h> + +#include <qstring.h> + +class KListBox; + +namespace KABC { + class AddressBook; +} + +namespace KPIM { + +class DistributionListPickerDialog : public KDialogBase +{ + Q_OBJECT +public: + explicit DistributionListPickerDialog( KABC::AddressBook* book, QWidget* parent = 0 ); + QString selectedDistributionList() const; + + void setLabelText( const QString& text ); + +private slots: + + //override + void slotOk(); + + //override + void slotCancel(); + + //override + void slotUser1(); + + void entrySelected( const QString& name ); + +private: + KABC::AddressBook* m_book; + QLabel* m_label; + KListBox* m_listBox; + QString m_selectedDistributionList; +}; + +} //namespace KPIM + +#endif // KPIM_DISTRIBUTIONLISTPICKER_H diff --git a/kaddressbook/editors/Makefile.am b/kaddressbook/editors/Makefile.am new file mode 100644 index 000000000..e611bb5ea --- /dev/null +++ b/kaddressbook/editors/Makefile.am @@ -0,0 +1,32 @@ +INCLUDES = -I$(top_srcdir) -I$(top_srcdir)/kaddressbook/interfaces \ + -I$(top_srcdir)/kaddressbook \ + -I$(top_srcdir)/certmanager/lib \ + -I$(top_srcdir)/libkdenetwork \ + -I$(top_builddir)/kaddressbook/editors \ + $(GPGME_CFLAGS) \ + $(all_includes) + +kde_module_LTLIBRARIES = libkaddrbk_cryptosettings.la + +XXLIBS = $(top_builddir)/kaddressbook/interfaces/libkabinterfaces.la \ + $(top_builddir)/certmanager/lib/libkleopatra.la + +libkaddrbk_cryptosettings_la_SOURCES = cryptowidget.cpp +libkaddrbk_cryptosettings_la_LDFLAGS = -module $(KDE_PLUGIN) $(KDE_RPATH) $(all_libraries) # -no-undefined +libkaddrbk_cryptosettings_la_LIBADD = $(XXLIBS) + +noinst_HEADERS = cryptowidget.h imeditorwidget.h imaddresswidget.h + +METASOURCES = AUTO + +SUBDIRS = protocols icons +servicedir = $(kde_servicesdir)/kaddressbook +service_DATA = cryptosettings.desktop + +servicetypedir = $(kde_servicetypesdir) +servicetype_DATA = kaddressbookimprotocol.desktop + +noinst_LTLIBRARIES = libkabim.la +libkabim_la_SOURCES = imeditorwidget.cpp imeditorbase.ui imaddressbase.ui imaddresswidget.cpp +libkabim_la_LDFLAGS = $(all_libraries) $(KDE_RPATH) -no-undefined +libkabim_la_LIBADD = $(top_builddir)/kaddressbook/interfaces/libkabinterfaces.la diff --git a/kaddressbook/editors/cryptosettings.desktop b/kaddressbook/editors/cryptosettings.desktop new file mode 100644 index 000000000..90ea108b7 --- /dev/null +++ b/kaddressbook/editors/cryptosettings.desktop @@ -0,0 +1,56 @@ +[Desktop Entry] +X-KDE-Library=libkaddrbk_cryptosettings +Name=Crypto Preferences +Name[af]=Kripto Voorkeure +Name[be]=Перавагі крыптаграфіі +Name[bg]=Шифроване +Name[bs]=Postavke kriptografije +Name[ca]=Preferències de criptografia +Name[cs]=Nastavení šifrování +Name[da]=Krypto-indstillinger +Name[de]=Kryptographie-Einstellungen +Name[el]=Προτιμήσεις κρυπτογραφίας +Name[eo]=Agordoj pri Ĉifrado +Name[es]=Preferencias de cifrado +Name[et]=Krüptoseadistused +Name[eu]=Kriptografia hobespenak +Name[fa]=تنظیمات مخفی +Name[fi]=Salauksen asetukset +Name[fr]=Préférences de chiffrement +Name[fy]=Fersiferingynstellings +Name[gl]=Preferencias de Cifraxe +Name[he]=מאפייני הצפנה +Name[hu]=Titkosítási beállítások +Name[is]=Stillingar dulritunar +Name[it]=Preferenze crittografia +Name[ja]=暗号の設定 +Name[ka]=დაშიფრვის პარამეტრები +Name[kk]=Шифрлау параметрлері +Name[km]=ចំណង់ចំណូលចិត្ត Crypto +Name[ko]=암호화 설정 +Name[lt]=Šifravimo pasirinkimai +Name[ms]=Keutamaan Kripto +Name[nb]=Krypteringsinnstillinger +Name[nds]=Verslöteln-Instellen +Name[ne]=गुप्तिकरण प्राथमिकता +Name[nl]=Versleutelingsinstellingen +Name[nn]=Krypteringsinnstillinger +Name[pl]=Ustawienia kryptograficzne +Name[pt]=Preferências de Encriptação +Name[pt_BR]=Configurações de Criptografia +Name[ru]=Настройки шифрования +Name[se]=Krypterenheivehusat +Name[sk]=Nastavenie šifrovania +Name[sl]=Lastnosti šifriranja +Name[sr]=Криптографска подешавања +Name[sr@Latn]=Kriptografska podešavanja +Name[sv]=Krypteringsinställningar +Name[ta]= க்ரிப்டோ முன்னுரிமைகள் +Name[tg]=Танзимоти рамзгузорӣ +Name[tr]=Şifreleme Özellikleri +Name[uk]=Параметри шифрування +Name[zh_CN]=加密首选项 +Name[zh_TW]=加密設定 +Type=Service +ServiceTypes=KAddressBook/ContactEditorWidget +X-KDE-KAddressBook-CEWPluginVersion=1 diff --git a/kaddressbook/editors/cryptowidget.cpp b/kaddressbook/editors/cryptowidget.cpp new file mode 100644 index 000000000..d2d5917f9 --- /dev/null +++ b/kaddressbook/editors/cryptowidget.cpp @@ -0,0 +1,227 @@ +/* + This file is part of KAddressBook. + Copyright (c) 2004 Klar�vdalens Datakonsult AB + + 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 <config.h> +#include "certmanager/lib/ui/keyrequester.h" +#include "certmanager/lib/cryptplugfactory.h" +#include "certmanager/lib/cryptplugwrapper.h" +#include "certmanager/lib/kleo/enum.h" + +#include "gpgmepp/data.h" +#include "gpgmepp/key.h" + +#include <kdebug.h> +#include <kdialog.h> +#include <kiconloader.h> +#include <klocale.h> + +#include <qlayout.h> +#include <qlabel.h> +#include <qcheckbox.h> +#include <qcombobox.h> +#include <qpushbutton.h> +#include <qvgroupbox.h> +#include <qhbox.h> + +#include "cryptowidget.h" + +extern "C" { + void *init_libkaddrbk_cryptosettings() + { + return ( new CryptoWidgetFactory ); + } +} + +CryptoWidgetFactory::CryptoWidgetFactory() +{ + KGlobal::locale()->insertCatalogue( "libkleopatra" ); + KGlobal::iconLoader()->addAppDir( "libkleopatra" ); +} + +QString CryptoWidgetFactory::pageTitle() const +{ + return i18n( "Crypto Settings" ); +} + +QString CryptoWidgetFactory::pageIdentifier() const +{ + return "crypto"; +} + +CryptoWidget::CryptoWidget( KABC::AddressBook *ab, QWidget *parent, const char *name ) + : KAB::ContactEditorWidget( ab, parent, name ), mReadOnly( false ) +{ + QGridLayout *topLayout = new QGridLayout( this, 2, 5, KDialog::marginHint(), + KDialog::spacingHint() ); + topLayout->setColStretch( 1, 1 ); + topLayout->setRowStretch( 4, 1 ); + + QVGroupBox* protGB = new QVGroupBox( i18n( "Allowed Protocols" ), this ); + topLayout->addMultiCellWidget( protGB, 0, 0, 0, 1 ); + + uint msgFormat = 1; + for ( uint i = 0 ; i < NumberOfProtocols ; ++i ) { + Kleo::CryptoMessageFormat f = static_cast<Kleo::CryptoMessageFormat>( msgFormat ); + mProtocolCB[ i ] = new QCheckBox( Kleo::cryptoMessageFormatToLabel( f ), protGB ); + connect( mProtocolCB[i], SIGNAL( clicked() ), this, SLOT( setModified() ) ); + + // Iterating over a bitfield means *2 every time + msgFormat *= 2; + } + + QLabel* l = new QLabel( i18n( "Preferred OpenPGP encryption key:" ), this ); + topLayout->addWidget( l, 1, 0 ); + + mPgpKey = new Kleo::EncryptionKeyRequester( true, Kleo::EncryptionKeyRequester::OpenPGP, this ); + topLayout->addWidget( mPgpKey, 1, 1 ); + + l = new QLabel( i18n( "Preferred S/MIME encryption certificate:" ), this ); + topLayout->addWidget( l, 2, 0 ); + + mSmimeCert = new Kleo::EncryptionKeyRequester( true, Kleo::EncryptionKeyRequester::SMIME, this ); + topLayout->addWidget( mSmimeCert, 2, 1 ); + + QGroupBox* box = new QVGroupBox( i18n( "Message Preference" ), this ); + topLayout->addMultiCellWidget( box, 3, 3, 0, 1 ); + + + // Send preferences/sign (see certmanager/lib/kleo/enum.h) + QHBox* hbox = new QHBox( box ); + + l = new QLabel( i18n( "Sign:" ), hbox ); + + mSignPref = new QComboBox( false, hbox ); + for ( unsigned int i = Kleo::UnknownSigningPreference; i < Kleo::MaxSigningPreference ; ++i ) + mSignPref->insertItem( Kleo::signingPreferenceToLabel( + static_cast<Kleo::SigningPreference>( i ) ) ); + + // Send preferences/encrypt (see certmanager/lib/kleo/enum.h) + hbox = new QHBox( box ); + + l = new QLabel( i18n("Encrypt:"), hbox ); + + mCryptPref = new QComboBox( false, hbox ); + for ( unsigned int i = Kleo::UnknownPreference; i < Kleo::MaxEncryptionPreference ; ++i ) + mCryptPref->insertItem( Kleo::encryptionPreferenceToLabel( + static_cast<Kleo::EncryptionPreference>( i ) ) ); + + // Emit "changed()" signal + connect( mSignPref, SIGNAL( activated(int) ), this, SLOT( setModified() ) ); + connect( mCryptPref, SIGNAL( activated(int) ), this, SLOT( setModified() ) ); + // Not optimal, but KeyRequester doesn't emit any signals when the key changes + connect( mPgpKey->eraseButton(), SIGNAL( clicked() ), this, SLOT( setModified() ) ); + connect( mPgpKey->dialogButton(), SIGNAL( clicked() ), this, SLOT( setModified() ) ); + connect( mSmimeCert->eraseButton(), SIGNAL( clicked() ), this, SLOT( setModified() ) ); + connect( mSmimeCert->dialogButton(), SIGNAL( clicked() ), this, SLOT( setModified() ) ); +} + +CryptoWidget::~CryptoWidget() +{ +} + +void CryptoWidget::loadContact( KABC::Addressee *addr ) +{ + bool blocked = signalsBlocked(); + blockSignals( true ); + + QStringList lst = QStringList::split( ',', addr->custom( "KADDRESSBOOK", + "CRYPTOPROTOPREF" ) ); + uint cryptoFormats = Kleo::stringListToCryptoMessageFormats( lst ); + + uint msgFormat = 1; + for ( uint i = 0 ; i < NumberOfProtocols ; ++i, msgFormat *= 2 ) { + mProtocolCB[i]->setChecked( cryptoFormats & msgFormat ); + } + + mSignPref->setCurrentItem( Kleo::stringToSigningPreference( addr->custom( "KADDRESSBOOK", + "CRYPTOSIGNPREF" ) ) ); + mCryptPref->setCurrentItem( Kleo::stringToEncryptionPreference( addr->custom( "KADDRESSBOOK", + "CRYPTOENCRYPTPREF" ) ) ); + + // We dont use the contents of addr->key(...) because we want just a ref. + // to the key/cert. stored elsewhere. + + mPgpKey->setFingerprints( QStringList::split( ",", addr->custom( "KADDRESSBOOK", "OPENPGPFP" ) ) ); + mSmimeCert->setFingerprints( QStringList::split( ",", addr->custom( "KADDRESSBOOK", "SMIMEFP" ) ) ); + + blockSignals( blocked ); +} + +void CryptoWidget::storeContact( KABC::Addressee *addr ) +{ + uint cryptoFormats = 0; + uint msgFormat = 1; + for ( uint i = 0 ; i < NumberOfProtocols ; ++i, msgFormat *= 2 ) { + if ( mProtocolCB[ i ]->isChecked() ) + cryptoFormats |= msgFormat; + } + + QStringList lst = Kleo::cryptoMessageFormatsToStringList( cryptoFormats ); + if ( !lst.isEmpty() ) + addr->insertCustom( "KADDRESSBOOK", "CRYPTOPROTOPREF", lst.join( "," ) ); + else + addr->removeCustom( "KADDRESSBOOK", "CRYPTOPROTOPREF" ); + + Kleo::SigningPreference signPref = + static_cast<Kleo::SigningPreference>( mSignPref->currentItem() ); + if ( signPref != Kleo::UnknownSigningPreference ) + addr->insertCustom( "KADDRESSBOOK", "CRYPTOSIGNPREF", + Kleo::signingPreferenceToString( signPref ) ); + else + addr->removeCustom( "KADDRESSBOOK", "CRYPTOSIGNPREF" ); + + Kleo::EncryptionPreference encryptPref = + static_cast<Kleo::EncryptionPreference>( mCryptPref->currentItem() ); + if ( encryptPref != Kleo::UnknownPreference ) + addr->insertCustom( "KADDRESSBOOK", "CRYPTOENCRYPTPREF", + Kleo::encryptionPreferenceToString( encryptPref ) ); + else + addr->removeCustom( "KADDRESSBOOK", "CRYPTOENCRYPTPREF" ); + + QStringList pfp = mPgpKey->fingerprints(); + QStringList sfp = mSmimeCert->fingerprints(); + + if ( !pfp.isEmpty() ) + addr->insertCustom( "KADDRESSBOOK", "OPENPGPFP", pfp.join( "," ) ); + else + addr->removeCustom( "KADDRESSBOOK", "OPENPGPFP" ); + + if ( !sfp.isEmpty() ) + addr->insertCustom( "KADDRESSBOOK", "SMIMEFP", sfp.join( "," ) ); + else + addr->removeCustom( "KADDRESSBOOK", "SMIMEFP" ); +} + +void CryptoWidget::setReadOnly( bool readOnly ) +{ + mReadOnly = readOnly; + for ( uint i = 0 ; i < NumberOfProtocols ; ++i ) + mProtocolCB[ i ]->setEnabled( !readOnly ); + + mSignPref->setEnabled( !readOnly ); + mCryptPref->setEnabled( !readOnly ); + mPgpKey->setEnabled( !readOnly ); + mSmimeCert->setEnabled( !readOnly ); +} + +#include "cryptowidget.moc" diff --git a/kaddressbook/editors/cryptowidget.h b/kaddressbook/editors/cryptowidget.h new file mode 100644 index 000000000..de2c7bfcc --- /dev/null +++ b/kaddressbook/editors/cryptowidget.h @@ -0,0 +1,71 @@ +/* + This file is part of KAddressBook. + Copyright (c) 2004 Klarlvdalens Datakonsult AB + + 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 CRYPTOWIDGET_H +#define CRYPTOWIDGET_H + +#include "contacteditorwidget.h" + +class QComboBox; + +namespace Kleo { + class KeyRequester; +} +class QCheckBox; + +class CryptoWidget : public KAB::ContactEditorWidget +{ + Q_OBJECT + + public: + CryptoWidget( KABC::AddressBook *ab, QWidget *parent, const char *name = 0 ); + ~CryptoWidget(); + + void loadContact( KABC::Addressee *addr ); + void storeContact( KABC::Addressee *addr ); + void setReadOnly( bool readOnly ); + + private: + enum { NumberOfProtocols = 4 }; + QCheckBox* mProtocolCB[NumberOfProtocols]; + QComboBox* mSignPref; + QComboBox* mCryptPref; + Kleo::KeyRequester* mPgpKey; + Kleo::KeyRequester* mSmimeCert; + bool mReadOnly; +}; + +class CryptoWidgetFactory : public KAB::ContactEditorWidgetFactory +{ + public: + CryptoWidgetFactory(); + KAB::ContactEditorWidget *createWidget( KABC::AddressBook *ab, QWidget *parent, const char *name ) + { + return new CryptoWidget( ab, parent, name ); + } + + QString pageTitle() const; + QString pageIdentifier() const; +}; + +#endif diff --git a/kaddressbook/editors/icons/Makefile.am b/kaddressbook/editors/icons/Makefile.am new file mode 100644 index 000000000..828085c74 --- /dev/null +++ b/kaddressbook/editors/icons/Makefile.am @@ -0,0 +1,3 @@ +kaddressbookicondir = $(kde_datadir)/kaddressbook/icons +kaddressbookicon_ICON = AUTO + diff --git a/kaddressbook/editors/icons/cr16-app-aim_protocol.png b/kaddressbook/editors/icons/cr16-app-aim_protocol.png Binary files differnew file mode 100644 index 000000000..1e89df85c --- /dev/null +++ b/kaddressbook/editors/icons/cr16-app-aim_protocol.png diff --git a/kaddressbook/editors/icons/cr16-app-gadu_protocol.png b/kaddressbook/editors/icons/cr16-app-gadu_protocol.png Binary files differnew file mode 100644 index 000000000..46f062c3d --- /dev/null +++ b/kaddressbook/editors/icons/cr16-app-gadu_protocol.png diff --git a/kaddressbook/editors/icons/cr16-app-groupwise_protocol.png b/kaddressbook/editors/icons/cr16-app-groupwise_protocol.png Binary files differnew file mode 100644 index 000000000..87dcf0dca --- /dev/null +++ b/kaddressbook/editors/icons/cr16-app-groupwise_protocol.png diff --git a/kaddressbook/editors/icons/cr16-app-icq_protocol.png b/kaddressbook/editors/icons/cr16-app-icq_protocol.png Binary files differnew file mode 100644 index 000000000..eda0f8c4d --- /dev/null +++ b/kaddressbook/editors/icons/cr16-app-icq_protocol.png diff --git a/kaddressbook/editors/icons/cr16-app-irc_protocol.png b/kaddressbook/editors/icons/cr16-app-irc_protocol.png Binary files differnew file mode 100644 index 000000000..c5678d1ef --- /dev/null +++ b/kaddressbook/editors/icons/cr16-app-irc_protocol.png diff --git a/kaddressbook/editors/icons/cr16-app-jabber_protocol.png b/kaddressbook/editors/icons/cr16-app-jabber_protocol.png Binary files differnew file mode 100644 index 000000000..48dd715eb --- /dev/null +++ b/kaddressbook/editors/icons/cr16-app-jabber_protocol.png diff --git a/kaddressbook/editors/icons/cr16-app-meanwhile_protocol.png b/kaddressbook/editors/icons/cr16-app-meanwhile_protocol.png Binary files differnew file mode 100644 index 000000000..69767ef3a --- /dev/null +++ b/kaddressbook/editors/icons/cr16-app-meanwhile_protocol.png diff --git a/kaddressbook/editors/icons/cr16-app-msn_protocol.png b/kaddressbook/editors/icons/cr16-app-msn_protocol.png Binary files differnew file mode 100644 index 000000000..a18ff5d4e --- /dev/null +++ b/kaddressbook/editors/icons/cr16-app-msn_protocol.png diff --git a/kaddressbook/editors/icons/cr16-app-skype_protocol.png b/kaddressbook/editors/icons/cr16-app-skype_protocol.png Binary files differnew file mode 100644 index 000000000..5649464ff --- /dev/null +++ b/kaddressbook/editors/icons/cr16-app-skype_protocol.png diff --git a/kaddressbook/editors/icons/cr16-app-sms_protocol.png b/kaddressbook/editors/icons/cr16-app-sms_protocol.png Binary files differnew file mode 100644 index 000000000..3bfa3627c --- /dev/null +++ b/kaddressbook/editors/icons/cr16-app-sms_protocol.png diff --git a/kaddressbook/editors/icons/cr16-app-yahoo_protocol.png b/kaddressbook/editors/icons/cr16-app-yahoo_protocol.png Binary files differnew file mode 100644 index 000000000..30569212b --- /dev/null +++ b/kaddressbook/editors/icons/cr16-app-yahoo_protocol.png diff --git a/kaddressbook/editors/imaddressbase.ui b/kaddressbook/editors/imaddressbase.ui new file mode 100644 index 000000000..f62ac00d7 --- /dev/null +++ b/kaddressbook/editors/imaddressbase.ui @@ -0,0 +1,89 @@ +<!DOCTYPE UI><UI version="3.3" stdsetdef="1"> +<class>IMAddressBase</class> +<widget class="QWidget"> + <property name="name"> + <cstring>IMAddressBase</cstring> + </property> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>208</width> + <height>121</height> + </rect> + </property> + <property name="sizePolicy"> + <sizepolicy> + <hsizetype>0</hsizetype> + <vsizetype>5</vsizetype> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="caption"> + <string>Edit Address</string> + </property> + <grid> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QComboBox" row="0" column="1"> + <property name="name"> + <cstring>cmbProtocol</cstring> + </property> + </widget> + <widget class="QLabel" row="0" column="0"> + <property name="name"> + <cstring>labelProtocol</cstring> + </property> + <property name="text"> + <string>&Protocol:</string> + </property> + <property name="buddy" stdset="0"> + <cstring>cmbProtocol</cstring> + </property> + </widget> + <widget class="QLineEdit" row="1" column="1"> + <property name="name"> + <cstring>edtAddress</cstring> + </property> + </widget> + <widget class="QLabel" row="1" column="0"> + <property name="name"> + <cstring>labelAddress</cstring> + </property> + <property name="text"> + <string>&Address:</string> + </property> + <property name="buddy" stdset="0"> + <cstring>edtAddress</cstring> + </property> + </widget> + <widget class="QLabel" row="2" column="0"> + <property name="name"> + <cstring>labelNetwork</cstring> + </property> + <property name="text"> + <string>&Network:</string> + </property> + <property name="buddy" stdset="0"> + <cstring>edtNetwork</cstring> + </property> + </widget> + <widget class="QLineEdit" row="2" column="1"> + <property name="name"> + <cstring>edtNetwork</cstring> + </property> + </widget> + </grid> +</widget> +<tabstops> + <tabstop>cmbProtocol</tabstop> + <tabstop>edtAddress</tabstop> +</tabstops> +<slots> + <slot>slotProtocolChanged( const QString & )</slot> + <slot>slotProtocolChanged()</slot> +</slots> +<layoutdefaults spacing="6" margin="11"/> +</UI> diff --git a/kaddressbook/editors/imaddresseditor.desktop b/kaddressbook/editors/imaddresseditor.desktop new file mode 100644 index 000000000..64dc74425 --- /dev/null +++ b/kaddressbook/editors/imaddresseditor.desktop @@ -0,0 +1,104 @@ +[Desktop Entry] +Type=Service +Name=Instant Messaging +Name[af]=Kits bootskap +Name[bg]=Мигновени съобщения +Name[br]=Postelerezh a-benn-kaer +Name[bs]=Instant poruke +Name[ca]=Missatgeria instantània +Name[cs]=Komunikátor +Name[el]=Στιγμιαίο μήνυμα +Name[eo]=Rapidmesaĝilo +Name[es]=Mensajería instantánea +Name[et]=Kiirsuhtlus +Name[eu]=Berehalako mezularitza +Name[fa]=پیامدهی فوری +Name[fi]=Pikaviestintä +Name[fr]=Messagerie instantanée +Name[gl]=Mensaxería Instantánea +Name[he]=מסרים מיידיים +Name[hu]=Azonnali üzenetküldés (IM) +Name[is]=Skilaboðaforrit +Name[it]=Messaggistica istantanea +Name[ja]=インスタントメッセージ +Name[ka]=მყისიერი შეტყობინებები +Name[kk]=Лезде хабарласу +Name[km]=ផ្ញើសារបន្ទាន់ +Name[ko]=인스턴트 페시징 +Name[lt]=Momentinės žinutės +Name[ms]=Penghantaran Mesej Segera +Name[nb]=Lynmelding +Name[nds]=Kortnarichten-Maker +Name[ne]=संदेशन दृश्टान्त +Name[nn]=Lynmelding +Name[pl]=Komunikacja internetowa +Name[pt]=Mensagens Instantâneas +Name[pt_BR]=Mensagem Instantâneo +Name[ru]=Службы обмена сообщениями +Name[se]=Šleađgadieđáhus +Name[sk]=Rozhovor +Name[sl]=Takojšno sporočanje +Name[sr]=Тренутне поруке +Name[sr@Latn]=Trenutne poruke +Name[sv]=Direktmeddelanden +Name[ta]=உடனடி செய்தி பரிமாற்றம் +Name[tg]=Хизматгоҳи мубодилаи иттилоот +Name[tr]=Hızlı Mesajlaşma +Name[uk]=Миттєвий зв'язок +Name[uz]=Xabar almashish +Name[uz@cyrillic]=Хабар алмашиш +Name[zh_CN]=即时通讯 +Name[zh_TW]=即時通訊 +Comment=Instant Messaging Address Editor +Comment[af]=Kits boodskap adres redigeerder +Comment[bg]=Редактор на адреси за мигновените съобщения +Comment[bs]=Editor adresa za instant poruke +Comment[ca]=Editor d'adreces de missatgeria instantània +Comment[cs]=Editor adres komunikátorů +Comment[da]=Instant Messaging adresseeditor +Comment[de]=Editor für Instant Messaging-Adressen +Comment[el]=Επεξεργαστής διευθύνσεων στιγμιαίων μηνυμάτων +Comment[eo]=Rapidmesaĝila Adres-Redaktilo +Comment[es]=Editor de direcciones de mensajería instantánea +Comment[et]=Kiirsuhtluse aadresside redaktor +Comment[eu]=Berehalako mezularitza helbide editorea +Comment[fa]=ویرایشگر نشانی پیامدهی فوری +Comment[fi]=Pikaviestinnän osoitteet +Comment[fr]=Éditeur d'adresses de messagerie instantanée +Comment[fy]=Instant Messaging Adresbewurker +Comment[gl]=Editor de Enderezos de Mensaxería Instantánea +Comment[he]=עורך כתובות מסרים מידיים +Comment[hu]=IM-címszerkesztő +Comment[is]=Vistfangaritill fyrir skilaboðaforrit +Comment[it]=Editor degli indirizzi per messaggi istantanei +Comment[ja]=インスタントメッセージのアドレスを編集 +Comment[ka]=მყისიერი შეტყობინებების წიგნაკის რედაქტორი +Comment[kk]=Лезде хабарласу адрестер өңдегіші +Comment[km]=កម្មវិធីនិពន្ធអាសយដ្ឋានដើម្បីផ្ញើសារបន្ទាន់ +Comment[ko]=인스턴트 메시징 주소 편집기 +Comment[lt]=Momentinių žinučių adresų redaktorius +Comment[ms]=Pengedit Alamat Penghantaran Mesej Segera +Comment[nb]=Adresse-redigerer for lynmelding +Comment[nds]=Editor för Kortnarichten-Adressen +Comment[ne]=दृष्टान्त संदेशन ठेगाना सम्पादक +Comment[nl]=Instant Messaging Adresbewerker +Comment[nn]=Adresseredigering for lynmelding +Comment[pl]=Edytor adresów komunikatorów internetowych +Comment[pt]=Editor de Endereços do Mensageiro Instantâneo +Comment[pt_BR]=Editor de Endereços do Mensageiro Instantâneo +Comment[ru]=Редактор контактов служб обмена сообщениями +Comment[se]=Šleađgadieđáhusaid čujuhusdoaimmaheaddji +Comment[sk]=Editor adries pre Instant Messaging +Comment[sl]=Urejevalnik naslovov takojšnega sporočanja +Comment[sr]=Едитор адреса тренутних порука +Comment[sr@Latn]=Editor adresa trenutnih poruka +Comment[sv]=Adresseditor för direktmeddelanden +Comment[ta]= உடனடி செய்தி பரிமாற்றத்தின் முகவரி தொகுப்பான் +Comment[tg]=Муҳаррири алоқоти хизматгоҳҳои мубодилаи иттилоот +Comment[tr]=Hızlı Mesajlaşma Adres Düzenleyicisi +Comment[uk]=Редактор адрес миттєвого зв'язку +Comment[zh_CN]=即时通讯地址编辑器 +Comment[zh_TW]=即時通訊位址編輯器 +ServiceTypes=KAddressBook/ContactEditorWidget +X-KDE-Library=libkaddrbk_instantmessaging +X-KDE-KAddressBook-CEWPluginVersion=1 diff --git a/kaddressbook/editors/imaddresswidget.cpp b/kaddressbook/editors/imaddresswidget.cpp new file mode 100644 index 000000000..3d2af677e --- /dev/null +++ b/kaddressbook/editors/imaddresswidget.cpp @@ -0,0 +1,137 @@ +/* + IM address editor widget for KAddressbook + + Copyright (c) 2004 Will Stephenson <lists@stevello.free-online.co.uk> + + 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 <qcombobox.h> +#include <qlineedit.h> +#include <qlabel.h> + +#include <kdebug.h> +#include <kiconloader.h> +#include <klocale.h> +#include <kplugininfo.h> + +#include "imaddresswidget.h" + +IMAddressWidget::IMAddressWidget( QWidget *parent, QValueList<KPluginInfo *> protocols ) + : IMAddressBase( parent ) +{ + mProtocols = protocols; + populateProtocols(); + init(); +} + +IMAddressWidget::IMAddressWidget( QWidget *parent, QValueList<KPluginInfo *> protocols, + KPluginInfo *protocol, const QString& address, + const IMContext& context ) + : IMAddressBase( parent ) +{ + Q_UNUSED( context ); + + mProtocols = protocols; + populateProtocols(); + cmbProtocol->setCurrentItem( mProtocols.findIndex( protocol ) ); + + edtAddress->setText( address.section( QChar( 0xE120 ), 0, 0 ) ); + edtNetwork->setText( address.section( QChar( 0xE120 ), 1 ) ); + + init(); +} + +void IMAddressWidget::init() +{ + connect( cmbProtocol, SIGNAL( activated( const QString& ) ), + this, SLOT( slotProtocolChanged() ) ); + connect( edtAddress, SIGNAL( textChanged( const QString& ) ), + this, SLOT( slotAddressChanged( const QString& ) ) ); + + slotProtocolChanged(); +} + +void IMAddressWidget::slotAddressChanged( const QString &text ) +{ + emit inValidState( !text.stripWhiteSpace().isEmpty() ); +} + +KPluginInfo * IMAddressWidget::protocol() const +{ + int protocolIndex = cmbProtocol->currentItem(); + + return mProtocols[ protocolIndex ]; +} + +IMContext IMAddressWidget::context() const +{ + IMContext context = Any; +/* if ( cmbContext->currentItem() ) + { + + int contextIndex = cmbContext->currentItem(); + switch ( contextIndex ) + { + case 0: + context = Any; + break; + case 1: + context = Home; + break; + case 2: + context = Work; + break; + } + } + */ + + return context; +} + +QString IMAddressWidget::address() const +{ + // The protocol irc is a special case and hard coded in. + // It's not nice, but the simplest way that I can see. + if ( protocol()->name() == "IRC" && !edtNetwork->text().stripWhiteSpace().isEmpty() ) + return edtAddress->text().stripWhiteSpace() + QChar( 0xE120 ) + edtNetwork->text().stripWhiteSpace(); + else + return edtAddress->text().stripWhiteSpace(); +} + +void IMAddressWidget::populateProtocols() +{ + // insert the protocols in order + QValueList<KPluginInfo *>::ConstIterator it; + for ( it = mProtocols.begin(); it != mProtocols.end(); ++it ) + cmbProtocol->insertItem( SmallIcon( (*it)->icon() ), (*it)->name() ); +} + +void IMAddressWidget::slotProtocolChanged() +{ + if ( protocol()->name() == "IRC" ) { + edtNetwork->show(); + labelNetwork->show(); + } else { + edtNetwork->hide(); + labelNetwork->hide(); + } +} + +#include "imaddresswidget.moc" diff --git a/kaddressbook/editors/imaddresswidget.h b/kaddressbook/editors/imaddresswidget.h new file mode 100644 index 000000000..29d93b13f --- /dev/null +++ b/kaddressbook/editors/imaddresswidget.h @@ -0,0 +1,74 @@ +/* + IM address editor widget for KAddressbook + + Copyright (c) 2004 Will Stephenson <lists@stevello.free-online.co.uk> + + 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 IMADDRESSWIDGET_H +#define IMADDRESSWIDGET_H + +#include <qvaluelist.h> + +#include "imaddressbase.h" +#include "imeditorwidget.h" + +class KPluginInfo; + +/* Note regarding Context: + * It wasn not possible to get an idea of Context into Kopete in time for KDE 3.3, + * so it has been removed from the UI and functionally disabled in the code. + */ + +/** + * A widget for editing an instant messaging address + */ +class IMAddressWidget : public IMAddressBase +{ + Q_OBJECT + + public: + IMAddressWidget( QWidget *parent, QValueList<KPluginInfo *> protocols); + IMAddressWidget( QWidget *parent, QValueList<KPluginInfo *> protocols, + KPluginInfo *protocol, const QString& address, + const IMContext& context = Any ); + + KPluginInfo * protocol() const; + IMContext context() const; + QString address() const ; + QValueList<KPluginInfo *> mProtocols; + + signals: + void inValidState( bool ); + + protected: + /** + * Populate combobox with protocols + */ + void populateProtocols(); + + protected slots: + void slotProtocolChanged(); + void slotAddressChanged( const QString &text ); + + private: + void init(); +}; + +#endif diff --git a/kaddressbook/editors/imeditorbase.ui b/kaddressbook/editors/imeditorbase.ui new file mode 100644 index 000000000..24a5696a9 --- /dev/null +++ b/kaddressbook/editors/imeditorbase.ui @@ -0,0 +1,164 @@ +<!DOCTYPE UI><UI version="3.3" stdsetdef="1"> +<class>IMEditorBase</class> +<widget class="QWidget"> + <property name="name"> + <cstring>IMEditorBase</cstring> + </property> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>442</width> + <height>247</height> + </rect> + </property> + <property name="sizePolicy"> + <sizepolicy> + <hsizetype>5</hsizetype> + <vsizetype>7</vsizetype> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="caption"> + <string>IM Addresses</string> + </property> + <grid> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <spacer row="4" column="1"> + <property name="name"> + <cstring>spacer1</cstring> + </property> + <property name="orientation"> + <enum>Vertical</enum> + </property> + <property name="sizeType"> + <enum>Expanding</enum> + </property> + <property name="sizeHint"> + <size> + <width>20</width> + <height>16</height> + </size> + </property> + </spacer> + <widget class="QPushButton" row="3" column="1"> + <property name="name"> + <cstring>btnSetStandard</cstring> + </property> + <property name="text"> + <string>&Set Standard</string> + </property> + <property name="toolTip" stdset="0"> + <string>The IM Address that is set as the standard is the address that is shown in main editor window.</string> + </property> + <property name="whatsThis" stdset="0"> + <string><qt>Only one IM Address can be set as the standard IM Address.<br>The standard IM Address is shown in the main editor window, and other programs may use this as hint for deciding which IM Address to show.</qt></string> + </property> + </widget> + <widget class="KPushButton" row="2" column="1"> + <property name="name"> + <cstring>btnDelete</cstring> + </property> + <property name="text"> + <string>&Remove</string> + </property> + </widget> + <widget class="KPushButton" row="1" column="1"> + <property name="name"> + <cstring>btnEdit</cstring> + </property> + <property name="text"> + <string>&Edit...</string> + </property> + </widget> + <widget class="KPushButton" row="0" column="1"> + <property name="name"> + <cstring>btnAdd</cstring> + </property> + <property name="text"> + <string>&Add...</string> + </property> + </widget> + <widget class="KListView" row="0" column="0" rowspan="5" colspan="1"> + <column> + <property name="text"> + <string>Protocol</string> + </property> + <property name="clickable"> + <bool>true</bool> + </property> + <property name="resizable"> + <bool>true</bool> + </property> + </column> + <column> + <property name="text"> + <string>Address</string> + </property> + <property name="clickable"> + <bool>true</bool> + </property> + <property name="resizable"> + <bool>true</bool> + </property> + </column> + <property name="name"> + <cstring>lvAddresses</cstring> + </property> + <property name="sizePolicy"> + <sizepolicy> + <hsizetype>7</hsizetype> + <vsizetype>3</vsizetype> + <horstretch>1</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="minimumSize"> + <size> + <width>200</width> + <height>28</height> + </size> + </property> + <property name="selectionMode" stdset="0"> + <enum>Extended</enum> + </property> + <property name="allColumnsShowFocus"> + <bool>true</bool> + </property> + <property name="fullWidth"> + <bool>true</bool> + </property> + </widget> + <widget class="KActiveLabel" row="5" column="0" rowspan="1" colspan="2"> + <property name="name"> + <cstring>lblWarning</cstring> + </property> + <property name="sizePolicy"> + <sizepolicy> + <hsizetype>5</hsizetype> + <vsizetype>5</vsizetype> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="text"> + <string><em>Note:</em> Please read the help page before adding or editing Instant Messenging Addresses here.</string> + </property> + </widget> + </grid> +</widget> +<customwidgets> +</customwidgets> +<layoutdefaults spacing="6" margin="0"/> +<layoutfunctions spacing="KDialog::spacingHint"/> +<includehints> + <includehint>kpushbutton.h</includehint> + <includehint>kpushbutton.h</includehint> + <includehint>kpushbutton.h</includehint> + <includehint>klistview.h</includehint> + <includehint>kactivelabel.h</includehint> +</includehints> +</UI> diff --git a/kaddressbook/editors/imeditorwidget.cpp b/kaddressbook/editors/imeditorwidget.cpp new file mode 100644 index 000000000..f61e06386 --- /dev/null +++ b/kaddressbook/editors/imeditorwidget.cpp @@ -0,0 +1,491 @@ +/* + IM address editor widget for KAddressBook + + Copyright (c) 2004 Will Stephenson <lists@stevello.free-online.co.uk> + + 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 <qlistview.h> +#include <qstringlist.h> +#include <qvbox.h> +#include <qlayout.h> +#include <qfont.h> +#include <qpainter.h> + +#include <kdialogbase.h> +#include <kdebug.h> +#include <kiconloader.h> +#include <klocale.h> +#include <kmessagebox.h> +#include <kplugininfo.h> +#include <kpushbutton.h> +#include <ktrader.h> + +#include "imaddresswidget.h" +#include "imeditorbase.h" +#include "imeditorwidget.h" + + +IMAddressLVI::IMAddressLVI( KListView *parent, KPluginInfo *protocol, + const QString &address, const IMContext &context ) + : KListViewItem( parent ) +{ + setProtocol( protocol ); + setAddress( address ); + setContext( context ); + mPreferred = false; +} + +void IMAddressLVI::setPreferred( bool preferred ) +{ + mPreferred = preferred; +} + +bool IMAddressLVI::preferred() const +{ + return mPreferred; +} + +void IMAddressLVI::paintCell( QPainter *p, const QColorGroup &cg, + int column, int width, int alignment ) +{ + if ( mPreferred ) { + QFont font = p->font(); + font.setBold( true ); + p->setFont( font ); + } + + KListViewItem::paintCell( p, cg, column, width, alignment ); +} + +void IMAddressLVI::setAddress( const QString &address ) +{ + // irc uses 0xE120 to seperate the nick and the server group. + QString serverOrGroup = address.section( QChar( 0xE120 ), 1 ); + + if ( serverOrGroup.isEmpty() ) + setText( 1, address ); + else { + QString nickname = address.section( QChar( 0xE120 ), 0, 0 ); + setText( 1, i18n( "<nickname> on <server>","%1 on %2" ) + .arg( nickname ).arg( serverOrGroup ) ); + } + + mAddress = address; +} + +void IMAddressLVI::setContext( const IMContext &context ) +{ + mContext = context; + // set context +/* switch ( context ) + { + case Home: + setText( 2, i18n( "Home" ) ); + break; + case Work: + setText( 2, i18n( "Work" ) ); + break; + case Any: + setText( 2, i18n( "Any" ) ); + break; + } +*/ +} + +void IMAddressLVI::setProtocol( KPluginInfo *protocol ) +{ + mProtocol = protocol; + + setPixmap( 0, SmallIcon( mProtocol->icon() ) ); + setText( 0, mProtocol->name() ); +} + +KPluginInfo * IMAddressLVI::protocol() const +{ + return mProtocol; +} + +IMContext IMAddressLVI::context() const +{ + return mContext; +} + +QString IMAddressLVI::address() const +{ + return mAddress; +} + +void IMAddressLVI::activate() +{ + // show editor +} + +/*===========================================================================*/ + +IMEditorWidget::IMEditorWidget( QWidget *parent, const QString &preferredIM, const char *name ) + : KDialogBase( parent, name, false, i18n( "Edit Instant Messenging Address" ), + Help | Ok | Cancel, Ok, false ), + mReadOnly( false ) +{ + mWidget = new IMEditorBase( this ); + setMainWidget( mWidget ); + + connect( mWidget->btnAdd, SIGNAL( clicked() ), SLOT( slotAdd() ) ); + connect( mWidget->btnEdit, SIGNAL( clicked() ), SLOT( slotEdit() ) ); + connect( mWidget->btnDelete, SIGNAL( clicked() ), SLOT( slotDelete() ) ); + connect( mWidget->btnSetStandard, SIGNAL( clicked()), SLOT( slotSetStandard() ) ); + connect( mWidget->lvAddresses, SIGNAL( selectionChanged() ), SLOT( slotUpdateButtons() ) ); + + connect( mWidget->lvAddresses, SIGNAL( doubleClicked( QListViewItem*, const QPoint&, int ) ), + SLOT( slotEdit() ) ); + + setHelp( "managing-contacts-im-addresses" ); + + mWidget->btnEdit->setEnabled( false ); + mWidget->btnDelete->setEnabled( false ); + mWidget->btnSetStandard->setEnabled( false ); + // Disabled pending implementation + //mWidget->btnUp->setEnabled( false ); + //mWidget->btnDown->setEnabled( false ); + mPreferred = preferredIM; + mPreferred = mPreferred.replace( " on ", QString( QChar( 0xE120 ) ), true ); + mProtocols = KPluginInfo::fromServices( KTrader::self()->query( QString::fromLatin1( "KABC/IMProtocol" ) ) ); + + // order the protocols by putting them in a qmap, then sorting the set of keys and recreating the list + QMap<QString, KPluginInfo *> protocolMap; + QValueList<KPluginInfo *>::ConstIterator it; + QValueList<KPluginInfo *> sorted; + for ( it = mProtocols.begin(); it != mProtocols.end(); ++it ) + protocolMap.insert( (*it)->name(), (*it) ); + + QStringList keys = protocolMap.keys(); + keys.sort(); + QStringList::ConstIterator keyIt = keys.begin(); + QStringList::ConstIterator end = keys.end(); + for ( ; keyIt != end; ++keyIt ) + sorted.append( protocolMap[*keyIt] ); + mProtocols = sorted; +} + +QValueList<KPluginInfo *> IMEditorWidget::availableProtocols() const +{ + return mProtocols; +} + +void IMEditorWidget::loadContact( KABC::Addressee *addr ) +{ + if ( mWidget->lvAddresses ) + mWidget->lvAddresses->clear(); + + // see README for details of how Evolution stores IM addresses (differently) + const QStringList customs = addr->customs(); + + QStringList::ConstIterator it; + bool isSet = false; + for ( it = customs.begin(); it != customs.end(); ++it ) { + QString app, name, value; + splitField( *it, app, name, value ); + + if ( app.startsWith( QString::fromLatin1( "messaging/" ) ) ) { + if ( name == QString::fromLatin1( "All" ) ) { + KPluginInfo *protocol = protocolFromString( app ); + if ( protocol ) { + QStringList addresses = QStringList::split( QChar( 0xE000 ), value ); + QStringList::iterator end = addresses.end(); + for ( QStringList::ConstIterator it = addresses.begin(); it != end; ++it ) { + IMAddressLVI *imaddresslvi = new IMAddressLVI( mWidget->lvAddresses, protocol, *it, Any/*, false*/ ); + if ( !isSet && (*it).stripWhiteSpace().lower() == mPreferred.stripWhiteSpace().lower() ) { + imaddresslvi->setPreferred( true ); + isSet = true; //Only set one item to be preferred + } + } + } else + kdDebug( 5720 ) << k_funcinfo << " no protocol found for: " << app << endl; + } + } + } + + if ( mWidget->lvAddresses->firstChild() ) + mWidget->lvAddresses->firstChild()->setSelected( true ); +} + +void IMEditorWidget::storeContact( KABC::Addressee *addr ) +{ + // for each changed protocol, write a new custom field containing the current set of + // addresses + QValueList<KPluginInfo *>::ConstIterator protocolIt; + for ( protocolIt = mChangedProtocols.begin(); protocolIt != mChangedProtocols.end(); ++protocolIt ) { + QStringList lst; + QListViewItemIterator addressIt( mWidget->lvAddresses ); + while ( addressIt.current() ) { + IMAddressLVI* currentAddress = static_cast<IMAddressLVI*>( *addressIt ); + if ( currentAddress->protocol() == *protocolIt ) + lst.append( currentAddress->address() ); + ++addressIt; + } + + QString addrBookField = (*protocolIt)->property( "X-KDE-InstantMessagingKABCField" ).toString(); + if ( !lst.isEmpty() ) + addr->insertCustom( addrBookField, QString::fromLatin1( "All" ), lst.join( QChar( 0xE000 ) ) ); + else + addr->removeCustom( addrBookField, QString::fromLatin1( "All" ) ); + } +} + +void IMEditorWidget::setReadOnly( bool readOnly ) +{ + mReadOnly = readOnly; + slotUpdateButtons(); +} + +void IMEditorWidget::slotSetStandard() +{ + QListViewItemIterator it( mWidget->lvAddresses, QListViewItemIterator::Selected ); + + // Just set the first one selected as standard + if ( IMAddressLVI *current = static_cast<IMAddressLVI*>( it.current() ) ) { + QListViewItemIterator it2( mWidget->lvAddresses ); + while ( it2.current() ) { + IMAddressLVI *item = static_cast<IMAddressLVI*>( it2.current() ); + + if ( item->preferred() ) { + if ( current == item ) + return; //Selected is already preferred + else { + item->setPreferred( false ); + mWidget->lvAddresses->repaintItem( item ); + break; + } + } + + ++it2; + } + + mPreferred = current->address(); + current->setPreferred( true ); + setModified( true ); + mWidget->lvAddresses->repaintItem( current ); + } +} + +void IMEditorWidget::slotUpdateButtons() +{ + int num_selected = 0; + QListViewItemIterator it( mWidget->lvAddresses, QListViewItemIterator::Selected ); + while ( it.current() ) { + ++num_selected; + if ( num_selected > 1 ) + break; //no need to count above 2. + + ++it; + } + + if ( !mReadOnly && num_selected == 1 ) { + mWidget->btnAdd->setEnabled( true ); + mWidget->btnEdit->setEnabled( true ); + mWidget->btnDelete->setEnabled( true ); + IMAddressLVI *current = static_cast<IMAddressLVI*>( it.current() ); + + // Disable "set standard" if already standard + mWidget->btnSetStandard->setEnabled( !current || !current->preferred() ); + } else if ( !mReadOnly && num_selected > 1 ) { + mWidget->btnAdd->setEnabled( true ); + mWidget->btnEdit->setEnabled( false ); + mWidget->btnDelete->setEnabled( true ); + mWidget->btnSetStandard->setEnabled( false ); + } else { + mWidget->btnAdd->setEnabled( !mReadOnly ); + mWidget->btnSetStandard->setEnabled( false ); + mWidget->btnEdit->setEnabled( false ); + mWidget->btnDelete->setEnabled( false ); + } +} + +void IMEditorWidget::setModified( bool modified ) +{ + mModified = modified; +} + +bool IMEditorWidget::isModified() const +{ + return mModified; +} + +void IMEditorWidget::slotAdd() +{ + KDialogBase addDialog( this, "addaddress", true, i18n( "Instant messaging", "Add Address" ), + KDialogBase::Ok | KDialogBase::Cancel ); + + IMAddressWidget *addressWid = new IMAddressWidget( &addDialog, mProtocols ); + addDialog.enableButtonOK( false ); + connect( addressWid, SIGNAL( inValidState( bool ) ), + &addDialog, SLOT( enableButtonOK( bool ) ) ); + addDialog.setMainWidget( addressWid ); + + if ( addDialog.exec() == QDialog::Accepted ) { + // add the new item + IMAddressLVI *imaddresslvi = new IMAddressLVI( mWidget->lvAddresses, addressWid->protocol(), + addressWid->address() /*, addressWid->context() */ ); + + // If it's a new address, set is as preferred. + if ( mPreferred.isEmpty() ) { + imaddresslvi->setPreferred( true ); + mPreferred = addressWid->address(); + } + + if ( mChangedProtocols.find( addressWid->protocol() ) == mChangedProtocols.end() ) + mChangedProtocols.append( addressWid->protocol() ); + + mWidget->lvAddresses->sort(); + + setModified( true ); + } +} + +void IMEditorWidget::slotEdit() +{ + QListViewItemIterator it( mWidget->lvAddresses, QListViewItemIterator::Selected ); + + // Just edit the first one selected. + if ( IMAddressLVI *current = static_cast<IMAddressLVI*>( it.current() ) ) { + KDialogBase editDialog( this, "editaddress", true, i18n( "Instant messaging", "Edit Address" ), + KDialogBase::Ok | KDialogBase::Cancel ); + IMAddressWidget *addressWid = new IMAddressWidget( &editDialog, mProtocols, current->protocol(), + current->address(), current->context() ) ; + connect( addressWid, SIGNAL( inValidState( bool ) ), + &editDialog, SLOT( enableButtonOK( bool ) ) ); + editDialog.setMainWidget( addressWid ); + + if ( editDialog.exec() == QDialog::Accepted ) { + bool modified = false; + if ( addressWid->address() != current->address() ) { + modified = true; + current->setAddress( addressWid->address() ); + } + if ( addressWid->context() != current->context() ) { + modified = true; + current->setContext( addressWid->context() ); + } + + // the entry for the protocol of the current address has changed + if ( mChangedProtocols.find( current->protocol() ) == mChangedProtocols.end() ) { + mChangedProtocols.append( current->protocol() ); + } + // update protocol - has another protocol gained an address? + if ( current->protocol() != addressWid->protocol() ) { + modified = true; + // this proto is losing an entry + current->setProtocol( addressWid->protocol() ); + if ( mChangedProtocols.find( current->protocol() ) == mChangedProtocols.end() ) + mChangedProtocols.append( current->protocol() ); + } + + if ( modified ) + setModified(true); + } + } +} + +void IMEditorWidget::slotDelete() +{ + int num_selected = 0; + + { + QListViewItemIterator it( mWidget->lvAddresses, QListViewItemIterator::Selected ); + while ( it.current() ) { + num_selected++; + ++it; + } + } + + if ( num_selected == 0 ) + return; + + if ( KMessageBox::warningContinueCancel( this, i18n( "Do you really want to delete the selected address?", + "Do you really want to delete the %n selected addresses?", num_selected ), + i18n( "Confirm Delete" ), KStdGuiItem::del() ) != KMessageBox::Continue ) + return; + + QListViewItemIterator it( mWidget->lvAddresses ); + bool deletedPreferred = false; + while( it.current() ) { + if ( it.current()->isSelected() ) { + IMAddressLVI * current = static_cast<IMAddressLVI*>( *it ); + if ( mChangedProtocols.find( current->protocol() ) == mChangedProtocols.end() ) + mChangedProtocols.append( current->protocol() ); + + if ( current->preferred() ) + deletedPreferred = true; + + delete current; + } else + ++it; + } + + if ( deletedPreferred ) { + IMAddressLVI *first = static_cast<IMAddressLVI*>( mWidget->lvAddresses->firstChild() ); + if ( first ) { + first->setPreferred( true ); + mPreferred = first->address(); + } else + mPreferred = ""; + } + + setModified( true ); +} + +QString IMEditorWidget::preferred() const +{ + QString retval( mPreferred ); + return retval.replace( QChar( 0xE120 ), " on " ); +} + + +KPluginInfo * IMEditorWidget::protocolFromString( const QString &fieldValue ) const +{ + QValueList<KPluginInfo *>::ConstIterator it; + KPluginInfo * protocol = 0; + for ( it = mProtocols.begin(); it != mProtocols.end(); ++it ) { + if ( (*it)->property( "X-KDE-InstantMessagingKABCField" ).toString() == fieldValue ) { + protocol = *it; + break; + } + } + + return protocol; +} + +void IMEditorWidget::splitField( const QString &str, QString &app, QString &name, QString &value ) +{ + int colon = str.find( ':' ); + if ( colon != -1 ) { + QString tmp = str.left( colon ); + value = str.mid( colon + 1 ); + + int dash = tmp.find( '-' ); + if ( dash != -1 ) { + app = tmp.left( dash ); + name = tmp.mid( dash + 1 ); + } + } +} + +#include "imeditorwidget.moc" diff --git a/kaddressbook/editors/imeditorwidget.h b/kaddressbook/editors/imeditorwidget.h new file mode 100644 index 000000000..441db257b --- /dev/null +++ b/kaddressbook/editors/imeditorwidget.h @@ -0,0 +1,128 @@ +/* + IM addresses editor widget for KAddressbook + + Copyright (c) 2004 Will Stephenson <lists@stevello.free-online.co.uk> + + 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 IMEDITORWIDGET_H +#define IMEDITORWIDGET_H + +#include <qvaluelist.h> +#include <klistview.h> +#include <kdialogbase.h> + +#include "contacteditorwidget.h" + + +class AddressWidget; +class KPluginInfo; +class IMEditorBase; + +enum IMContext { Any, Home, Work }; + +/* Note regarding Context: + * It wasn not possible to get an idea of Context into Kopete in time for KDE 3.3, + * so it has been removed from the UI and functionally disabled in the code. + */ + +/** + * The widget we add to KAddressbook's contact editor dialog + */ +class IMEditorWidget : public KDialogBase +{ + Q_OBJECT + + public: + IMEditorWidget( QWidget *parent, const QString &preferredIM, const char *name = 0 ); + ~IMEditorWidget() {}; + + void loadContact( KABC::Addressee *addr ); + void storeContact( KABC::Addressee *addr ); + void setReadOnly( bool readOnly ); + QValueList<KPluginInfo *> availableProtocols() const; + bool isModified() const; + QString preferred() const; + + protected slots: + void slotUpdateButtons(); + void slotAdd(); + void slotEdit(); + void slotDelete(); + void slotSetStandard(); + + protected: + /** + * Helper method to split the contents of an addressbook field up + */ + static void splitField( const QString &str, QString &app, QString &name, QString &value ); + + /** + * Find a protocol that matches the KABC key, or 0 if none found + */ + KPluginInfo * protocolFromString( const QString &fieldValue ) const; + + private: + bool mReadOnly; + bool mModified; + QString mPreferred; + IMEditorBase *mWidget; + void setModified( bool modified ); + + // Used to track changed protocols to reduce KABC writes + QValueList<KPluginInfo *> mChangedProtocols; + QValueList<KPluginInfo *> mProtocols; +}; + +/** + * List view item representing a single IM address. + */ + +// VCard has been disabled as there is no standard VCard location to store IM addresses yet. +class IMAddressLVI : public KListViewItem +{ + public: + IMAddressLVI( KListView *parent, KPluginInfo * protocol, + const QString &address, const IMContext &context = Any ); + + void setAddress( const QString &address ); + void setProtocol( KPluginInfo * protocol ); + void setContext( const IMContext &context ); + void activate(); + + KPluginInfo * protocol() const; + QString address() const; + IMContext context() const; + + void setPreferred( bool preferred ); + bool preferred() const; + + protected: + virtual void paintCell( QPainter *p, const QColorGroup &cg, int column, int width, int alignment ); + + private: + KPluginInfo * mProtocol; + bool mPreferred; + IMContext mContext; + QString mAddress; +}; + +#endif + diff --git a/kaddressbook/editors/kaddressbookimprotocol.desktop b/kaddressbook/editors/kaddressbookimprotocol.desktop new file mode 100644 index 000000000..80a6f89aa --- /dev/null +++ b/kaddressbook/editors/kaddressbookimprotocol.desktop @@ -0,0 +1,57 @@ +[Desktop Entry] +Type=ServiceType +X-KDE-ServiceType=KABC/IMProtocol +X-KDE-KAddressBook-CEWVersion=1 +Name=KAddressbook Instant Messaging Protocol +Name[af]=KAddressbook kits boodskap protokol +Name[bg]=Протокол за мигновени съобщения за адресника +Name[bs]=KAddressbook protokol za instant poruke +Name[ca]=Protocol de missatgeria instantània KAddressbook +Name[cs]=KAddressbook instant messaging protokol +Name[da]=KAddressbook kvikbesked-protokol +Name[de]=Adressbuch Instant Messaging Protokoll +Name[el]=Πρωτόκολλο στιγμιαίου μηνύματος του KAddressbook +Name[eo]=KAddressbook Rapidmesaĝila Protokolo +Name[es]=Protocolo de mensajería instantánea de KAddressbook +Name[et]=KDE aadressiraamatu kiirsuhtlusprotokoll +Name[eu]=KAddressbook berehalako mezularitza protokoloa +Name[fa]=قرارداد پیامدهی فوری KAddressbook +Name[fi]=KAddresbookin pikaviestintäprotokolla +Name[fr]=Protocole de messagerie instantanée pour KAddressbook +Name[fy]=KAddressbook Instant Messaging-protokol +Name[gl]=Protocolo de Mensaxería Instantánea de KAddressbook +Name[he]=פרוטוקול מסרים מידיים של KAddressbook +Name[hu]=KAddressbook azonnali üzenetküldési protokoll +Name[is]=KAddressbook skilaboðaforritið +Name[it]=KAddressbook protocollo messaggistica istantanea +Name[ja]=KAddressbook インスタントメッセージプロトコル +Name[ka]=KDE ოქმი მყისიერი შეტყობინებებისათვისწიგნაკითვის +Name[kk]=KAddressbook лезде хабарласу протоколы +Name[km]=ពិធីការផ្ញើសារបន្ទាន់របស់ KAddressbook +Name[ko]=KAddressbook 인스턴트 메시징 프로토콜 +Name[lt]=KAddressbook momentinių žinučių protokolas +Name[ms]=Protokol Penghantaran Mesej Segera KAddressbook +Name[nb]=KAdressbook lynmeldingsprotokoll +Name[nds]=KAddressbook-Kortnarichten-Protokoll +Name[ne]=केडीई ठेगानापुस्तिका दृष्टान्त संदेशन प्रोटोकल +Name[nl]=KAddressbook Instant Messaging-protocol +Name[nn]=Lynmeldingsprotokoll for KDE-adresseboka +Name[pl]=Protokół komunikacji internetowej KAddressbook +Name[pt]=Protocolo de Mensagens Instantâneas do KAdressbook +Name[pt_BR]=Protocolo de Mensagens Instantâneas do KAddressbook +Name[ru]=Протокол обмена сообщениями адресной книги KDE +Name[se]=Šleađgadieđáhusprotokolla KDE-čujuhusgirjji várás +Name[sk]=Protokol pre KDE Adresár Instant Messaging +Name[sl]=Protokol takojšnega sporočanja za Adresar +Name[sr]=KAddressbook протокол тренутних адреса +Name[sr@Latn]=KAddressbook protokol trenutnih adresa +Name[sv]=Direktmeddelandeprotokoll för adressboken +Name[ta]=கேஅட்ரஸ்புக் உடனடி செய்தி பரிமாற்றம் +Name[tg]=Протоколи мубодилаи иттилооти китоби адресии KDE +Name[tr]=KAddressbook Hızlı Mesajlaşma Protokolü +Name[uk]=Протокол миттєвого зв'язку KAddressbook +Name[zh_CN]=KAddressbook 即时通讯协议 +Name[zh_TW]=KAddressbook 即時通訊協定 +[PropertyDef::X-KDE-InstantMessagingKABCField] +Type=QString + diff --git a/kaddressbook/editors/protocols/Makefile.am b/kaddressbook/editors/protocols/Makefile.am new file mode 100644 index 000000000..4ec5576b9 --- /dev/null +++ b/kaddressbook/editors/protocols/Makefile.am @@ -0,0 +1,6 @@ +servicedir = $(kde_servicesdir)/kaddressbook +service_DATA = icqprotocol.desktop aimprotocol.desktop ircprotocol.desktop \ + smsprotocol.desktop gaduprotocol.desktop \ + jabberprotocol.desktop yahooprotocol.desktop \ + msnprotocol.desktop groupwiseprotocol.desktop \ + meanwhileprotocol.desktop skypeprotocol.desktop diff --git a/kaddressbook/editors/protocols/aimprotocol.desktop b/kaddressbook/editors/protocols/aimprotocol.desktop new file mode 100644 index 000000000..e17be1f67 --- /dev/null +++ b/kaddressbook/editors/protocols/aimprotocol.desktop @@ -0,0 +1,63 @@ +[Desktop Entry] +Type=Service +Icon=aim_protocol +ServiceTypes=KABC/IMProtocol,KPluginInfo +X-KDE-InstantMessagingKABCField=messaging/aim +Comment=AIM Protocol +Comment[ar]=ميفاق AIM +Comment[be]=Пратакол AIM +Comment[bg]=Протокол AIM +Comment[br]=Komenad AIM +Comment[bs]=AIM protokol +Comment[ca]=Protocol AIM +Comment[cs]=AIM protokol +Comment[da]=AIM Protokol +Comment[de]=AIM-Protokoll +Comment[el]=Πρωτόκολλο AIM +Comment[eo]=AIM-Protokolo +Comment[es]=Protocolo AIM +Comment[et]=AIM protokoll +Comment[eu]=AIM protokoloa +Comment[fa]=قرارداد AIM +Comment[fi]=AIM-protokolla +Comment[fr]=Protocole AIM +Comment[fy]=AIM-protokol +Comment[ga]=Prótacal AIM +Comment[gl]=Protocolo AIM +Comment[he]=פרוטוקול AIM +Comment[hu]=AIM protokoll +Comment[is]=AIM samskiptamátinn +Comment[it]=Protocollo AIM +Comment[ja]=AIM プロトコル +Comment[ka]=AIM ოქმი +Comment[kk]=AIM протоколы +Comment[km]=ពិធីការ AIM +Comment[ko]=AIM 프로토콜 +Comment[lt]=AIM protokolas +Comment[mk]=AIM-протокол +Comment[ms]=Protokol AIM +Comment[nb]=AIM-protokoll +Comment[nds]=AIM-Protokoll +Comment[ne]=एआईएम प्रोटोकल +Comment[nl]=AIM-protocol +Comment[nn]=AIM-protokoll +Comment[pa]=AIM ਪ੍ਰੋਟੋਕਾਲ +Comment[pl]=Protokół AIM +Comment[pt]=Protocolo AIM +Comment[pt_BR]=Protocolo AIM +Comment[ru]=Протокол AIM +Comment[se]=AIM-protokolla +Comment[sk]=Protokol AIM +Comment[sl]=Protokol AIM +Comment[sr]=AIM протокол +Comment[sr@Latn]=AIM protokol +Comment[sv]=AIM-protokoll +Comment[ta]=AIM நெறிமுறை +Comment[tg]=Протоколи AIM +Comment[tr]=AIM Protokolü +Comment[uk]=Протокол AIM +Comment[zh_CN]=AIM 协议 +Comment[zh_TW]=AIM 協定 +Name=AIM +Name[ne]=एआईएम + diff --git a/kaddressbook/editors/protocols/gaduprotocol.desktop b/kaddressbook/editors/protocols/gaduprotocol.desktop new file mode 100644 index 000000000..96ee6e9ee --- /dev/null +++ b/kaddressbook/editors/protocols/gaduprotocol.desktop @@ -0,0 +1,63 @@ +[Desktop Entry] +Type=Service +Icon=gadu_protocol +ServiceTypes=KABC/IMProtocol,KPluginInfo +X-KDE-InstantMessagingKABCField=messaging/gadu +Comment=Gadu-Gadu Protocol +Comment[af]=Gadu-Gadu protokol +Comment[ar]=ميفاق Gadu-Gadu +Comment[be]=Пратакол Gadu-Gadu +Comment[bg]=Протокол Gadu-Gadu +Comment[br]=Komenad Gadu-Gadu +Comment[bs]=Gadu-Gadu protokol +Comment[ca]=Protocol Gadu-Gadu +Comment[cs]=Gadu-Gadu protokol +Comment[da]=Gadu-Gadu Protokol +Comment[de]=Gadu-Gadu-Protokoll +Comment[el]=Πρωτόκολλο Gadu-Gadu +Comment[eo]=Gadu-Gadu Protokolo +Comment[es]=Protocolo Gadu-Gadu +Comment[et]=Gadu-Gadu protokoll +Comment[eu]=Gadu-Gadu protokoloa +Comment[fa]=قرارداد Gadu-Gadu +Comment[fi]=Gadu-Gadu -protokolla +Comment[fr]=Protocole Gadu-Gadu +Comment[fy]=Gadu-Gadu-protokol +Comment[ga]=Prótacal Gadu-Gadu +Comment[gl]=Protocolo Gadu-Gadu +Comment[he]=פרוטוקול Gadu-Gadu +Comment[hu]=Gadu-Gadu protokoll +Comment[is]=Gadu-Gadu samskiptamátinn +Comment[it]=Protocollo Gadu-Gadu +Comment[ja]=Gadu-Gadu プロトコル +Comment[ka]=Gadu-Gadu ოქმი +Comment[kk]=Gadu-Gadu протоколы +Comment[km]=ពិធីការ Gadu-Gadu +Comment[lt]=Gadu-Gadu protokolas +Comment[mk]=Gadu-Gadu-протокол +Comment[ms]=Protokol Gadu-Gadu +Comment[nb]=Gadu-Gadu-protokoll +Comment[nds]=Gadu-Gadu-Protokoll +Comment[ne]=गाडु-गाडु प्रोटोकल +Comment[nl]=Gadu-Gadu-protocol +Comment[nn]=Gadu-Gadu-protokoll +Comment[pl]=Protokół Gadu-Gadu +Comment[pt]=Protocolo Gadu-Gadu +Comment[pt_BR]=Protocolo Gadu-Gadu +Comment[ru]=протокол Gadu-Gadu +Comment[se]=Gadu-Gadu-protokolla +Comment[sk]=Protokol Gadu-Gadu +Comment[sl]=Protokol Gadu-Gadu +Comment[sr]=Gadu-Gadu протокол +Comment[sr@Latn]=Gadu-Gadu protokol +Comment[sv]=Gadu-Gadu-protokoll +Comment[ta]=கடு-கடு நெறிமுறை +Comment[tg]=протоколи Gadu-Gadu +Comment[tr]=Gadu-Gadu Protokolü +Comment[uk]=Протокол Gadu-Gadu +Comment[zh_CN]=Gadu-Gadu 协议 +Comment[zh_TW]=Gadu-Gadu 協定 +Name=Gadu-Gadu +Name[ne]=गाडु-गाडु +Name[ta]=கடு-கடு + diff --git a/kaddressbook/editors/protocols/groupwiseprotocol.desktop b/kaddressbook/editors/protocols/groupwiseprotocol.desktop new file mode 100644 index 000000000..0ee40fd2e --- /dev/null +++ b/kaddressbook/editors/protocols/groupwiseprotocol.desktop @@ -0,0 +1,44 @@ +[Desktop Entry] +Type=Service +Icon=groupwise_protocol +ServiceTypes=KABC/IMProtocol,KPluginInfo +X-KDE-InstantMessagingKABCField=messaging/groupwise +Comment=Novell GroupWise Messenger +Comment[af]=Novell GroupWise boodskappe +Comment[bg]=Месинджър Novell GroupWise +Comment[cs]=Novell GroupWise komunikátor +Comment[el]=GroupWise Messenger της Novell +Comment[eo]=Novell GroupWise Mesaĝilo +Comment[es]=Servidor de mensajería de Novell GroupWise +Comment[et]=Novelli GroupWise Messenger +Comment[eu]=Novell GroupWise mezularia +Comment[fa]=مدیر Novell GroupWise +Comment[fr]=Messagerie GroupWise de Novell +Comment[fy]=Novell GroupWise-messenger +Comment[he]=מסנג'ר של Novell GroupWise +Comment[is]=Novell GroupWise Samskiptatólið +Comment[ja]=Novell GroupWise メッセンジャー +Comment[ka]= Novell GroupWise მყისიერი შეტყობინებების მაცნე +Comment[kk]=Novell GroupWise хабарласу +Comment[km]=កម្មវិធីផ្ញើសាររបស់ណូវែល - GroupWise +Comment[lt]=Novell GroupWise momentinių žinučių klientas +Comment[ms]=Pembawa mesej Novell GroupWise +Comment[nds]=Novell-GroupWise-Kortnarichtenmaker +Comment[ne]=नोभेल समूहगत म्यासेन्जर +Comment[nl]=Novell GroupWise-messenger +Comment[pl]=Komunikator Novell GroupWise +Comment[pt_BR]=Mensageiro GroupWise da Novell +Comment[ru]=Обмен сообщениями Novell GroupWise +Comment[sr]=Novell-ов GroupWise Messenger +Comment[sr@Latn]=Novell-ov GroupWise Messenger +Comment[sv]=Novell Groupwise Messenger +Comment[ta]=நோவல் குழுவாரியான செய்தியாளன் +Comment[tr]=Novell GroupWise Mesajlaşma Uygulaması +Comment[zh_CN]=Novell GroupWise 信使 +Name=GroupWise +Name[ne]=समूहगत +Name[sr]=Groupware +Name[sr@Latn]=Groupware +Name[sv]=Groupwise +Name[ta]=குழுவாரியாக + diff --git a/kaddressbook/editors/protocols/icqprotocol.desktop b/kaddressbook/editors/protocols/icqprotocol.desktop new file mode 100644 index 000000000..e071238ed --- /dev/null +++ b/kaddressbook/editors/protocols/icqprotocol.desktop @@ -0,0 +1,61 @@ +[Desktop Entry] +Type=Service +Icon=icq_protocol +ServiceTypes=KABC/IMProtocol,KPluginInfo +X-KDE-InstantMessagingKABCField=messaging/icq +Comment=ICQ Protocol +Comment[af]=ICQ protokol +Comment[be]=Пратакол ICQ +Comment[bg]=Протокол ICQ +Comment[br]=Komenad ICQ +Comment[bs]=ICQ protokol +Comment[ca]=Protocol ICQ +Comment[cs]=ICQ protokol +Comment[da]=ICQ Protokol +Comment[de]=ICQ-Protokoll +Comment[el]=Πρωτόκολλο ICQ +Comment[eo]=ICQ Protokolo +Comment[es]=Protocolo ICQ +Comment[et]=ICQ protokoll +Comment[eu]=ICQ protokoloa +Comment[fa]=قرارداد ICQ +Comment[fi]=ICQ-protokolla +Comment[fr]=Protocole ICQ +Comment[fy]=ICQ-protokol +Comment[ga]=Prótacal ICQ +Comment[gl]=Protocolo ICQ +Comment[he]=פרוטוקול ICQ +Comment[hu]=ICQ protokoll +Comment[is]=ICQ samskiptamátinn +Comment[it]=Protocollo ICQ +Comment[ja]=ICQ プロトコル +Comment[ka]=ICQ ოქმი +Comment[kk]=ICQ протоколы +Comment[km]=ពិធីការ ICQ +Comment[lt]=ICQ protokolas +Comment[mk]=ICQ-протокол +Comment[ms]=Protokol ICQ +Comment[nb]=ICQ-protokoll +Comment[nds]=ICQ-Protokoll +Comment[ne]=आईसीक्यू प्रोटोकल +Comment[nl]=ICQ-protocol +Comment[nn]=ICQ-protokoll +Comment[pl]=Protokół ICQ +Comment[pt]=Protocolo ICQ +Comment[pt_BR]=Protocolo ICQ +Comment[ru]=Протокол ICQ +Comment[se]=ICQ-protokolla +Comment[sk]=Protokol ICQ +Comment[sl]=Protokol ICQ +Comment[sr]=ICQ протокол +Comment[sr@Latn]=ICQ protokol +Comment[sv]=ICQ-protokoll +Comment[ta]=ICQ நெறிமுறை +Comment[tg]=Протоколи ICQ +Comment[tr]=ICQ Protokolü +Comment[uk]=Протокол ICQ +Comment[zh_CN]=ICQ 协议 +Comment[zh_TW]=ICQ 協定 +Name=ICQ +Name[ne]=आईसीक्यू + diff --git a/kaddressbook/editors/protocols/ircprotocol.desktop b/kaddressbook/editors/protocols/ircprotocol.desktop new file mode 100644 index 000000000..78f19447b --- /dev/null +++ b/kaddressbook/editors/protocols/ircprotocol.desktop @@ -0,0 +1,31 @@ +[Desktop Entry] +Type=Service +Icon=irc_protocol +ServiceTypes=KABC/IMProtocol,KPluginInfo +X-KDE-InstantMessagingKABCField=messaging/irc +Comment=Internet Relay Chat +Comment[bg]=Протокол IRC +Comment[fa]=گپ بازپخش اینترنت +Comment[hu]=IRC (Internet Relay Chat) +Comment[is]=Internet spjall +Comment[ja]=インターネットリレーチャット +Comment[ka]=IRC +Comment[kk]=Internet Relay Chat хабарласу +Comment[km]=ជជែកកំសាន្តតាមអ៊ីនធឺណិត +Comment[lt]=Estafetinis Interneto pokalbis +Comment[ne]=इन्टरनेटबाट प्रसारण कुराकानी +Comment[pl]=IRC (Internet Relay Chat) +Comment[pt_BR]=Protocolo de Bate-papo na Internet - IRC +Comment[ru]=IRC +Comment[sl]=Internet Relay Chat (»internetno prenešen klepet«) +Comment[sr]=Ћаскање преко интернета +Comment[sr@Latn]=Ćaskanje preko interneta +Comment[ta]=இணைய வழங்கும் அறட்டை +Comment[tg]=IRC (Internet Relay Chat) +Comment[tr]=İnternet Genel Sohbeti +Comment[uk]=IRChat +Comment[zh_CN]=Internet 聊天 +Comment[zh_TW]=IRC +Name=IRC +Name[ne]=आईआरसी + diff --git a/kaddressbook/editors/protocols/jabberprotocol.desktop b/kaddressbook/editors/protocols/jabberprotocol.desktop new file mode 100644 index 000000000..94b7271b7 --- /dev/null +++ b/kaddressbook/editors/protocols/jabberprotocol.desktop @@ -0,0 +1,63 @@ +[Desktop Entry] +Type=Service +Icon=jabber_protocol +ServiceTypes=KABC/IMProtocol,KPluginInfo +X-KDE-InstantMessagingKABCField=messaging/xmpp +Comment=Jabber Protocol +Comment[af]=Jabber protokol +Comment[ar]=ميفاق Jabber +Comment[be]=Пратакол Jabber +Comment[bg]=Протокол Jabber +Comment[br]=Komenad Jabber +Comment[bs]=Jabber protokol +Comment[ca]=Protocol Jabber +Comment[cs]=Jabber protokol +Comment[da]=Jabber Protokol +Comment[de]=Jabber-Protokoll +Comment[el]=Πρωτόκολλο Jabber +Comment[eo]=Jabber Protokolo +Comment[es]=Protocolo Jabber +Comment[et]=Jabberi protokoll +Comment[eu]=Jabber protokoloa +Comment[fa]=قرارداد Jabber +Comment[fi]=Jabber-protokolla +Comment[fr]=Protocole Jabber +Comment[fy]=Jabber-protokol +Comment[ga]=Prótacal Jabber +Comment[gl]=Protocolo Jabber +Comment[he]=פרוטוקול Jabber +Comment[hu]=Jabber protokoll +Comment[is]=Jabber samskiptamátinn +Comment[it]=Protocollo Jabber +Comment[ja]=Jabber プロトコル +Comment[ka]=Jabber ოქმი +Comment[kk]=Jabber протоколы +Comment[km]=ពិធីការ Jabber +Comment[lt]=Jabber protokolas +Comment[mk]=Jabber-протокол +Comment[ms]=Protokol Jabber +Comment[nb]=Jabber-protokoll +Comment[nds]=Jabber-Protokoll +Comment[ne]=ज्याबर प्रोटोकल +Comment[nl]=Jabber-protocol +Comment[nn]=Jabber-protokoll +Comment[pl]=Protokół Jabber +Comment[pt]=Protocolo Jabber +Comment[pt_BR]=Protocolo Jabber +Comment[ru]=протокол Jabber +Comment[se]=Jabber-protokolla +Comment[sk]=Protokol Jabber +Comment[sl]=Protokol Jabber +Comment[sr]=Jabber протокол +Comment[sr@Latn]=Jabber protokol +Comment[sv]=Jabber-protokoll +Comment[ta]=ஜாபர் நெறிமுறை +Comment[tg]=протоколи Jabber +Comment[tr]=Jabber Protokolü +Comment[uk]=Протокол Jabber +Comment[zh_CN]=Jabber 协议 +Comment[zh_TW]=Jabber 協定 +Name=Jabber +Name[ne]=ज्याबर +Name[ta]=ஜாபர் + diff --git a/kaddressbook/editors/protocols/meanwhileprotocol.desktop b/kaddressbook/editors/protocols/meanwhileprotocol.desktop new file mode 100644 index 000000000..7442cd04d --- /dev/null +++ b/kaddressbook/editors/protocols/meanwhileprotocol.desktop @@ -0,0 +1,61 @@ +[Desktop Entry] +Type=Service +Icon=meanwhile_protocol +ServiceTypes=KABC/IMProtocol,KPluginInfo +X-KDE-InstantMessagingKABCField=messaging/meanwhile +Comment=Meanwhile Protocol +Comment[af]=Meanwhile protokol +Comment[ar]=ميفاق Meanwhile +Comment[be]=Пратакол Meanwhile +Comment[bg]=Протокол Meanwhile +Comment[br]=Komenad Meanwhile +Comment[ca]=Protocol Meanwhile +Comment[cs]=Meanwhile protokol +Comment[da]=Meanwhile Protokol +Comment[de]=Meanwhile-Protokoll +Comment[el]=Πρωτόκολλο Meanwhile +Comment[eo]=Meanwhile Protokolo +Comment[es]=Protocolo Meanwhile +Comment[et]=Meanwhile'i protokoll +Comment[eu]=Meanwhile protokoloa +Comment[fa]=قرارداد در ضمن +Comment[fi]=Meanwhile-protokolla +Comment[fr]=Protocole Meanwhile +Comment[fy]=Meanwhile-protokol +Comment[ga]=Prótacal Meanwhile +Comment[gl]=Protocolo Meanwhile +Comment[he]=פרוטוקול Meanhwile +Comment[hu]=Meanwhile protokoll +Comment[is]=Meanwhile samskiptamátinn +Comment[it]=Protocollo Meanwhile +Comment[ja]=Meanwhile プロトコル +Comment[ka]=Meanwhile ოქმი +Comment[kk]=Meanwhile протоколы +Comment[km]=ពិធីការ Meanwhile +Comment[lt]=Meanwhile protokolas +Comment[mk]=Meanwhile-протокол +Comment[ms]=Protokol Meanwhile +Comment[nb]=Meanwhile-protokoll +Comment[nds]=Meanwhile-Protokoll +Comment[ne]=त्यसै समयको प्रोटोकल +Comment[nl]=Meanwhile-protocol +Comment[nn]=Meanwhile-protokollen +Comment[pl]=Protokół Meanwhile +Comment[pt]=Protocolo Meanwhile +Comment[pt_BR]=Protocolo Meanwhile +Comment[ru]=Протокол Meanwhile +Comment[se]=Meanwhile-protokolla +Comment[sk]=Meanwhile protokol +Comment[sl]=Protokol Meanwhile +Comment[sr]=Meanwhile протокол +Comment[sr@Latn]=Meanwhile protokol +Comment[sv]=Meanwhile-protokoll +Comment[ta]=நெறிமுறை +Comment[tr]=Meanwhile Protokolü +Comment[uk]=Протокол Meanwhile +Comment[zh_CN]=Meanwhile 协议 +Comment[zh_TW]=Meanwhile 協定 +Name=Meanwhile +Name[fa]=در ضمن +Name[ne]=त्यस समयको + diff --git a/kaddressbook/editors/protocols/msnprotocol.desktop b/kaddressbook/editors/protocols/msnprotocol.desktop new file mode 100644 index 000000000..58504fd71 --- /dev/null +++ b/kaddressbook/editors/protocols/msnprotocol.desktop @@ -0,0 +1,34 @@ +[Desktop Entry] +Type=Service +Icon=msn_protocol +ServiceTypes=KABC/IMProtocol,KPluginInfo +X-KDE-InstantMessagingKABCField=messaging/msn +Comment=MSN Messenger +Comment[af]=MSN boodskapper +Comment[bg]=Протокол MSN +Comment[cy]=Negesydd MSN +Comment[eo]=MSN Mesaĝilo +Comment[fa]=پیامرسان MSN +Comment[fr]=Messagerie MSN +Comment[is]=MSN spjallforritið +Comment[ja]=MSN メッセンジャー +Comment[ka]=MSN შიკრიკი +Comment[km]=កម្មវិធីផ្ញើសារ MSN +Comment[nds]=MSN-Kortnarichtenmaker +Comment[ne]=एमएसएन म्यासेन्जर +Comment[pa]=MSN ਸੁਨੇਹਾਦਾਰ +Comment[ta]=MSN மெசஞ்சர் +Comment[tr]=MSN Mesajcısı +Name=MSN Messenger +Name[bg]=MSN +Name[cy]=Negesydd MSN +Name[eo]=MSN Mesaĝilo +Name[fa]=پیامرسان MSN +Name[ja]=MSN メッセンジャー +Name[ka]=MSN შიკრიკი +Name[km]=កម្មវិធីផ្ញើសារ MSN +Name[nds]=MSN-Kortnarichtenmaker +Name[ne]=एमएसएन म्यासेन्जर +Name[ta]=MSN மெசஞ்சர் +Name[tr]=MSN Mesajcısı + diff --git a/kaddressbook/editors/protocols/skypeprotocol.desktop b/kaddressbook/editors/protocols/skypeprotocol.desktop new file mode 100644 index 000000000..60ac34060 --- /dev/null +++ b/kaddressbook/editors/protocols/skypeprotocol.desktop @@ -0,0 +1,53 @@ +[Desktop Entry] +Type=Service +Icon=skype_protocol +ServiceTypes=KABC/IMProtocol,KPluginInfo +X-KDE-InstantMessagingKABCField=messaging/skype +Comment=Skype Internet Telephony +Comment[af]=Skype Internet Telefoon +Comment[bg]=Интернет телефония чрез Skype +Comment[ca]=Telefonia per Internet Skype +Comment[cs]=Internetová telefonie Skype +Comment[da]=Skype internettelefoni +Comment[de]=Internet-Telefonie mit Skype +Comment[eo]=Skype Interreta Telefonado +Comment[es]=Telefonía por internet con Skype +Comment[et]=Internetitelefon Skype +Comment[eu]=Skype-en internet telefonia +Comment[fa]=ارتباط تلفنی اینترنت Skype +Comment[fi]=Skype Internet-puhelin +Comment[fr]=Téléphonie Internet Skype +Comment[fy]=Skype ynternettelefony +Comment[gl]=Telefonía por Internet con Skype +Comment[he]=טלפוניית רשת של Skype +Comment[hu]=Skype internetes telefon +Comment[is]=Skype Internet sími +Comment[it]=Telefonia internet Skype +Comment[ja]=Skype インターネット電話 +Comment[ka]=Skype ინტერნეტ ტელეფონი +Comment[kk]=Skype Интернет телефониясы +Comment[km]=ទូរស័ព្ទតាមអ៊ីនធឺណិតដោយប្រើ Skype +Comment[lt]=Skype Interneto telefonija +Comment[mk]=Интернет-телефонија со Skype +Comment[nb]=Skype IP-telefoni +Comment[nds]=Internet-Telefoneren mit Skype +Comment[ne]=स्काइप इन्टरनेट दूरभाषी +Comment[nl]=Skype internettelefonie +Comment[nn]=Skype Internett-telefoni +Comment[pl]=Skype - telefonia internetowa +Comment[pt]=Telefonia Internet Skype +Comment[pt_BR]=Telefonia via Internet Skype +Comment[ru]=Интернет-телефон Skype +Comment[se]=Skype Interneahtta-telefoniija +Comment[sk]=Skype Internet telefonovanie +Comment[sl]=Internetno telefoniranje Skype +Comment[sr]=Skype интернет телефонија +Comment[sr@Latn]=Skype internet telefonija +Comment[sv]=Skype Internettelefoni +Comment[tr]=Skype İnternet Telefonu +Comment[uk]=Інтернет-телефон Skype +Comment[zh_CN]=Skype Internet 电话 +Comment[zh_TW]=Skype 網路電話 +Name=Skype +Name[eo]=kype +Name[ne]=स्काइप diff --git a/kaddressbook/editors/protocols/smsprotocol.desktop b/kaddressbook/editors/protocols/smsprotocol.desktop new file mode 100644 index 000000000..30b50a1ea --- /dev/null +++ b/kaddressbook/editors/protocols/smsprotocol.desktop @@ -0,0 +1,64 @@ +[Desktop Entry] +Type=Service +Icon=sms_protocol +ServiceTypes=KABC/IMProtocol,KPluginInfo +X-KDE-InstantMessagingKABCField=messaging/sms +Comment=SMS Protocol +Comment[af]=SMS protokol +Comment[be]=Пратакол SMS +Comment[bg]=Протокол SMS +Comment[br]=Komenad SMS +Comment[bs]=SMS poruke +Comment[ca]=Protocol SMS +Comment[cs]=SMS protokol +Comment[da]=SMS Protokol +Comment[de]=SMS-Protokoll +Comment[el]=Πρωτόκολλο SMS +Comment[eo]=SMS Protokolo +Comment[es]=Protocolo SMS +Comment[et]=SMS protokoll +Comment[eu]=SMS protokoloa +Comment[fa]=قرارداد پیام کوتاه +Comment[fi]=SMS-protokolla +Comment[fr]=Protocole SMS +Comment[fy]=SMS-protokol +Comment[ga]=Prótacal SMS +Comment[gl]=Protocolo SMS +Comment[he]=פרוטוקול SMS +Comment[hu]=SMS protokoll +Comment[is]=SMS samskiptamátinn +Comment[it]=Protocollo SMS +Comment[ja]=SMS プロトコル +Comment[ka]= SMS ოქმი +Comment[kk]=SMS протоколы +Comment[km]=ពិធីការសេវាសារខ្លីៗ +Comment[lt]=SMS protokolas +Comment[mk]=SMS-протокол +Comment[ms]=Protokol SMS +Comment[nb]=SMS Protokoll +Comment[nds]=SMS-Protokoll +Comment[ne]=एसएमएस प्रोटोकल +Comment[nl]=SMS-protocol +Comment[nn]=SMS-protokoll +Comment[pl]=Protokół SMS +Comment[pt]=Protocolo SMS +Comment[pt_BR]=Protocolo SMS +Comment[ru]=протокол SMS +Comment[se]=SMS-protokolla +Comment[sk]=Protokol SMS +Comment[sl]=Protokol SMS +Comment[sr]=SMS протокол +Comment[sr@Latn]=SMS protokol +Comment[sv]=SMS-protokoll +Comment[ta]=SMS நெறிமுறை +Comment[tg]=протоколи SMS +Comment[tr]=SMS Protokolü +Comment[uk]=Протокол SMS +Comment[zh_CN]=短信息协议 +Comment[zh_TW]=SMS 協定 +Name=SMS +Name[fa]=پیام کوتاه +Name[km]=សេវាសារខ្លីៗ +Name[ne]=एसएमएस +Name[zh_CN]=短信息 + diff --git a/kaddressbook/editors/protocols/yahooprotocol.desktop b/kaddressbook/editors/protocols/yahooprotocol.desktop new file mode 100644 index 000000000..c3055472e --- /dev/null +++ b/kaddressbook/editors/protocols/yahooprotocol.desktop @@ -0,0 +1,66 @@ +[Desktop Entry] +Type=Service +Icon=yahoo_protocol +ServiceTypes=KABC/IMProtocol,KPluginInfo +X-KDE-InstantMessagingKABCField=messaging/yahoo +Comment=Yahoo Protocol +Comment[af]=Yahoo protokol +Comment[ar]=ميفاق Yahoo +Comment[be]=Пратакол Yahoo +Comment[bg]=Протокол Yahoo +Comment[br]=Komenad Yahoo +Comment[bs]=Yahoo protokol +Comment[ca]=Protocol Yahoo +Comment[cs]=Yahoo protokol +Comment[da]=Yahoo Protokol +Comment[de]=Yahoo!-Protokoll +Comment[el]=Πρωτόκολλο Yahoo +Comment[eo]=Yahoo Protokolo +Comment[es]=Protocolo Yahoo +Comment[et]=Yahoo protokoll +Comment[eu]=Yahoo protokoloa +Comment[fa]=قرارداد یاهو +Comment[fi]=Yahoo-protokolla +Comment[fr]=Protocole Yahoo +Comment[fy]=Yahoo-protokol +Comment[ga]=Prótacal Yahoo +Comment[gl]=Protocolo Yahoo +Comment[he]=פרוטוקול Yahoo +Comment[hu]=Yahoo protokoll +Comment[is]=Yahoo samskiptamátinn +Comment[it]=Protocollo Yahoo +Comment[ja]=Yahoo プロトコル +Comment[ka]=Yahoo ოქმი +Comment[kk]=Yahoo протоколы +Comment[km]=ពិធីការយ៉ាហ៊ូ +Comment[lt]=Yahoo protokolas +Comment[mk]=Yahoo-протокол +Comment[ms]=Protokol Yahoo +Comment[nb]=Yahoo-protokoll +Comment[nds]=Yahoo-Protokoll +Comment[ne]=याहू प्रोटोकल +Comment[nl]=Yahoo-protocol +Comment[nn]=Yahoo-protokoll +Comment[pl]=Protokół Yahoo +Comment[pt]=Protocolo Yahoo +Comment[pt_BR]=Protocolo Yahoo +Comment[ru]=Протокол Yahoo +Comment[se]=Yahoo-protokolla +Comment[sk]=Protokol Yahoo +Comment[sl]=Protokol Yahoo +Comment[sr]=Yahoo протокол +Comment[sr@Latn]=Yahoo protokol +Comment[sv]=Yahoo-protokoll +Comment[ta]=Yahoo நெறிமுறை +Comment[tg]=Протоколи Yahoo +Comment[tr]=Yahoo Protokolü +Comment[uk]=Протокол Yahoo +Comment[zh_CN]=Yahoo 协议 +Comment[zh_TW]=Yahoo 協定 +Name=Yahoo +Name[de]=Yahoo! +Name[fa]=یاهو +Name[km]=យ៉ាហ៊ូ +Name[ne]=याहू +Name[pa]=ਯਾਹੂ + diff --git a/kaddressbook/emaileditwidget.cpp b/kaddressbook/emaileditwidget.cpp new file mode 100644 index 000000000..8fc857f7e --- /dev/null +++ b/kaddressbook/emaileditwidget.cpp @@ -0,0 +1,352 @@ +/* + This file is part of KAddressBook. + Copyright (c) 2002 Mike Pilone <mpilone@slac.com> + + 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 <qlabel.h> +#include <qlayout.h> +#include <qpainter.h> +#include <qpushbutton.h> +#include <qvalidator.h> +#include <qstring.h> +#include <qtoolbutton.h> +#include <qtooltip.h> + +#include <kaccelmanager.h> +#include <kconfig.h> +#include <kcombobox.h> +#include <kdebug.h> +#include <kdialog.h> +#include <kiconloader.h> +#include <kinputdialog.h> +#include <klineedit.h> +#include <klocale.h> +#include <kmessagebox.h> + +#include "emaileditwidget.h" + +class EmailValidator : public QRegExpValidator +{ + public: + EmailValidator() + : QRegExpValidator( 0, "EmailValidator" ) + { + QRegExp rx( ".*@.*\\.[A-Za-z]+" ); + setRegExp( rx ); + } +}; + +class EmailItem : public QListBoxText +{ + public: + EmailItem( QListBox *parent, const QString &text, bool preferred ) + : QListBoxText( parent, text ), mPreferred( preferred ) + {} + + void setPreferred( bool preferred ) { mPreferred = preferred; } + bool preferred() const { return mPreferred; } + + void setText( const QString &text ) + { + QListBoxText::setText( text ); + } + + protected: + virtual void paint( QPainter *p ) + { + if ( mPreferred ) { + QFont font = p->font(); + font.setBold( true ); + p->setFont( font ); + } + + QListBoxText::paint( p ); + } + + private: + bool mPreferred; +}; + +EmailEditWidget::EmailEditWidget( QWidget *parent, const char *name ) + : QWidget( parent, name ) +{ + QGridLayout *topLayout = new QGridLayout( this, 2, 2, KDialog::marginHint(), + KDialog::spacingHint() ); + + QLabel *label = new QLabel( i18n( "Email:" ), this ); + topLayout->addWidget( label, 0, 0 ); + + mEmailEdit = new KLineEdit( this ); + mEmailEdit->setValidator( new EmailValidator ); + connect( mEmailEdit, SIGNAL( textChanged( const QString& ) ), + SLOT( textChanged( const QString& ) ) ); + connect( mEmailEdit, SIGNAL( textChanged( const QString& ) ), + SIGNAL( modified() ) ); + label->setBuddy( mEmailEdit ); + topLayout->addWidget( mEmailEdit, 0, 1 ); + + mEditButton = new QPushButton( i18n( "Edit Email Addresses..." ), this); + connect( mEditButton, SIGNAL( clicked() ), SLOT( edit() ) ); + topLayout->addMultiCellWidget( mEditButton, 1, 1, 0, 1 ); + + topLayout->activate(); +} + +EmailEditWidget::~EmailEditWidget() +{ +} + +void EmailEditWidget::setReadOnly( bool readOnly ) +{ + mEmailEdit->setReadOnly( readOnly ); + mEditButton->setEnabled( !readOnly ); +} + +void EmailEditWidget::setEmails( const QStringList &list ) +{ + mEmailList = list; + + bool blocked = mEmailEdit->signalsBlocked(); + mEmailEdit->blockSignals( true ); + if ( list.count() > 0 ) + mEmailEdit->setText( list[ 0 ] ); + else + mEmailEdit->setText( "" ); + mEmailEdit->blockSignals( blocked ); +} + +QStringList EmailEditWidget::emails() +{ + if ( mEmailEdit->text().isEmpty() ) { + if ( mEmailList.count() > 0 ) + mEmailList.remove( mEmailList.begin() ); + } else { + if ( mEmailList.count() > 0 ) + mEmailList.remove( mEmailList.begin() ); + + mEmailList.prepend( mEmailEdit->text() ); + } + + return mEmailList; +} + +void EmailEditWidget::edit() +{ + EmailEditDialog dlg( mEmailList, this ); + + if ( dlg.exec() ) { + if ( dlg.changed() ) { + mEmailList = dlg.emails(); + mEmailEdit->setText( mEmailList[ 0 ] ); + emit modified(); + } + } +} + +void EmailEditWidget::textChanged( const QString &text ) +{ + if ( mEmailList.count() > 0 ) + mEmailList.remove( mEmailList.begin() ); + + mEmailList.prepend( text ); +} + + +EmailEditDialog::EmailEditDialog( const QStringList &list, QWidget *parent, + const char *name ) + : KDialogBase( KDialogBase::Plain, i18n( "Edit Email Addresses" ), + KDialogBase::Ok | KDialogBase::Cancel, KDialogBase::Help, + parent, name, true ) +{ + QWidget *page = plainPage(); + + QGridLayout *topLayout = new QGridLayout( page, 4, 3, 0, spacingHint() ); + + mEmailListBox = new QListBox( page ); + + // Make sure there is room for the scrollbar + mEmailListBox->setMinimumHeight( mEmailListBox->sizeHint().height() + 30 ); + connect( mEmailListBox, SIGNAL( highlighted( int ) ), + SLOT( selectionChanged( int ) ) ); + connect( mEmailListBox, SIGNAL( selected( int ) ), + SLOT( edit() ) ); + topLayout->addMultiCellWidget( mEmailListBox, 0, 3, 0, 1 ); + + mAddButton = new QPushButton( i18n( "Add..." ), page ); + connect( mAddButton, SIGNAL( clicked() ), SLOT( add() ) ); + topLayout->addWidget( mAddButton, 0, 2 ); + + mEditButton = new QPushButton( i18n( "Edit..." ), page ); + connect( mEditButton, SIGNAL( clicked() ), SLOT( edit() ) ); + topLayout->addWidget( mEditButton, 1, 2 ); + + mRemoveButton = new QPushButton( i18n( "Remove" ), page ); + connect( mRemoveButton, SIGNAL( clicked() ), SLOT( remove() ) ); + topLayout->addWidget( mRemoveButton, 2, 2 ); + + mStandardButton = new QPushButton( i18n( "Set Standard" ), page ); + connect( mStandardButton, SIGNAL( clicked() ), SLOT( standard() ) ); + topLayout->addWidget( mStandardButton, 3, 2 ); + + topLayout->activate(); + + QStringList items = list; + if ( items.remove( "" ) > 0 ) + mChanged = true; + else + mChanged = false; + + QStringList::ConstIterator it; + bool preferred = true; + for ( it = items.begin(); it != items.end(); ++it ) { + new EmailItem( mEmailListBox, *it, preferred ); + preferred = false; + } + + // set default state + selectionChanged( -1 ); + KAcceleratorManager::manage( this ); + + setInitialSize( QSize( 400, 200 ) ); +} + +EmailEditDialog::~EmailEditDialog() +{ +} + +QStringList EmailEditDialog::emails() const +{ + QStringList emails; + + for ( uint i = 0; i < mEmailListBox->count(); ++i ) { + EmailItem *item = static_cast<EmailItem*>( mEmailListBox->item( i ) ); + if ( item->preferred() ) + emails.prepend( item->text() ); + else + emails.append( item->text() ); + } + + return emails; +} + +void EmailEditDialog::add() +{ + EmailValidator *validator = new EmailValidator; + bool ok = false; + + QString email = KInputDialog::getText( i18n( "Add Email" ), i18n( "New Email:" ), + QString::null, &ok, this, "EmailEditDialog", + validator ); + + if ( !ok ) + return; + + // check if item already available, ignore if so... + for ( uint i = 0; i < mEmailListBox->count(); ++i ) { + if ( mEmailListBox->text( i ) == email ) + return; + } + + new EmailItem( mEmailListBox, email, (mEmailListBox->count() == 0) ); + + mChanged = true; +} + +void EmailEditDialog::edit() +{ + EmailValidator *validator = new EmailValidator; + bool ok = false; + + int editPos = mEmailListBox->currentItem(); + + QString email = KInputDialog::getText( i18n( "Edit Email" ), i18n( "Email:" ), + mEmailListBox->text( editPos ), &ok, this, + "EmailEditDialog", validator ); + + if ( !ok ) + return; + + // check if item already available, ignore if so... + for ( uint i = 0; i < mEmailListBox->count(); ++i ) { + if ( mEmailListBox->text( i ) == email ) + return; + } + + EmailItem *item = static_cast<EmailItem*>( mEmailListBox->item( editPos ) ); + item->setText( email ); + mEmailListBox->triggerUpdate( true ); + + mChanged = true; +} + +void EmailEditDialog::remove() +{ + QString address = mEmailListBox->currentText(); + + QString text = i18n( "<qt>Are you sure that you want to remove the email address <b>%1</b>?</qt>" ).arg( address ); + QString caption = i18n( "Confirm Remove" ); + + if ( KMessageBox::warningContinueCancel( this, text, caption, KGuiItem( i18n("&Delete"), "editdelete") ) == KMessageBox::Continue) { + EmailItem *item = static_cast<EmailItem*>( mEmailListBox->item( mEmailListBox->currentItem() ) ); + + bool preferred = item->preferred(); + mEmailListBox->removeItem( mEmailListBox->currentItem() ); + if ( preferred ) { + item = dynamic_cast<EmailItem*>( mEmailListBox->item( 0 ) ); + if ( item ) + item->setPreferred( true ); + } + + mChanged = true; + } +} + +bool EmailEditDialog::changed() const +{ + return mChanged; +} + +void EmailEditDialog::standard() +{ + for ( uint i = 0; i < mEmailListBox->count(); ++i ) { + EmailItem *item = static_cast<EmailItem*>( mEmailListBox->item( i ) ); + if ( (int)i == mEmailListBox->currentItem() ) + item->setPreferred( true ); + else + item->setPreferred( false ); + } + + mEmailListBox->triggerUpdate( true ); + + mChanged = true; +} + +void EmailEditDialog::selectionChanged( int index ) +{ + bool value = ( index >= 0 ); // An item is selected + + mRemoveButton->setEnabled( value ); + mEditButton->setEnabled( value ); + mStandardButton->setEnabled( value ); +} + +#include "emaileditwidget.moc" diff --git a/kaddressbook/emaileditwidget.h b/kaddressbook/emaileditwidget.h new file mode 100644 index 000000000..a8cef6761 --- /dev/null +++ b/kaddressbook/emaileditwidget.h @@ -0,0 +1,99 @@ +/* + This file is part of KAddressBook. + Copyright (c) 2002 Mike Pilone <mpilone@slac.com> + + 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 EMAILEDITWIDGET_H +#define EMAILEDITWIDGET_H + +#include <kabc/addressee.h> +#include <kdialogbase.h> + +class QButtonGroup; +class QCheckBox; +class QListView; +class QTextEdit; +class QToolButton; + +class KComboBox; +class KLineEdit; +class KListView; + +/** + This widget displays a list box of the email addresses as well as buttons + to manipulate them (up, down, add, remove). +*/ +class EmailEditWidget : public QWidget +{ + Q_OBJECT + + public: + EmailEditWidget( QWidget *parent, const char *name = 0 ); + ~EmailEditWidget(); + + void setEmails( const QStringList &list ); + QStringList emails(); + + void setReadOnly( bool readOnly ); + + signals: + void modified(); + + private slots: + void edit(); + void textChanged( const QString& ); + + private: + KLineEdit *mEmailEdit; + QPushButton *mEditButton; + QStringList mEmailList; +}; + +class EmailEditDialog : public KDialogBase +{ + Q_OBJECT + + public: + EmailEditDialog( const QStringList &list, QWidget *parent, + const char *name = 0 ); + ~EmailEditDialog(); + + QStringList emails() const; + bool changed() const; + + protected slots: + void add(); + void edit(); + void remove(); + void standard(); + void selectionChanged( int ); + + private: + QListBox *mEmailListBox; + QPushButton *mAddButton; + QPushButton *mRemoveButton; + QPushButton *mEditButton; + QPushButton *mStandardButton; + + bool mChanged; +}; + +#endif diff --git a/kaddressbook/extensionmanager.cpp b/kaddressbook/extensionmanager.cpp new file mode 100644 index 000000000..121c6a1c7 --- /dev/null +++ b/kaddressbook/extensionmanager.cpp @@ -0,0 +1,256 @@ +/* + 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 <kactionclasses.h> +#include <kconfig.h> +#include <kdebug.h> +#include <klocale.h> +#include <ktrader.h> + +#include <qlayout.h> +#include <qobjectlist.h> +#include <qsignalmapper.h> +#include <qsplitter.h> +#include <qtimer.h> +#include <qwidgetstack.h> + +#include "addresseeeditorextension.h" +#include "core.h" +#include "kabprefs.h" + +#include "extensionmanager.h" + +ExtensionData::ExtensionData() : action( 0 ), widget( 0 ), weight( 0 ), isDetailsExtension( false ) +{ +} + +ExtensionManager::ExtensionManager( QWidget* extensionBar, QWidgetStack* detailsStack, KAB::Core *core, QObject *parent, + const char *name ) + : QObject( parent, name ), mExtensionBar( extensionBar ), mCore( core ), + mMapper( 0 ), mDetailsStack( detailsStack ), mActiveDetailsWidget( 0 ) +{ + Q_ASSERT( mExtensionBar ); + QVBoxLayout* layout = new QVBoxLayout( mExtensionBar ); + mSplitter = new QSplitter( mExtensionBar ); + mSplitter->setOrientation( QSplitter::Vertical ); + layout->addWidget( mSplitter ); + + createExtensionWidgets(); + + mActionCollection = new KActionCollection( this, "ActionCollection" ); + + extensionBar->setShown( false ); + QTimer::singleShot( 0, this, SLOT( createActions() ) ); +} + +ExtensionManager::~ExtensionManager() +{ +} + + +void ExtensionManager::restoreSettings() +{ + const QStringList activeExtensions = KABPrefs::instance()->activeExtensions(); + + typedef QMap<QString, ExtensionData>::ConstIterator ConstIterator; + for ( ConstIterator it = mExtensionMap.begin(), end = mExtensionMap.end(); it != end; ++it ) { + if ( activeExtensions.contains( it.data().identifier ) ) { + KToggleAction *action = static_cast<KToggleAction*>( it.data().action ); + if ( action ) + action->setChecked( true ); + setExtensionActive( it.data().identifier, true ); + } + } + const QValueList<int> sizes = KABPrefs::instance()->extensionsSplitterSizes(); + mSplitter->setSizes( sizes ); +} + +void ExtensionManager::saveSettings() +{ + KABPrefs::instance()->setActiveExtensions( mActiveExtensions ); + KABPrefs::instance()->setExtensionsSplitterSizes( mSplitter->sizes() ); +} + +void ExtensionManager::reconfigure() +{ + saveSettings(); + createExtensionWidgets(); + createActions(); + restoreSettings(); + mExtensionBar->setShown( !mActiveExtensions.isEmpty() ); +} + +bool ExtensionManager::isQuickEditVisible() const +{ + return mActiveExtensions.contains( "contact_editor" ); +} + +void ExtensionManager::setSelectionChanged() +{ + for ( QStringList::ConstIterator it = mActiveExtensions.begin(), end = mActiveExtensions.end(); it != end; ++it ) { + if ( mExtensionMap.contains( *it ) && mExtensionMap[*it].widget ) + mExtensionMap[*it].widget->contactsSelectionChanged(); + } +} + +void ExtensionManager::activationToggled( const QString &extid ) +{ + if ( !mExtensionMap.contains( extid ) ) + return; + const ExtensionData data = mExtensionMap[ extid ]; + const bool activated = data.action->isChecked(); + setExtensionActive( extid, activated ); +} + +void ExtensionManager::setExtensionActive( const QString& extid, bool active ) +{ + if ( !mExtensionMap.contains( extid ) ) + return; + if ( mActiveExtensions.contains( extid ) == active ) + return; + const ExtensionData data = mExtensionMap[ extid ]; + if ( active ) { + mActiveExtensions.append( extid ); + if ( data.widget ) { + if ( data.isDetailsExtension ) { + mActiveDetailsWidget = data.widget; + emit detailsWidgetActivated( data.widget ); + } else { + data.widget->show(); + } + data.widget->contactsSelectionChanged(); + } + } else { + mActiveExtensions.remove( extid ); + if ( data.widget && !data.isDetailsExtension ) { + data.widget->hide(); + } + if ( data.isDetailsExtension ) { + mActiveDetailsWidget = 0; + emit detailsWidgetDeactivated( data.widget ); + } + } + mExtensionBar->setShown( !mActiveExtensions.isEmpty() ); +} + +void ExtensionManager::createActions() +{ + mCore->guiClient()->unplugActionList( "extensions_list" ); + mActionList.setAutoDelete( true ); + mActionList.clear(); + mActionList.setAutoDelete( false ); + + delete mMapper; + mMapper = new QSignalMapper( this, "SignalMapper" ); + connect( mMapper, SIGNAL( mapped( const QString& ) ), + this, SLOT( activationToggled( const QString& ) ) ); + + ExtensionData::List::ConstIterator it; + for ( QMap<QString, ExtensionData>::Iterator it = mExtensionMap.begin(), end = mExtensionMap.end(); it != end; ++it ) { + ExtensionData& data = it.data(); + data.action = new KToggleAction( data.title, 0, mMapper, SLOT( map() ), + mActionCollection, + QString( data.identifier + "_extension" ).latin1() ); + mMapper->setMapping( data.action, data.identifier ); + mActionList.append( data.action ); + + if ( mActiveExtensions.contains( data.identifier ) ) + data.action->setChecked( true ); + } + + mActionList.append( new KActionSeparator( mActionCollection ) ); + mCore->guiClient()->plugActionList( "extensions_list", mActionList ); +} + +QWidget* ExtensionManager::activeDetailsWidget() const +{ + return mActiveDetailsWidget; +} + +void ExtensionManager::createExtensionWidgets() +{ + // clean up + for ( QMap<QString, ExtensionData>::ConstIterator it = mExtensionMap.begin(), end = mExtensionMap.end(); it != end; ++it ) { + delete it.data().widget; + } + mExtensionMap.clear(); + + KAB::ExtensionWidget *wdg = 0; + + { + // add addressee editor as default + wdg = new AddresseeEditorExtension( mCore, mDetailsStack ); + wdg->hide(); + + connect( wdg, SIGNAL( modified( const KABC::Addressee::List& ) ), + SIGNAL( modified( const KABC::Addressee::List& ) ) ); + connect( wdg, SIGNAL( deleted( const QStringList& ) ), + SIGNAL( deleted( const QStringList& ) ) ); + + ExtensionData data; + data.identifier = wdg->identifier(); + data.title = wdg->title(); + data.widget = wdg; + data.isDetailsExtension = true; + mExtensionMap.insert( data.identifier, data ); + } + + // load the other extensions + const KTrader::OfferList plugins = KTrader::self()->query( "KAddressBook/Extension", + QString( "[X-KDE-KAddressBook-ExtensionPluginVersion] == %1" ).arg( KAB_EXTENSIONWIDGET_PLUGIN_VERSION ) ); + + KTrader::OfferList::ConstIterator it; + for ( it = plugins.begin(); it != plugins.end(); ++it ) { + KLibFactory *factory = KLibLoader::self()->factory( (*it)->library().latin1() ); + if ( !factory ) { + kdDebug(5720) << "ExtensionManager::loadExtensions(): Factory creation failed" << endl; + continue; + } + + KAB::ExtensionFactory *extensionFactory = static_cast<KAB::ExtensionFactory*>( factory ); + + if ( !extensionFactory ) { + kdDebug(5720) << "ExtensionManager::loadExtensions(): Cast failed" << endl; + continue; + } + + wdg = extensionFactory->extension( mCore, mSplitter ); + if ( wdg ) { + if ( wdg->identifier() == "distribution_list_editor_ng" ) + mSplitter->moveToFirst( wdg ); + wdg->hide(); + connect( wdg, SIGNAL( modified( const KABC::Addressee::List& ) ), + SIGNAL( modified( const KABC::Addressee::List& ) ) ); + connect( wdg, SIGNAL( deleted( const QStringList& ) ), + SIGNAL( deleted( const QStringList& ) ) ); + + ExtensionData data; + data.identifier = wdg->identifier(); + data.title = wdg->title(); + data.widget = wdg; + mExtensionMap.insert( data.identifier, data ); + } + } +} + +#include "extensionmanager.moc" diff --git a/kaddressbook/extensionmanager.h b/kaddressbook/extensionmanager.h new file mode 100644 index 000000000..5ecc725b3 --- /dev/null +++ b/kaddressbook/extensionmanager.h @@ -0,0 +1,118 @@ +/* + 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 EXTENSIONMANAGER_H +#define EXTENSIONMANAGER_H + +#include "extensionwidget.h" + +#include <qwidget.h> +#include <qmap.h> +#include <qptrlist.h> +#include <qstringlist.h> + +class QSignalMapper; +class QWidgetStack; +class KActionCollection; + +namespace KAB { +class Core; +} + +class ExtensionData +{ + public: + ExtensionData(); + typedef QValueList<ExtensionData> List; + + KToggleAction* action; + KAB::ExtensionWidget *widget; + QString identifier; + QString title; + int weight; + bool isDetailsExtension; +}; + +class ExtensionManager : public QObject +{ + Q_OBJECT + + public: + ExtensionManager( QWidget *extensionBar, QWidgetStack *detailsStack, KAB::Core *core, QObject *parent, const char *name = 0 ); + ~ExtensionManager(); + + /** + Restores the extension manager specific settings. + */ + void restoreSettings(); + + /** + Saves the extension manager specific settings. + */ + void saveSettings(); + + /** + Rereads the extension manager specific settings with some + additional initialization stuff. + */ + void reconfigure(); + + /** + Returns whether the quickedit extension is currently visible. + */ + bool isQuickEditVisible() const; + + QWidget *activeDetailsWidget() const; + + public slots: + void setSelectionChanged(); + void createActions(); + + signals: + + void detailsWidgetActivated( QWidget* widget ); + void detailsWidgetDeactivated( QWidget* widget ); + void modified( const KABC::Addressee::List& ); + void deleted( const QStringList& ); + + private slots: + void activationToggled( const QString &extid ); + + private: + void createExtensionWidgets(); + void setExtensionActive( const QString &extid, bool active ); + + private: + QWidget *mExtensionBar; + KAB::Core *mCore; + QMap<QString, ExtensionData> mExtensionMap; + QStringList mActiveExtensions; + QSignalMapper *mMapper; + QPtrList<KAction> mActionList; + KActionCollection *mActionCollection; + QSplitter *mSplitter; + QWidgetStack *mDetailsStack; + QWidget *mActiveDetailsWidget; +}; + +#endif diff --git a/kaddressbook/features/Makefile.am b/kaddressbook/features/Makefile.am new file mode 100644 index 000000000..d3311c77b --- /dev/null +++ b/kaddressbook/features/Makefile.am @@ -0,0 +1,36 @@ +INCLUDES = -I$(top_srcdir)/kaddressbook/interfaces -I$(top_srcdir)/kaddressbook \ + -I$(top_srcdir) $(all_includes) + +if compile_newdistrlists +TARGET_DISTRIBUTIONLISTNG=libkaddrbk_distributionlistng.la +DISTRIBUTIONLISTNG_DESKTOPFILE=distributionlistng.desktop +else +DISTRIBUTIONLIST_DESKTOPFILE=distributionlist.desktop +endif + +kde_module_LTLIBRARIES = $(TARGET_DISTRIBUTIONLISTNG) libkaddrbk_distributionlist.la libkaddrbk_resourceselection.la + +XXLIBS = $(top_builddir)/kaddressbook/interfaces/libkabinterfaces.la \ + $(top_builddir)/libkdepim/libkdepim.la + + +if compile_newdistrlists +libkaddrbk_distributionlistng_la_SOURCES = distributionlistngwidget.cpp +libkaddrbk_distributionlistng_la_LDFLAGS = -module $(KDE_PLUGIN) $(KDE_RPATH) $(all_libraries) -no-undefined +libkaddrbk_distributionlistng_la_LIBADD = $(XXLIBS) +else +libkaddrbk_distributionlist_la_SOURCES = distributionlistwidget.cpp +libkaddrbk_distributionlist_la_LDFLAGS = -module $(KDE_PLUGIN) $(KDE_RPATH) $(all_libraries) -no-undefined +libkaddrbk_distributionlist_la_LIBADD = $(XXLIBS) +endif + +libkaddrbk_resourceselection_la_SOURCES = resourceselection.cpp +libkaddrbk_resourceselection_la_LDFLAGS = -module $(KDE_PLUGIN) $(KDE_RPATH) $(all_libraries) -no-undefined +libkaddrbk_resourceselection_la_LIBADD = $(XXLIBS) + +noinst_HEADERS = distributionlistwidget.h distributionlistngwidget.h resourceselection.h + +METASOURCES = AUTO + +servicedir = $(kde_servicesdir)/kaddressbook +service_DATA = $(DISTRIBUTIONLISTNG_DESKTOPFILE) $(DISTRIBUTIONLIST_DESKTOPFILE) resourceselection.desktop diff --git a/kaddressbook/features/distributionlist.desktop b/kaddressbook/features/distributionlist.desktop new file mode 100644 index 000000000..b05d7b5e8 --- /dev/null +++ b/kaddressbook/features/distributionlist.desktop @@ -0,0 +1,116 @@ +[Desktop Entry] +X-KDE-Library=libkaddrbk_distributionlist +Name=KAB Distribution List Plugin +Name[af]=KAB verspreiding lys inprop module +Name[ar]=ملحق قائمة توزيع KAB +Name[be]=Дапаўненне KAB "Сьпіс распаўсюджвання" +Name[bg]=Приставка за списъка за разпращане на KAB +Name[br]=Lugent roll ingaladur evit KAB +Name[bs]=KAB dodatak za distribucione liste +Name[ca]=Endollable de la llista de distribució KAB +Name[cs]=Modul distribučního seznamu +Name[cy]=Ategyn Rhestr Ddosbarthu KAB +Name[da]=KAB-Distribution liste-plugin +Name[de]=Verteilerlisten-Modul für Adressbuch +Name[el]=Πρόσθετο λίστας διανομής του KAB +Name[eo]=KAB Distribulista Kromprogramo +Name[es]=Plugin KAB para listas de distribución +Name[et]=KAB postiloendi plugin +Name[eu]=KAB banaketa zerrenda plugin-a +Name[fa]=وصلۀ فهرست توزیع KAB +Name[fi]=KAB-jakelulistaliitännäinen +Name[fr]=Module de liste de diffusion pour KAB +Name[fy]=KAB Distribúsjelist-plugin +Name[gl]=Extensión de Lista de Distribución KAB +Name[hi]=केएबी वितरण सूची प्लगइन +Name[hu]=KAB címlista bővítőmodul +Name[is]=Íforrit fyrir KAB dreifilista +Name[it]=Plugin lista di distribuzione KAB +Name[ja]=KAB 配布リストプラグイン +Name[ka]=KAB დისტრიბუციის სიის მოდული +Name[kk]=KAB тарату тізімінің плагин модулі +Name[km]=កម្មវិធីជំនួយបញ្ជីចែកចាយរបស់ KAB +Name[lt]=KAB platinimo sąrašo priedas +Name[ms]=Plugin Senarai Agihan KAB +Name[nb]=KAB programtillegg for distribusjonslister +Name[nds]=Verdeellist-Moduul för KAdressbook +Name[ne]=KAB वितरण सूची प्लगइन +Name[nl]=KAB Distributielijst-plugin +Name[nn]=Programtillegg for KAB distribusjonsliste +Name[pl]=Wtyczka KAB do obsługi list wysyłkowych +Name[pt]='Plugin' de Lista de Distribuição do KAB +Name[pt_BR]=Plug-in de Lista de Distribuição do KAB +Name[ru]=Списки рассылки +Name[se]=KAB:a distribušuvdnalistu lassemoduvla +Name[sk]=KAB plugin distribučného zoznamu +Name[sl]=Vstavek za distribucijski seznam KAB +Name[sr]=Прикључак KAB-а за дистрибуционе листе +Name[sr@Latn]=Priključak KAB-a za distribucione liste +Name[sv]=Adressbokens insticksprogram för distributionslistor +Name[ta]=KABயின் பகிர்ந்தளித்தல் பட்டியல் சொருகுப்பொருள் +Name[tg]=Рӯйхати ба ҳар тараф мефиристодагӣ +Name[tr]=KAB Dağıtım Listesi Eklentisi +Name[uk]=Втулок списку розповсюдження KAB +Name[uz]=Tarqatish roʻyxat plagini +Name[uz@cyrillic]=Тарқатиш рўйхат плагини +Name[zh_CN]=KAB 分发列表插件 +Comment=Plugin for managing distribution lists +Comment[af]=Inprop module vir die bestuur van verspreiding lyste +Comment[ar]=ملحق لإدارة قوائم التوزيع +Comment[be]=Дапаўненне для кіравання сьпісамі распаўсюджвання +Comment[bg]=Приставка за управление на списъци +Comment[br]=Lugent melestradur ar rolloù ingaladur +Comment[bs]=Dodatak za upravljanje distribucionim listama +Comment[ca]=Endollable per a gestionar llistes de distribució +Comment[cs]=Modul pro správu distribučních seznamů +Comment[cy]=Ategyn ar gyfer rheoli rhestri dosbarthu +Comment[da]=Plugin til at håndtere distributionslister +Comment[de]=Modul zur Verwaltung von Verteilerlisten +Comment[el]=Πρόσθετο για τη διαχείριση λιστών διανομής +Comment[eo]=Kromaĵo por administri distribulistojn +Comment[es]=Plugin para gestionar listas de distribución +Comment[et]=Plugin postiloendite haldamiseks +Comment[eu]=Banaketa zerrendak kudeatzeko plugin-a +Comment[fa]=وصله برای مدیریت فهرستهای توزیع +Comment[fi]=Liitännäinen jakelulistojen hallintaan +Comment[fr]=Module pour gérer des listes de diffusion +Comment[fy]=Plugin foar nit behearen fan distribúsjelisten +Comment[gl]=Plugin para manexar listas de distribución +Comment[he]=תוסף לניהול רשימות תפוצה +Comment[hi]=वितरण सूची प्रबंधन के लिए प्लगइन +Comment[hu]=Bővítőmodul címlisták kezeléséhez +Comment[is]=Íforrit til að sjá um dreifilista +Comment[it]=Plugin per gestire liste di distribuzione +Comment[ja]=配布リスト管理用プラグイン +Comment[ka]=სადისტრიბუციო სიათა მართვის მოდული +Comment[kk]=Тарату тізімімен айналысу плагин модулі +Comment[km]=កម្មវិធីជំនួយដើម្បីគ្រប់គ្រងបញ្ជីចែកចាយ +Comment[lt]=Priedas platinimo sąrašų tvarkymui +Comment[ms]=Plug masuk untuk pengurusan senarai edaran +Comment[nb]=Programtillegg for å håndtere distribusjonslister +Comment[nds]=Moduul för't Plegen vun Verdeellisten +Comment[ne]=व्यवस्थापन वितरण सूचीका लागि प्लगइन +Comment[nl]=Plugin voor het beheren van distributielijsten +Comment[nn]=Programtillegg for handtering av distibusjonsliste +Comment[pl]=Wtyczka do zarządzania listami wysyłkowymi +Comment[pt]=Um 'plugin' para gerir as listas de distribuição +Comment[pt_BR]=Plug-in para gerenciar listas de distribuição +Comment[ro]=Modul pentru administrarea listelor de distribuţie +Comment[ru]=Работа со списками рассылок +Comment[se]=Lassemoduvla mii gieđahallá distribušuvdnalisttuid +Comment[sk]=Plugin pre správu distribučných zoznamov +Comment[sl]=Vstavek za upravljanje distribucijskih seznamov +Comment[sr]=Прикључак за управљање дистрибуционим листама +Comment[sr@Latn]=Priključak za upravljanje distribucionim listama +Comment[sv]=Insticksprogram för att hantera distributionslistor +Comment[ta]=பகிர்தல் பட்டியல் நிர்வகித்தலின் சொருகுப்பொருள் +Comment[tg]=Кор бо рӯйхати ба ҳар тараф мефиристодагӣ +Comment[tr]=Dağıtım listelerini yönetmek için eklenti +Comment[uk]=Втулок для керування списками розповсюдження +Comment[uz]=Tarqatish roʻyxatlarni boshqarish uchu plagin +Comment[uz@cyrillic]=Тарқатиш рўйхатларни бошқариш учу плагин +Comment[zh_CN]=管理分发列表的插件 +Comment[zh_TW]=管理分配清單外掛程式 +Type=Service +ServiceTypes=KAddressBook/Extension +X-KDE-KAddressBook-ExtensionPluginVersion=1 diff --git a/kaddressbook/features/distributionlistng.desktop b/kaddressbook/features/distributionlistng.desktop new file mode 100644 index 000000000..84d7070bb --- /dev/null +++ b/kaddressbook/features/distributionlistng.desktop @@ -0,0 +1,86 @@ +[Desktop Entry] +X-KDE-Library=libkaddrbk_distributionlistng +Name=KAB Distribution List Next Generation Plugin +Name[bg]=Приставка от следващо поколение за списъка за разпращане на KAB +Name[ca]=Endollable de la propera generació de la llista de distribució KAB +Name[da]=Næste generations-plugin til KAB-Distribution-liste +Name[de]=Verteilerlisten-Modul für neues Adressbuch +Name[el]=Πρόσθετο επόμενης γενιάς λίστας διανομής του KAB +Name[es]=Complemento de nueva generación KAB para listas de distribución +Name[et]=KAB postiloendi järgmise põlvkonna plugin +Name[fr]=Module de liste de diffusion nouvelle génération pour KAB +Name[is]=Næstu kynslóðar íforrit fyrir KAB dreifilista +Name[it]=Plugin lista di distribuzione KAB di nuova generazione +Name[ja]=KAB 配布リスト次世代プラグイン +Name[km]=កម្មវិធីជំនួយជំនាន់ក្រោយរបស់បញ្ជីចែកចាយ KAB +Name[nds]=Verbetert Verdeellist-Moduul för KAdressbook +Name[nl]=Plugin voor KAB Distributielijst (Nieuwe Generatie) +Name[pl]=Wtyczka KAB do obsługi list wysyłkowych +Name[ru]=Списки рассылки (новая версия) +Name[sk]=KAB plugin distribučného zoznamu ďaľšej generácie +Name[sr]=Прикључак KAB-а наредне генерације за дистрибуционе листе +Name[sr@Latn]=Priključak KAB-a naredne generacije za distribucione liste +Name[sv]=Adressbokens nästa generation insticksprogram för distributionslistor +Name[tr]=KAB Dağıtım Listesi Sonraki Kuşak Eklentisi +Name[zh_CN]=KAB 分发列表生成插件 +Name[zh_TW]=KAB 分派清單下一代外掛程式 +Comment=Plugin for managing distribution lists +Comment[af]=Inprop module vir die bestuur van verspreiding lyste +Comment[ar]=ملحق لإدارة قوائم التوزيع +Comment[be]=Дапаўненне для кіравання сьпісамі распаўсюджвання +Comment[bg]=Приставка за управление на списъци +Comment[br]=Lugent melestradur ar rolloù ingaladur +Comment[bs]=Dodatak za upravljanje distribucionim listama +Comment[ca]=Endollable per a gestionar llistes de distribució +Comment[cs]=Modul pro správu distribučních seznamů +Comment[cy]=Ategyn ar gyfer rheoli rhestri dosbarthu +Comment[da]=Plugin til at håndtere distributionslister +Comment[de]=Modul zur Verwaltung von Verteilerlisten +Comment[el]=Πρόσθετο για τη διαχείριση λιστών διανομής +Comment[eo]=Kromaĵo por administri distribulistojn +Comment[es]=Plugin para gestionar listas de distribución +Comment[et]=Plugin postiloendite haldamiseks +Comment[eu]=Banaketa zerrendak kudeatzeko plugin-a +Comment[fa]=وصله برای مدیریت فهرستهای توزیع +Comment[fi]=Liitännäinen jakelulistojen hallintaan +Comment[fr]=Module pour gérer des listes de diffusion +Comment[fy]=Plugin foar nit behearen fan distribúsjelisten +Comment[gl]=Plugin para manexar listas de distribución +Comment[he]=תוסף לניהול רשימות תפוצה +Comment[hi]=वितरण सूची प्रबंधन के लिए प्लगइन +Comment[hu]=Bővítőmodul címlisták kezeléséhez +Comment[is]=Íforrit til að sjá um dreifilista +Comment[it]=Plugin per gestire liste di distribuzione +Comment[ja]=配布リスト管理用プラグイン +Comment[ka]=სადისტრიბუციო სიათა მართვის მოდული +Comment[kk]=Тарату тізімімен айналысу плагин модулі +Comment[km]=កម្មវិធីជំនួយដើម្បីគ្រប់គ្រងបញ្ជីចែកចាយ +Comment[lt]=Priedas platinimo sąrašų tvarkymui +Comment[ms]=Plug masuk untuk pengurusan senarai edaran +Comment[nb]=Programtillegg for å håndtere distribusjonslister +Comment[nds]=Moduul för't Plegen vun Verdeellisten +Comment[ne]=व्यवस्थापन वितरण सूचीका लागि प्लगइन +Comment[nl]=Plugin voor het beheren van distributielijsten +Comment[nn]=Programtillegg for handtering av distibusjonsliste +Comment[pl]=Wtyczka do zarządzania listami wysyłkowymi +Comment[pt]=Um 'plugin' para gerir as listas de distribuição +Comment[pt_BR]=Plug-in para gerenciar listas de distribuição +Comment[ro]=Modul pentru administrarea listelor de distribuţie +Comment[ru]=Работа со списками рассылок +Comment[se]=Lassemoduvla mii gieđahallá distribušuvdnalisttuid +Comment[sk]=Plugin pre správu distribučných zoznamov +Comment[sl]=Vstavek za upravljanje distribucijskih seznamov +Comment[sr]=Прикључак за управљање дистрибуционим листама +Comment[sr@Latn]=Priključak za upravljanje distribucionim listama +Comment[sv]=Insticksprogram för att hantera distributionslistor +Comment[ta]=பகிர்தல் பட்டியல் நிர்வகித்தலின் சொருகுப்பொருள் +Comment[tg]=Кор бо рӯйхати ба ҳар тараф мефиристодагӣ +Comment[tr]=Dağıtım listelerini yönetmek için eklenti +Comment[uk]=Втулок для керування списками розповсюдження +Comment[uz]=Tarqatish roʻyxatlarni boshqarish uchu plagin +Comment[uz@cyrillic]=Тарқатиш рўйхатларни бошқариш учу плагин +Comment[zh_CN]=管理分发列表的插件 +Comment[zh_TW]=管理分配清單外掛程式 +Type=Service +ServiceTypes=KAddressBook/Extension +X-KDE-KAddressBook-ExtensionPluginVersion=1 diff --git a/kaddressbook/features/distributionlistngwidget.cpp b/kaddressbook/features/distributionlistngwidget.cpp new file mode 100644 index 000000000..fee8377a6 --- /dev/null +++ b/kaddressbook/features/distributionlistngwidget.cpp @@ -0,0 +1,249 @@ +/* + This file is part of KAddressBook. + Copyright (c) 2007 Klaralvdalens Datakonsult AB <frank@kdab.net> + + 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 "distributionlistngwidget.h" +#include "interfaces/core.h" +#include "searchmanager.h" + +#include <libkdepim/distributionlist.h> +#include <libkdepim/kvcarddrag.h> + +#include <kabc/vcardconverter.h> + +#include <kdialog.h> +#include <kiconloader.h> +#include <klistview.h> +#include <klocale.h> +#include <kpopupmenu.h> + +#include <qevent.h> +#include <qguardedptr.h> +#include <qlabel.h> +#include <qlayout.h> +#include <qpoint.h> +#include <qtimer.h> +#include <qpushbutton.h> +#include <qtooltip.h> + +KAB::DistributionListNg::ListBox::ListBox( QWidget* parent ) : KListBox( parent ) +{ + setAcceptDrops( true ); +} + +void KAB::DistributionListNg::ListBox::dragMoveEvent( QDragMoveEvent *event ) +{ + QListBoxItem *item = itemAt( event->pos() ); + if ( !item ) { + event->ignore(); + } + else { + event->accept( itemRect( item ) ); + } +} + +void KAB::DistributionListNg::ListBox::dragEnterEvent( QDragEnterEvent *event ) +{ + KListBox::dragEnterEvent( event ); +} + +void KAB::DistributionListNg::ListBox::dropEvent( QDropEvent *event ) +{ + QListBoxItem *item = itemAt( event->pos() ); + if ( !item || index( item ) == 0 ) + return; + + QString vcards; + if ( !KVCardDrag::decode( event, vcards ) ) + return; + + KABC::VCardConverter converter; + emit dropped( item->text(), converter.parseVCards( vcards ) ); +} + +namespace KAB { +namespace DistributionListNg { + +class Factory : public KAB::ExtensionFactory +{ + public: + KAB::ExtensionWidget *extension( KAB::Core *core, QWidget *parent, const char *name ) + { + return new KAB::DistributionListNg::MainWidget( core, parent, name ); + } + + QString identifier() const + { + return "distribution_list_editor"; + } +}; + +} +} + +extern "C" { + void *init_libkaddrbk_distributionlistng() + { + return ( new KAB::DistributionListNg::Factory ); + } +} + +QString KAB::DistributionListNg::MainWidget::title() const +{ + return i18n( "Distribution List Editor NG" ); +} + +QString KAB::DistributionListNg::MainWidget::identifier() const +{ + return "distribution_list_editor_ng"; +} + +KAB::DistributionListNg::MainWidget::MainWidget( KAB::Core *core, QWidget *parent, const char *name ) : KAB::ExtensionWidget( core, parent, name ) +{ + QVBoxLayout *layout = new QVBoxLayout( this ); + layout->setSpacing( KDialog::spacingHint() ); + + QHBoxLayout *buttonLayout = new QHBoxLayout(); + layout->addLayout( buttonLayout ); + + QLabel *label = new QLabel( this ); + label->setText( i18n( "Distribution Lists" ) ); + buttonLayout->addWidget( label ); + buttonLayout->addStretch( 1 ); + + mAddButton = new QPushButton( this ); + mAddButton->setIconSet( SmallIconSet( "add" ) ); + QToolTip::add( mAddButton, i18n( "Add distribution list" ) ); + connect( mAddButton, SIGNAL(clicked()), core, SLOT(newDistributionList()) ); + buttonLayout->addWidget( mAddButton ); + + mEditButton = new QPushButton( this ); + mEditButton->setIconSet( SmallIconSet( "edit" ) ); + QToolTip::add( mEditButton, i18n( "Edit distribution list" ) ); + connect( mEditButton, SIGNAL(clicked()), this, SLOT(editSelectedDistributionList()) ); + buttonLayout->addWidget( mEditButton ); + + mRemoveButton = new QPushButton( this ); + mRemoveButton->setIconSet( SmallIconSet( "remove" ) ); + QToolTip::add( mRemoveButton, i18n( "Remove distribution list" ) ); + connect( mRemoveButton, SIGNAL(clicked()), this, SLOT(deleteSelectedDistributionList()) ); + buttonLayout->addWidget( mRemoveButton ); + + mListBox = new ListBox( this ); + connect( mListBox, SIGNAL( contextMenuRequested( QListBoxItem*, const QPoint& ) ), + this, SLOT( contextMenuRequested( QListBoxItem*, const QPoint& ) ) ); + connect( mListBox, SIGNAL( dropped( const QString &, const KABC::Addressee::List & ) ), + this, SLOT( contactsDropped( const QString &, const KABC::Addressee::List & ) ) ); + connect( mListBox, SIGNAL( highlighted( int ) ), + this, SLOT( itemSelected( int ) ) ); + layout->addWidget( mListBox ); + + connect( core, SIGNAL( contactsUpdated() ), + this, SLOT( updateEntries() ) ); + connect( core->addressBook(), SIGNAL( addressBookChanged( AddressBook* ) ), + this, SLOT( updateEntries() ) ); + + // When contacts are changed, update both distr list combo and contents of displayed distr list + connect( core, SIGNAL( contactsUpdated() ), + this, SLOT( updateEntries() ) ); + + QTimer::singleShot( 0, this, SLOT( updateEntries() ) ); +} + +void KAB::DistributionListNg::MainWidget::contextMenuRequested( QListBoxItem *item, const QPoint &point ) +{ + QGuardedPtr<KPopupMenu> menu = new KPopupMenu( this ); + menu->insertItem( i18n( "New Distribution List..." ), core(), SLOT( newDistributionList() ) ); + if ( item ) + { + menu->insertItem( i18n( "Edit..." ), this, SLOT( editSelectedDistributionList() ) ); + menu->insertItem( i18n( "Delete" ), this, SLOT( deleteSelectedDistributionList() ) ); + } + menu->exec( point ); + delete menu; +} + +void KAB::DistributionListNg::MainWidget::editSelectedDistributionList() +{ + const QListBoxItem* const item = mListBox->selectedItem(); + if ( !item ) + return; + core()->editDistributionList( item->text() ); +} + +void KAB::DistributionListNg::MainWidget::deleteSelectedDistributionList() +{ + const QListBoxItem* const item = mListBox->selectedItem(); + const QString name = item ? item->text() : QString(); + if ( name.isNull() ) + return; + const KPIM::DistributionList list = KPIM::DistributionList::findByName( + core()->addressBook(), name ); + if ( list.isEmpty() ) + return; + core()->deleteDistributionLists( name ); +} + +void KAB::DistributionListNg::MainWidget::contactsDropped( const QString &listName, const KABC::Addressee::List &addressees ) +{ + if ( addressees.isEmpty() ) + return; + + KPIM::DistributionList list = KPIM::DistributionList::findByName( + core()->addressBook(), listName ); + if ( list.isEmpty() ) // not found [should be impossible] + return; + + for ( KABC::Addressee::List::ConstIterator it = addressees.begin(); it != addressees.end(); ++it ) { + list.insertEntry( *it ); + } + + core()->addressBook()->insertAddressee( list ); + changed( list ); +} + +void KAB::DistributionListNg::MainWidget::changed( const KABC::Addressee& dist ) +{ + emit modified( KABC::Addressee::List() << dist ); +} + +void KAB::DistributionListNg::MainWidget::updateEntries() +{ + const bool hadSelection = mListBox->selectedItem() != 0; + const QStringList newEntries = core()->distributionListNames(); + if ( !mCurrentEntries.isEmpty() && newEntries == mCurrentEntries ) + return; + mCurrentEntries = newEntries; + mListBox->clear(); + mListBox->insertItem( i18n( "All Contacts" ), 0 ); + mListBox->insertStringList( mCurrentEntries ); + if ( !hadSelection ) + mListBox->setSelected( 0, true ); +} + +void KAB::DistributionListNg::MainWidget::itemSelected( int index ) +{ + core()->setSelectedDistributionList( index == 0 ? QString() : mListBox->item( index )->text() ); + mEditButton->setEnabled( index > 0 ); + mRemoveButton->setEnabled( index > 0 ); +} + +#include "distributionlistngwidget.moc" diff --git a/kaddressbook/features/distributionlistngwidget.h b/kaddressbook/features/distributionlistngwidget.h new file mode 100644 index 000000000..4a174dd83 --- /dev/null +++ b/kaddressbook/features/distributionlistngwidget.h @@ -0,0 +1,104 @@ +/* + This file is part of KAddressBook. + Copyright (c) 2007 Klaralvdalens Datakonsult AB <frank@kdab.net> + + 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 KAB_DISTRIBUTIONLISTNG_MAINWIDGET_H +#define KAB_DISTRIBUTIONLISTNG_MAINWIDGET_H + +#include "extensionwidget.h" + +#include <kabc/addressee.h> + +#include <klistbox.h> + +#include <qstringlist.h> + +class QDragEnterEvent; +class QDragMoveEvent; +class QDropEvent; +class QPoint; +class QPushButton; + +namespace KABC { + class DistributionListManager; +} + +namespace KAB { +namespace DistributionListNg { + +class ListBox : public KListBox +{ + Q_OBJECT +public: + ListBox( QWidget* parent = 0 ); + +signals: + + void dropped( const QString &listName, const KABC::Addressee::List &addressees ); + +protected: + //override + void dragEnterEvent( QDragEnterEvent *event ); + //override + void dragMoveEvent( QDragMoveEvent *event ); + //override + void dropEvent( QDropEvent *event ); +}; + +class MainWidget : public KAB::ExtensionWidget +{ + Q_OBJECT + +public: + explicit MainWidget( KAB::Core *core, QWidget *parent = 0, const char *name = 0 ); + + //impl + QString title() const; + + //impl + QString identifier() const; + + +private: + void changed( const KABC::Addressee& ); + +private slots: + + void deleteSelectedDistributionList(); + void editSelectedDistributionList(); + + void contextMenuRequested( QListBoxItem *item, const QPoint &point ); + void updateEntries(); + void itemSelected( int index ); + void contactsDropped( const QString &listName, const KABC::Addressee::List &addressees ); + +private: + ListBox *mListBox; + QStringList mCurrentEntries; + QPushButton *mAddButton; + QPushButton *mEditButton; + QPushButton *mRemoveButton; +}; + +} // namespace DistributionListNg +} // namespace KAB + +#endif // KAB_DISTRIBUTIONLISTNG_MAINWIDGET_H diff --git a/kaddressbook/features/distributionlistwidget.cpp b/kaddressbook/features/distributionlistwidget.cpp new file mode 100644 index 000000000..9c322d6f6 --- /dev/null +++ b/kaddressbook/features/distributionlistwidget.cpp @@ -0,0 +1,673 @@ +/* + This file is part of KAddressBook. + Copyright (c) 2002 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 "distributionlistwidget.h" + +#include <qbuttongroup.h> +#include <qcombobox.h> +#include <qlabel.h> +#include <qlayout.h> +#include <qlistview.h> +#include <qpushbutton.h> +#include <qradiobutton.h> + +#include <kaccelmanager.h> +#include <kconfig.h> +#include <kdebug.h> +#include <kglobal.h> +#include <kinputdialog.h> +#include <klocale.h> +#include <kmessagebox.h> + +#include <kabc/addresseedialog.h> +#ifdef KDEPIM_NEW_DISTRLISTS +#include <libkdepim/distributionlist.h> +typedef KPIM::DistributionList DistributionList; +#else +#include <kabc/distributionlist.h> +typedef KABC::DistributionList DistributionList; +#endif +#include <kabc/stdaddressbook.h> +#include <kabc/vcardconverter.h> +#include <libkdepim/kvcarddrag.h> + +#include "core.h" + +class DistributionListFactory : public KAB::ExtensionFactory +{ + public: + KAB::ExtensionWidget *extension( KAB::Core *core, QWidget *parent, const char *name ) + { + return new DistributionListWidget( core, parent, name ); + } + + QString identifier() const + { + return "distribution_list_editor"; + } +}; + +extern "C" { + void *init_libkaddrbk_distributionlist() + { + return ( new DistributionListFactory ); + } +} + +/** + We have to catch when the 'Del' key is pressed, otherwise + the event is forwarded to the ViewManager and it tries to + remove a contact instead of the distribution list. + */ +class DeletePressedCatcher : public QObject +{ + public: + DeletePressedCatcher( DistributionListWidget *parent ) + : QObject( parent, "DeletePressedCatcher" ), mWidget( parent ) + { + } + + protected: + bool eventFilter( QObject*, QEvent *event ) + { + if ( event->type() == QEvent::AccelOverride ) { + QKeyEvent *keyEvent = (QKeyEvent*)event; + if ( keyEvent->key() == Qt::Key_Delete ) { + keyEvent->accept(); + mWidget->removeContact(); + return true; + } else + return false; + } else { + return false; + } + } + + private: + DistributionListWidget *mWidget; +}; + +class ContactItem : public QListViewItem +{ + public: + ContactItem( DistributionListView *parent, const KABC::Addressee &addressee, + const QString &email = QString::null ) : + QListViewItem( parent ), + mAddressee( addressee ), + mEmail( email ) + { + setText( 0, addressee.realName() ); + if ( email.isEmpty() ) { + setText( 1, addressee.preferredEmail() ); + setText( 2, i18n( "Yes" ) ); + } else { + setText( 1, email ); + setText( 2, i18n( "No" ) ); + } + } + + KABC::Addressee addressee() const + { + return mAddressee; + } + + QString email() const + { + return mEmail; + } + + protected: + bool acceptDrop( const QMimeSource* ) + { + return true; + } + + private: + KABC::Addressee mAddressee; + QString mEmail; +}; + +DistributionListWidget::DistributionListWidget( KAB::Core *core, QWidget *parent, + const char *name ) + : KAB::ExtensionWidget( core, parent, name ) +#ifndef KDEPIM_NEW_DISTRLISTS + , mManager( 0 ) +#endif +{ + QGridLayout *topLayout = new QGridLayout( this, 3, 4, KDialog::marginHint(), + KDialog::spacingHint() ); + + mNameCombo = new QComboBox( this ); + topLayout->addWidget( mNameCombo, 0, 0 ); + connect( mNameCombo, SIGNAL( activated( int ) ), SLOT( updateContactView() ) ); + + mCreateListButton = new QPushButton( i18n( "New List..." ), this ); + topLayout->addWidget( mCreateListButton, 0, 1 ); + connect( mCreateListButton, SIGNAL( clicked() ), SLOT( createList() ) ); + + mEditListButton = new QPushButton( i18n( "Rename List..." ), this ); + topLayout->addWidget( mEditListButton, 0, 2 ); + connect( mEditListButton, SIGNAL( clicked() ), SLOT( editList() ) ); + + mRemoveListButton = new QPushButton( i18n( "Remove List" ), this ); + topLayout->addWidget( mRemoveListButton, 0, 3 ); + connect( mRemoveListButton, SIGNAL( clicked() ), SLOT( removeList() ) ); + + mContactView = new DistributionListView( this ); + mContactView->addColumn( i18n( "Name" ) ); + mContactView->addColumn( i18n( "Email" ) ); + mContactView->addColumn( i18n( "Use Preferred" ) ); + mContactView->setEnabled( false ); + mContactView->setAllColumnsShowFocus( true ); + mContactView->setFullWidth( true ); + topLayout->addMultiCellWidget( mContactView, 1, 1, 0, 3 ); + connect( mContactView, SIGNAL( selectionChanged() ), + SLOT( selectionContactViewChanged() ) ); + connect( mContactView, SIGNAL( dropped( QDropEvent*, QListViewItem* ) ), + SLOT( dropped( QDropEvent*, QListViewItem* ) ) ); + + mAddContactButton = new QPushButton( i18n( "Add Contact" ), this ); + mAddContactButton->setEnabled( false ); + topLayout->addWidget( mAddContactButton, 2, 0 ); + connect( mAddContactButton, SIGNAL( clicked() ), SLOT( addContact() ) ); + + mEntryCountLabel = new QLabel( this ); + topLayout->addWidget( mEntryCountLabel, 2, 1 ); + + mChangeEmailButton = new QPushButton( i18n( "Change Email..." ), this ); + topLayout->addWidget( mChangeEmailButton, 2, 2 ); + connect( mChangeEmailButton, SIGNAL( clicked() ), SLOT( changeEmail() ) ); + + mRemoveContactButton = new QPushButton( i18n( "Remove Contact" ), this ); + topLayout->addWidget( mRemoveContactButton, 2, 3 ); + connect( mRemoveContactButton, SIGNAL( clicked() ), SLOT( removeContact() ) ); + +#ifdef KDEPIM_NEW_DISTRLISTS + // When contacts are changed, update both distr list combo and contents of displayed distr list + connect( core, SIGNAL( contactsUpdated() ), + this, SLOT( updateNameCombo() ) ); +#else + mManager = new KABC::DistributionListManager( core->addressBook() ); + + connect( KABC::DistributionListWatcher::self(), SIGNAL( changed() ), + this, SLOT( updateNameCombo() ) ); +#endif + + connect( core->addressBook(), SIGNAL( addressBookChanged( AddressBook* ) ), + this, SLOT( updateNameCombo() ) ); + + updateNameCombo(); + + QObject *catcher = new DeletePressedCatcher( this ); + installEventFilter( catcher ); + mContactView->installEventFilter( catcher ); + + mContactView->restoreLayout( KGlobal::config(), "DistributionListViewColumns" ); + + KAcceleratorManager::manage( this ); +} + +DistributionListWidget::~DistributionListWidget() +{ +#ifndef KDEPIM_NEW_DISTRLISTS + delete mManager; +#endif + + mContactView->saveLayout( KGlobal::config(), "DistributionListViewColumns" ); +} + +void DistributionListWidget::save() +{ +#ifndef KDEPIM_NEW_DISTRLISTS + mManager->save(); +#endif +} + +void DistributionListWidget::selectionContactViewChanged() +{ + ContactItem *contactItem = + static_cast<ContactItem *>( mContactView->selectedItem() ); + bool state = contactItem; + + mChangeEmailButton->setEnabled( state ); + mRemoveContactButton->setEnabled( state ); +} + +bool DistributionListWidget::alreadyExists( const QString& distrListName ) const +{ +#ifdef KDEPIM_NEW_DISTRLISTS + return core()->distributionListNames().contains( distrListName ); +#else + return mManager->listNames().contains( distrListName ); +#endif +} + +void DistributionListWidget::createList() +{ + QString newName = KInputDialog::getText( i18n( "New Distribution List" ), + i18n( "Please enter name:" ), + QString::null, 0, this ); + + if ( newName.isEmpty() ) return; + + if ( alreadyExists( newName ) ) { + KMessageBox::sorry( this, i18n( "The name already exists" ) ); + return; + } +#ifdef KDEPIM_NEW_DISTRLISTS + KABC::Resource* resource = core()->requestResource( this ); + if ( !resource ) + return; + + KPIM::DistributionList dist; + dist.setResource( resource ); + dist.setName( newName ); + // Creates undo-redo command, calls setModified, also triggers contactsUpdated, + // which triggers updateNameCombo, so the new name appears + changed( dist ); + core()->addressBook()->insertAddressee( dist ); + +#else + new KABC::DistributionList( mManager, newName ); + changed(); + + updateNameCombo(); +#endif + + // Select the new one in the list + mNameCombo->setCurrentText( newName ); + // Display the contents of the list we just selected (well, it's empty) + updateContactView(); +} + +void DistributionListWidget::editList() +{ + const QString oldName = mNameCombo->currentText(); + + const QString newName = KInputDialog::getText( i18n( "Rename Distribution List" ), + i18n( "Please enter name:" ), + oldName, 0, this ); + + if ( newName.isEmpty() ) return; + + if ( alreadyExists( newName ) ) { + KMessageBox::sorry( this, i18n( "The name already exists." ) ); + return; + } +#ifdef KDEPIM_NEW_DISTRLISTS + KPIM::DistributionList dist = KPIM::DistributionList::findByName( + core()->addressBook(), mNameCombo->currentText() ); + if ( dist.isEmpty() ) // not found [should be impossible] + return; + + dist.setFormattedName( newName ); + core()->addressBook()->insertAddressee( dist ); + + changed( dist ); +#else + KABC::DistributionList *list = mManager->list( oldName ); + list->setName( newName ); + mManager->save(); + updateNameCombo(); +#endif + + // Select the new name in the list (updateNameCombo couldn't know we wanted that one) + mNameCombo->setCurrentText( newName ); + // Display the contents of the list we just selected + updateContactView(); + +#ifndef KDEPIM_NEW_DISTRLISTS + changed(); +#endif +} + +void DistributionListWidget::removeList() +{ + int result = KMessageBox::warningContinueCancel( this, + i18n( "<qt>Delete distribution list <b>%1</b>?</qt>" ) .arg( mNameCombo->currentText() ), + QString::null, KGuiItem( i18n("Delete"), "editdelete") ); + + if ( result != KMessageBox::Continue ) + return; + +#ifdef KDEPIM_NEW_DISTRLISTS + KPIM::DistributionList dist = KPIM::DistributionList::findByName( + core()->addressBook(), mNameCombo->currentText() ); + if ( dist.isEmpty() ) // not found [should be impossible] + return; + + emit deleted( dist.uid() ); + core()->addressBook()->removeAddressee( dist ); +#else + mManager->remove( mManager->list( mNameCombo->currentText() ) ); + mNameCombo->removeItem( mNameCombo->currentItem() ); + + updateContactView(); + + changed(); +#endif +} + +void DistributionListWidget::addContact() +{ +#ifdef KDEPIM_NEW_DISTRLISTS + KPIM::DistributionList dist = KPIM::DistributionList::findByName( + core()->addressBook(), mNameCombo->currentText() ); + if ( dist.isEmpty() ) { // not found + kdDebug(5720) << k_funcinfo << mNameCombo->currentText() << " not found" << endl; + return; + } +#else + KABC::DistributionList *list = mManager->list( mNameCombo->currentText() ); + if ( !list ) + return; + KABC::DistributionList& dist = *list; +#endif + + const KABC::Addressee::List addrList = selectedContacts(); + KABC::Addressee::List::ConstIterator it; + for ( it = addrList.begin(); it != addrList.end(); ++it ) + dist.insertEntry( *it ); + +#ifdef KDEPIM_NEW_DISTRLISTS + core()->addressBook()->insertAddressee( dist ); + changed( dist ); +#else + updateContactView(); + changed(); +#endif +} + +void DistributionListWidget::removeContact() +{ +#ifdef KDEPIM_NEW_DISTRLISTS + KPIM::DistributionList dist = KPIM::DistributionList::findByName( + core()->addressBook(), mNameCombo->currentText() ); + if ( dist.isEmpty() ) // not found + return; +#else + KABC::DistributionList *list = mManager->list( mNameCombo->currentText() ); + if ( !list ) + return; + KABC::DistributionList& dist = *list; +#endif + + ContactItem *contactItem = + static_cast<ContactItem *>( mContactView->selectedItem() ); + if ( !contactItem ) + return; + + dist.removeEntry( contactItem->addressee(), contactItem->email() ); + delete contactItem; + +#ifdef KDEPIM_NEW_DISTRLISTS + core()->addressBook()->insertAddressee( dist ); + changed( dist ); +#else + changed(); +#endif +} + +void DistributionListWidget::changeEmail() +{ +#ifdef KDEPIM_NEW_DISTRLISTS + KPIM::DistributionList dist = KPIM::DistributionList::findByName( + core()->addressBook(), mNameCombo->currentText() ); + if ( dist.isEmpty() ) // not found + return; +#else + KABC::DistributionList *list = mManager->list( mNameCombo->currentText() ); + if ( !list ) + return; + KABC::DistributionList& dist = *list; +#endif + + ContactItem *contactItem = + static_cast<ContactItem *>( mContactView->selectedItem() ); + if ( !contactItem ) + return; + + bool canceled = false; + const QString email = EmailSelector::getEmail( contactItem->addressee().emails(), + contactItem->email(), this, canceled); + if( canceled) + return; + dist.removeEntry( contactItem->addressee(), contactItem->email() ); + dist.insertEntry( contactItem->addressee(), email ); + +#ifdef KDEPIM_NEW_DISTRLISTS + core()->addressBook()->insertAddressee( dist ); + changed( dist ); +#else + updateContactView(); + changed(); +#endif +} + +void DistributionListWidget::updateContactView() +{ + mContactView->clear(); + + bool isListSelected = false; +#ifdef KDEPIM_NEW_DISTRLISTS + KPIM::DistributionList dist; + if ( mNameCombo->count() != 0 ) + dist = KPIM::DistributionList::findByName( + core()->addressBook(), mNameCombo->currentText() ); + isListSelected = !dist.isEmpty(); +#else + KABC::DistributionList *list = mManager->list( mNameCombo->currentText() ); + isListSelected = list != 0; +#endif + if ( !isListSelected ) { + mEditListButton->setEnabled( false ); + mRemoveListButton->setEnabled( false ); + mChangeEmailButton->setEnabled( false ); + mRemoveContactButton->setEnabled( false ); + mContactView->setEnabled( false ); + return; + } + mEditListButton->setEnabled( true ); + mRemoveListButton->setEnabled( true ); + mContactView->setEnabled( true ); + + uint entryCount = 0; +#ifdef KDEPIM_NEW_DISTRLISTS + const KPIM::DistributionList::Entry::List entries = dist.entries( core()->addressBook() ); + KPIM::DistributionList::Entry::List::ConstIterator it; +#else + const KABC::DistributionList::Entry::List entries = list->entries(); + KABC::DistributionList::Entry::List::ConstIterator it; +#endif + for ( it = entries.begin(); it != entries.end(); ++it, ++entryCount ) + new ContactItem( mContactView, (*it).addressee, (*it).email ); + + bool state = mContactView->selectedItem() != 0; + mChangeEmailButton->setEnabled( state ); + mRemoveContactButton->setEnabled( state ); + + mEntryCountLabel->setText( i18n( "Count: %n contact", "Count: %n contacts", entryCount ) ); +} + +void DistributionListWidget::updateNameCombo() +{ + int pos = mNameCombo->currentItem(); + mNameCombo->clear(); +#ifdef KDEPIM_NEW_DISTRLISTS + const QStringList names = core()->distributionListNames(); +#else + mManager->load(); + const QStringList names = mManager->listNames(); +#endif + mNameCombo->insertStringList( names ); + mNameCombo->setCurrentItem( QMIN( pos, (int)names.count() - 1 ) ); + + updateContactView(); +} + +void DistributionListWidget::dropEvent( QDropEvent *e ) +{ + if ( mNameCombo->count() == 0 ) + return; + +#ifdef KDEPIM_NEW_DISTRLISTS + KPIM::DistributionList dist = KPIM::DistributionList::findByName( + core()->addressBook(), mNameCombo->currentText() ); + if ( dist.isEmpty() ) + return; +#else + KABC::DistributionList *list = mManager->list( mNameCombo->currentText() ); + if ( !list ) + return; + KABC::DistributionList& dist = *list; +#endif + + QString vcards; + if ( KVCardDrag::decode( e, vcards ) ) { + KABC::VCardConverter converter; + const KABC::Addressee::List lst = converter.parseVCards( vcards ); + for ( KABC::Addressee::List::ConstIterator it = lst.begin(); it != lst.end(); ++it ) + dist.insertEntry( *it ); + +#ifdef KDEPIM_NEW_DISTRLISTS + core()->addressBook()->insertAddressee( dist ); + changed( dist ); +#else + changed(); + updateContactView(); +#endif + } +} + +void DistributionListWidget::contactsSelectionChanged() +{ + mAddContactButton->setEnabled( contactsSelected() && mNameCombo->count() > 0 ); +} + +QString DistributionListWidget::title() const +{ + return i18n( "Distribution List Editor" ); +} + +QString DistributionListWidget::identifier() const +{ + return "distribution_list_editor"; +} + +void DistributionListWidget::dropped( QDropEvent *e, QListViewItem* ) +{ + dropEvent( e ); +} + +#ifdef KDEPIM_NEW_DISTRLISTS +void DistributionListWidget::changed( const KABC::Addressee& dist ) +{ + emit modified( KABC::Addressee::List() << dist ); +} +#else +void DistributionListWidget::changed() +{ + save(); +} +#endif + +DistributionListView::DistributionListView( QWidget *parent, const char* name ) + : KListView( parent, name ) +{ + setDragEnabled( true ); + setAcceptDrops( true ); + setAllColumnsShowFocus( true ); +} + +void DistributionListView::dragEnterEvent( QDragEnterEvent* e ) +{ + bool canDecode = QTextDrag::canDecode( e ); + e->accept( canDecode ); +} + +void DistributionListView::viewportDragMoveEvent( QDragMoveEvent *e ) +{ + bool canDecode = QTextDrag::canDecode( e ); + e->accept( canDecode ); +} + +void DistributionListView::viewportDropEvent( QDropEvent *e ) +{ + emit dropped( e, 0 ); +} + +void DistributionListView::dropEvent( QDropEvent *e ) +{ + emit dropped( e, 0 ); +} + + +EmailSelector::EmailSelector( const QStringList &emails, + const QString ¤t, QWidget *parent ) + : KDialogBase( KDialogBase::Plain, i18n("Select Email Address"), Ok|Cancel, Ok, + parent ) +{ + QFrame *topFrame = plainPage(); + QBoxLayout *topLayout = new QVBoxLayout( topFrame ); + + mButtonGroup = new QButtonGroup( 1, Horizontal, i18n("Email Addresses"), + topFrame ); + mButtonGroup->setRadioButtonExclusive( true ); + topLayout->addWidget( mButtonGroup ); + + QRadioButton *button = new QRadioButton( i18n("Preferred address"), mButtonGroup ); + button->setDown( true ); + mEmailMap.insert( mButtonGroup->id( button ), "" ); + + QStringList::ConstIterator it; + for ( it = emails.begin(); it != emails.end(); ++it ) { + button = new QRadioButton( *it, mButtonGroup ); + mEmailMap.insert( mButtonGroup->id( button ), *it ); + if ( (*it) == current ) + button->setDown( true ); + } +} + +QString EmailSelector::selected() const +{ + QButton *button = mButtonGroup->selected(); + if ( button ) + return mEmailMap[ mButtonGroup->id( button ) ]; + + return QString::null; +} + +QString EmailSelector::getEmail( const QStringList &emails, + const QString ¤t, QWidget *parent, bool &canceled ) +{ + EmailSelector dlg( emails, current, parent ); + if(dlg.exec()) + { + canceled = false; + return dlg.selected(); + } + canceled = true; + return QString(); +} + + +#include "distributionlistwidget.moc" diff --git a/kaddressbook/features/distributionlistwidget.h b/kaddressbook/features/distributionlistwidget.h new file mode 100644 index 000000000..d52a06ab0 --- /dev/null +++ b/kaddressbook/features/distributionlistwidget.h @@ -0,0 +1,140 @@ +/* + This file is part of KAddressBook. + Copyright (c) 2002 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 DISTRIBUTIONLISTWIDGET_H +#define DISTRIBUTIONLISTWIDGET_H + +#include <config.h> // for KDEPIM_NEW_DISTRLISTS +#include <kdialogbase.h> +#include <klistview.h> + +#include "extensionwidget.h" + +class QButtonGroup; +class QComboBox; +class QListView; + +class DistributionListView; + +namespace KAB { +class Core; +} + +namespace KABC { +class AddressBook; +class DistributionListManager; +} + +class DistributionListWidget : public KAB::ExtensionWidget +{ + Q_OBJECT + + public: + DistributionListWidget( KAB::Core*, QWidget *parent, const char *name = 0 ); + virtual ~DistributionListWidget(); + + void contactsSelectionChanged(); + + QString title() const; + QString identifier() const; + + public slots: + void save(); + void dropped( QDropEvent*, QListViewItem* ); + + void removeContact(); + + private slots: + void createList(); + void editList(); + void removeList(); + void addContact(); + void changeEmail(); + void updateNameCombo(); + void updateContactView(); + void selectionContactViewChanged(); + + private: +#ifdef KDEPIM_NEW_DISTRLISTS + void changed( const KABC::Addressee& dist ); +#else + void changed(); +#endif + bool alreadyExists( const QString& distrListName ) const; + + protected: + void dropEvent( QDropEvent* ); + + private: + QComboBox *mNameCombo; + QLabel *mEntryCountLabel; + DistributionListView *mContactView; + +#ifndef KDEPIM_NEW_DISTRLISTS + KABC::DistributionListManager *mManager; +#endif + QPushButton *mCreateListButton; + QPushButton *mEditListButton; + QPushButton *mRemoveListButton; + QPushButton *mChangeEmailButton; + QPushButton *mAddContactButton; + QPushButton *mRemoveContactButton; +}; + +/** + @short Helper class +*/ +class DistributionListView : public KListView +{ + Q_OBJECT + + public: + DistributionListView( QWidget *parent, const char* name = 0 ); + + protected: + void dragEnterEvent( QDragEnterEvent *e ); + void dropEvent( QDropEvent *e ); + void viewportDragMoveEvent( QDragMoveEvent *e ); + void viewportDropEvent( QDropEvent *e ); +}; + +/** + @short Helper class +*/ +class EmailSelector : public KDialogBase +{ + public: + EmailSelector( const QStringList &emails, const QString ¤t, + QWidget *parent ); + + QString selected() const; + + static QString getEmail( const QStringList &emails, const QString ¤t, + QWidget *parent, bool &canceled ); + + private: + QButtonGroup *mButtonGroup; + QMap<int, QString> mEmailMap; +}; + +#endif diff --git a/kaddressbook/features/resourceselection.cpp b/kaddressbook/features/resourceselection.cpp new file mode 100644 index 000000000..c7e89dbf5 --- /dev/null +++ b/kaddressbook/features/resourceselection.cpp @@ -0,0 +1,421 @@ +/* + This file is part of KAddressBook. + Copyright (c) 2004 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 <qlayout.h> +#include <qpushbutton.h> +#include <qtimer.h> +#include <qlabel.h> +#include <qheader.h> +#include <qtooltip.h> + +#include <kabc/resource.h> +#include <kdialog.h> +#include <kglobal.h> +#include <kiconloader.h> +#include <kinputdialog.h> +#include <klocale.h> +#include <kmessagebox.h> +#include <kresources/configdialog.h> + +#include "core.h" + +#include "resourceselection.h" +#include <libkdepim/resourceabc.h> + +class AddressBookWrapper : public KABC::AddressBook +{ + public: + AddressBookWrapper( KABC::AddressBook* ); + + KRES::Manager<KABC::Resource>* getResourceManager() + { + return resourceManager(); + } +}; + +class ResourceItem : public QCheckListItem +{ + public: + ResourceItem( KListView *parent, KABC::Resource *resource ) + : QCheckListItem( parent, resource->resourceName(), CheckBox ), + mResource( resource ), mChecked( false ), + mIsSubresource( false ), mSubItemsCreated( false ), + mResourceIdentifier() + { + setOn( resource->isActive() ); + setPixmap( 0, KGlobal::iconLoader()->loadIcon( "contents", KIcon::Small ) ); + mChecked = isOn(); + } + + ResourceItem( KPIM::ResourceABC *resourceABC, ResourceItem* parent, + const QString& resourceIdent ) + : QCheckListItem( parent, resourceABC->subresourceLabel( resourceIdent ), CheckBox ), + mResource( resourceABC ), mChecked( false ), + mIsSubresource( true ), mSubItemsCreated( false ), + mResourceIdentifier( resourceIdent ) + { + KPIM::ResourceABC* res = dynamic_cast<KPIM::ResourceABC *>( mResource ); + setOn( res->subresourceActive( mResourceIdentifier ) ); + setPixmap( 0, KGlobal::iconLoader()->loadIcon( "contents", KIcon::Small ) ); + mChecked = isOn(); + } + + void createSubresourceItems(); + + void setChecked( bool state ) { mChecked = state; } + bool checked() const { return mChecked; } + KABC::Resource *resource() const { return mResource; } + QString resourceIdentifier() const { return mResourceIdentifier; } + bool isSubResource() const { return mIsSubresource; } + + virtual void stateChange( bool active ); + + private: + KABC::Resource * const mResource; + bool mChecked; + const bool mIsSubresource; + bool mSubItemsCreated; + const QString mResourceIdentifier; +}; + +// Comes from korganizer/resourceview.cpp +void ResourceItem::createSubresourceItems() +{ + KPIM::ResourceABC* res = dynamic_cast<KPIM::ResourceABC *>( mResource ); + QStringList subresources; + if ( res ) + subresources = res->subresources(); + if ( !subresources.isEmpty() ) { + setOpen( true ); + setExpandable( true ); + // This resource has subresources + QStringList::ConstIterator it; + for ( it = subresources.begin(); it != subresources.end(); ++it ) { + (void)new ResourceItem( res, this, *it ); + } + } + mSubItemsCreated = true; +} + +// TODO: connect this to some signalResourceModified +// void ResourceItem::setGuiState() +// { +// if ( mIsSubresource ) +// setOn( mResource->subresourceActive( mResourceIdentifier ) ); +// else +// setOn( mResource->isActive() ); +// } + +void ResourceItem::stateChange( bool active ) +{ + //kdDebug(5720) << k_funcinfo << this << " " << text( 0 ) << " active=" << active << endl; + if ( active && !mIsSubresource ) { + if ( !mSubItemsCreated ) + createSubresourceItems(); + } + + setOpen( active && childCount() > 0 ); +} + +//// + +ResourceSelection::ResourceSelection( KAB::Core *core, QWidget *parent, const char *name ) + : KAB::ExtensionWidget( core, parent, name ), mManager( 0 ) +{ + initGUI(); + + AddressBookWrapper *wrapper = static_cast<AddressBookWrapper*>( core->addressBook() ); + mManager = wrapper->getResourceManager(); + + connect( mAddButton, SIGNAL( clicked() ), SLOT( add() ) ); + connect( mEditButton, SIGNAL( clicked() ), SLOT( edit() ) ); + connect( mRemoveButton, SIGNAL( clicked() ), SLOT( remove() ) ); + + connect( mListView, SIGNAL( clicked( QListViewItem* ) ), + SLOT( currentChanged( QListViewItem* ) ) ); + + QTimer::singleShot( 0, this, SLOT( updateView() ) ); +} + +ResourceSelection::~ResourceSelection() +{ +} + +QString ResourceSelection::title() const +{ + return i18n( "Address Books" ); +} + +QString ResourceSelection::identifier() const +{ + return "resourceselection"; +} + +void ResourceSelection::add() +{ + QStringList types = mManager->resourceTypeNames(); + QStringList descs = mManager->resourceTypeDescriptions(); + + bool ok = false; + QString desc = KInputDialog::getItem( i18n( "Add Address Book" ), + i18n( "Please select type of the new address book:" ), + descs, 0, false, &ok, this ); + if ( !ok ) + return; + + QString type = types[ descs.findIndex( desc ) ]; + + // Create new resource + KABC::Resource *resource = mManager->createResource( type ); + if ( !resource ) { + KMessageBox::error( this, i18n("<qt>Unable to create an address book of type <b>%1</b>.</qt>") + .arg( type ) ); + return; + } + + resource->setResourceName( i18n( "%1 address book" ).arg( type ) ); + resource->setAddressBook(core()->addressBook()); + + KRES::ConfigDialog dlg( this, QString( "contact" ), resource ); + + if ( dlg.exec() ) { + core()->addressBook()->addResource( resource ); + resource->asyncLoad(); + + mLastResource = resource->identifier(); + updateView(); + } else { + delete resource; + resource = 0; + } +} + +void ResourceSelection::edit() +{ + ResourceItem *item = selectedItem(); + if ( !item ) + return; + + KRES::ConfigDialog dlg( this, QString( "contact" ), item->resource() ); + + if ( dlg.exec() ) { + mManager->change( item->resource() ); + item->resource()->asyncLoad(); + + mLastResource = item->resource()->identifier(); + updateView(); + } +} + +void ResourceSelection::remove() +{ + ResourceItem *item = selectedItem(); + if ( !item ) + return; + + int result = KMessageBox::warningContinueCancel( this, + i18n( "<qt>Do you really want to remove the address book <b>%1</b>?</qt>" ) + .arg( item->resource()->resourceName() ), "", + KGuiItem( i18n( "&Remove" ), "editdelete" ) ); + if ( result == KMessageBox::Cancel ) + return; + + mLastResource = item->resource()->identifier(); + + core()->addressBook()->removeResource( item->resource() ); + core()->addressBook()->emitAddressBookChanged(); + + updateView(); +} + +void ResourceSelection::currentChanged( QListViewItem *item ) +{ + ResourceItem *resItem = static_cast<ResourceItem*>( item ); + bool state = (resItem && !resItem->isSubResource() ); + + mEditButton->setEnabled( state ); + mRemoveButton->setEnabled( state ); + + if ( !resItem ) + return; + + KABC::Resource *resource = resItem->resource(); + + if ( resItem->checked() != resItem->isOn() ) { + resItem->setChecked( resItem->isOn() ); + if ( resItem->isSubResource() ) { + KPIM::ResourceABC *res = dynamic_cast<KPIM::ResourceABC *>( resource ); + res->setSubresourceActive( resItem->resourceIdentifier(), resItem->isOn() ); + mManager->change( resource ); + } else { + resource->setActive( resItem->isOn() ); + mManager->change( resource ); + + if ( resItem->checked() ) { + if ( !resource->addressBook() ) + resource->setAddressBook( core()->addressBook() ); + + if ( !resource->isOpen() ) + resource->open(); + + resource->asyncLoad(); + } else { + resource->close(); + } + } + + mLastResource = resource->identifier(); + core()->addressBook()->emitAddressBookChanged(); + //updateView(); + } +} + +void ResourceSelection::updateView() +{ + if ( !mManager ) + return; + + mListView->clear(); + + KRES::Manager<KABC::Resource>::Iterator it; + for ( it = mManager->begin(); it != mManager->end(); ++it ) { + + new ResourceItem( mListView, *it ); + KPIM::ResourceABC* resource = dynamic_cast<KPIM::ResourceABC *>( *it ); + if ( resource ) { + disconnect( resource, 0, this, 0 ); + connect( resource, SIGNAL( signalSubresourceAdded( KPIM::ResourceABC *, + const QString &, const QString & ) ), + SLOT( slotSubresourceAdded( KPIM::ResourceABC *, + const QString &, const QString & ) ) ); + + connect( resource, SIGNAL( signalSubresourceRemoved( KPIM::ResourceABC *, + const QString &, const QString & ) ), + SLOT( slotSubresourceRemoved( KPIM::ResourceABC *, + const QString &, const QString & ) ) ); + //connect( resource, SIGNAL( resourceSaved( KPIM::ResourceABC * ) ), + // SLOT( closeResource( KPIM::ResourceABC * ) ) ); + } + } + + QListViewItemIterator itemIt( mListView ); + while ( itemIt.current() ) { + ResourceItem *item = static_cast<ResourceItem*>( itemIt.current() ); + if ( item->resource()->identifier() == mLastResource ) { + mListView->setSelected( item, true ); + mListView->ensureItemVisible( item ); + break; + } + ++itemIt; + } + + core()->addressBook()->emitAddressBookChanged(); +} + + +// Add a new entry +void ResourceSelection::slotSubresourceAdded( KPIM::ResourceABC *resource, + const QString& /*type*/, + const QString& subResource ) +{ + kdDebug(5720) << k_funcinfo << resource->resourceName() << " " << subResource << endl; + QListViewItem *i = mListView->findItem( resource->resourceName(), 0 ); + if ( !i ) + // Not found + return; + + ResourceItem *item = static_cast<ResourceItem *>( i ); + (void)new ResourceItem( resource, item, subResource ); +} + +// Remove an entry +void ResourceSelection::slotSubresourceRemoved( KPIM::ResourceABC* resource, + const QString& /*type*/, + const QString& subResource ) +{ + core()->addressBook()->emitAddressBookChanged(); + updateView(); +} + +ResourceItem* ResourceSelection::selectedItem() const +{ + return static_cast<ResourceItem*>( mListView->selectedItem() ); +} + +void ResourceSelection::initGUI() +{ + QBoxLayout *topLayout = new QVBoxLayout( this ); + topLayout->setSpacing( KDialog::spacingHint() ); + + QBoxLayout *buttonLayout = new QHBoxLayout(); + buttonLayout->setSpacing( KDialog::spacingHint() ); + topLayout->addLayout( buttonLayout ); + + QLabel *abLabel = new QLabel( i18n( "Address Books" ), this ); + buttonLayout->addWidget( abLabel ); + buttonLayout->addStretch( 1 ); + + mAddButton = new QPushButton( this ); + mAddButton->setIconSet( SmallIconSet( "add" ) ); + QToolTip::add( mAddButton, i18n( "Add addressbook" ) ); + buttonLayout->addWidget( mAddButton ); + mEditButton = new QPushButton( this ); + mEditButton->setIconSet( SmallIconSet( "edit" ) ); + mEditButton->setEnabled( false ); + QToolTip::add( mEditButton, i18n( "Edit addressbook settings" ) ); + buttonLayout->addWidget( mEditButton ); + mRemoveButton = new QPushButton( this ); + mRemoveButton->setIconSet( SmallIconSet( "remove" ) ); + mRemoveButton->setEnabled( false ); + QToolTip::add( mRemoveButton, i18n( "Remove addressbook" ) ); + buttonLayout->addWidget( mRemoveButton ); + + mListView = new KListView( this ); + mListView->header()->hide(); + mListView->addColumn( i18n( "Address Books" ) ); + mListView->setFullWidth( true ); + topLayout->addWidget( mListView ); +} + +class ResourceSelectionFactory : public KAB::ExtensionFactory +{ + public: + KAB::ExtensionWidget *extension( KAB::Core *core, QWidget *parent, const char *name ) + { + return new ResourceSelection( core, parent, name ); + } + + QString identifier() const + { + return "resourceselection"; + } +}; + +extern "C" { + void *init_libkaddrbk_resourceselection() + { + return ( new ResourceSelectionFactory ); + } +} + +#include "resourceselection.moc" diff --git a/kaddressbook/features/resourceselection.desktop b/kaddressbook/features/resourceselection.desktop new file mode 100644 index 000000000..4879e939f --- /dev/null +++ b/kaddressbook/features/resourceselection.desktop @@ -0,0 +1,110 @@ +[Desktop Entry] +X-KDE-Library=libkaddrbk_resourceselection +Name=Address Book Management Plugin +Name[af]=Adres boek bestuur inprop module +Name[be]=Дапаўненне "Кіраванне адраснамі кнігамі" +Name[bg]=Приставка за управление на адресника +Name[br]=Lugent melestradur ar c'harnedoù chomlec'hioù +Name[bs]=Dodatak za rukovanje adresarom +Name[ca]=Endollable de gestió de llibretes d'adreces +Name[cs]=Modul pro správu knih adres +Name[da]=Plugin for adressebogshåndtering +Name[de]=Adressbuchverwaltungs-Modul +Name[el]=Πρόσθετο διαχείρισης βιβλίου διευθύνσεων +Name[eo]=Adresar-administra kromaĵo +Name[es]=Extensión para gestionar la libreta de direcciones +Name[et]=Aadressihalduri plugin +Name[eu]=Helbide-liburu kudeaketa plugin-a +Name[fa]=وصلۀ مدیریت کتاب نشانی +Name[fi]=Osoitekirjan ylläpidon laajennus +Name[fr]=Module de gestion de carnet d'adresses +Name[fy]=Plugin foar adresboekbehear +Name[ga]=Breiseán Bhainisteoireacht Leabhar na Seoltaí +Name[gl]=Extensión para xestión do Caderno de Enderezos +Name[he]=תוסף מנהל הכתובות +Name[hu]=Címjegyzékkezelő bővítőmodul +Name[is]=Umsjónaríforrit vistfangaflettis +Name[it]=Plugin per gestire rubriche indirizzi +Name[ja]=アドレス帳管理プラグイン +Name[ka]=წიგნაკის მართვის მოდული +Name[kk]=Адрестік кітапшамен айналысу плагин модулі +Name[km]=កម្មវិធីជំនួយការគ្រប់គ្រងសៀវភៅអាសយដ្ឋាន +Name[lt]=Adresų knygelės tvarkymo priedas +Name[mk]=Приклучок за менаџирање адресари +Name[ms]=Plugin Pengurusan Buku Alamat +Name[nb]=Programtillegg for adressebok behandling +Name[nds]=Adressbookpleeg-Moduul +Name[ne]=ठेगाना पुस्तिका व्यवस्थापन प्लगइन +Name[nl]=Plugin voor adresboekbeheer +Name[nn]=Programtillegg for adressebokhandtering +Name[pl]=Wtyczka zarządzania Książką adresową +Name[pt]='Plugin' de Gestão do Livro de Endereços +Name[pt_BR]=Plug-in de Gerenciamento do Livro de Endereços +Name[ru]=Управление адресной книгой +Name[se]=Lassemoduvla mii gieđáhalla čujuhusgirjjiid +Name[sk]=Modul pre správu adresára +Name[sl]=Vstavek Upravitelj adresarjev +Name[sr]=Прикључак управљања адресаром +Name[sr@Latn]=Priključak upravljanja adresarom +Name[sv]=Insticksprogram för adressbokshantering +Name[ta]=முகவரி புத்தகம் மேலாண்மை சொருகுப்பொருள் +Name[tg]=Идоракунии китоби адресӣ +Name[tr]=Adres Defteri Düzenleme Eklentisi +Name[uk]=Втулок для керування адресною книгою +Name[zh_CN]=地址簿管理插件 +Name[zh_TW]=管理通訊錄外掛程式 +Comment=Plugin for managing address books +Comment[af]=Inprop module om adres boeke te bestuur +Comment[be]=Дапаўненне для кіравання адраснамі кнігамі +Comment[bg]=Приставка за управление на адресника +Comment[br]=Lugent melestradur ar c'harnedoù chomlec'hioù +Comment[bs]=Dodatak za upravljanje adresarima +Comment[ca]=Endollable per gestionar llibretes d'adreces +Comment[cs]=Modul pro správu knih adres +Comment[da]=Plugin til at håndtere adressebøger +Comment[de]=Modul zur Verwaltung von Adressbüchern +Comment[el]=Πρόσθετο για τη διαχείριση βιβλίων διευθύνσεων +Comment[eo]=Kromaĵo por administri ddresarojn +Comment[es]=Extenxión para gestionar libretas de direcciones +Comment[et]=Plugin aadressiraamatute haldamiseks +Comment[eu]=Helbide-liburuak kudeatzeko plugin-a +Comment[fa]=وصله برای مدیریت کتابهای نشانی +Comment[fi]=Osoitekirjojen ylläpidon laajennus +Comment[fr]=Module pour gérer les carnets d'adresses +Comment[fy]=Plugin foar it behearen fan adresboeken +Comment[gl]=Extensión para xestionar cadernos de enderezos +Comment[he]=תוסף לניהול פנקסי כתובות +Comment[hu]=Bővítőmodul címjegyzékek kezeléséhez +Comment[is]=Íforrit til að sjá um vistfangaskrár +Comment[it]=Plugin per gestire rubriche indirizzi +Comment[ja]=アドレス帳管理用プラグイン +Comment[ka]=წიგნაკის მართვის მოდული +Comment[kk]=Адрестік кітапшамен айналысу плагин модулі +Comment[km]=កម្មវិធីជំនួយដើម្បីគ្រប់គ្រងសៀវភៅអាសយដ្ឋាន +Comment[lt]=Priedas adresų knygelių tvarkymui +Comment[mk]=Приклучок за менаџирање адресари +Comment[ms]=Plugin untuk pengurusan buku alamat +Comment[nb]=Programtillegg for å håndtere adressebøker +Comment[nds]=Moduul för't Plegen vun Adressböker +Comment[ne]=ठगाना पुस्तिका व्यवस्थापनका लागि प्लगइन +Comment[nl]=Plugin voor het beheren van adresboeken +Comment[nn]=Programtillegg for handtering av adressebøker +Comment[pl]=Wtyczka do zarządzania książkami adresowymi +Comment[pt]=Um 'plugin' para gerir os livros de endereços +Comment[pt_BR]=Plug-in para gerenciar livros de endereços +Comment[ru]=Управление адресными книгами +Comment[se]=Lassemoduvla mii gieđahallá čujuhusgirjjiid +Comment[sk]=Modul pre správu adresárov +Comment[sl]=Vstavek za upravljanje adresarjev +Comment[sr]=Прикључак за управљање адресарима +Comment[sr@Latn]=Priključak za upravljanje adresarima +Comment[sv]=Insticksprogram för att hantera adressböcker +Comment[ta]=பகிர்தல் பட்டியல் நிர்வகித்தலின் சொருகுப்பொருள் +Comment[tg]=Идоракунии китобҳои адресӣ +Comment[tr]=Adres defteterini düzenlemek için eklenti +Comment[uk]=Втулок для керування адресними книгами +Comment[zh_CN]=管理地址簿的插件 +Comment[zh_TW]=管理通訊錄外掛程式 +Type=Service +ServiceTypes=KAddressBook/Extension +X-KDE-KAddressBook-ExtensionPluginVersion=1 diff --git a/kaddressbook/features/resourceselection.h b/kaddressbook/features/resourceselection.h new file mode 100644 index 000000000..07c458f37 --- /dev/null +++ b/kaddressbook/features/resourceselection.h @@ -0,0 +1,81 @@ +/* + This file is part of KAddressBook. + Copyright (c) 2004 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 RESOURCESELECTION_H +#define RESOURCESELECTION_H + +#include <klistview.h> + +#include "extensionwidget.h" + +class QListViewItem; +class QPushButton; + +namespace KPIM { class ResourceABC; } + +class ResourceItem; + +class ResourceSelection : public KAB::ExtensionWidget +{ + Q_OBJECT + + public: + ResourceSelection( KAB::Core*, QWidget *parent, const char *name ); + virtual ~ResourceSelection(); + + QString title() const; + QString identifier() const; + + void contactsSelectionChanged() {}; + + private slots: + void add(); + void edit(); + void remove(); + void currentChanged( QListViewItem* ); + + void updateView(); + + void slotSubresourceAdded( KPIM::ResourceABC *resource, + const QString& /*type*/, + const QString& subResource ); + void slotSubresourceRemoved( KPIM::ResourceABC* /*resource*/, + const QString& /*type*/, + const QString& subResource ); + + private: + void initGUI(); + + ResourceItem* selectedItem() const; + + KListView *mListView; + QPushButton *mAddButton; + QPushButton *mEditButton; + QPushButton *mRemoveButton; + + QString mLastResource; + + KRES::Manager<KABC::Resource> *mManager; +}; + +#endif diff --git a/kaddressbook/filtereditdialog.cpp b/kaddressbook/filtereditdialog.cpp new file mode 100644 index 000000000..40c0f077c --- /dev/null +++ b/kaddressbook/filtereditdialog.cpp @@ -0,0 +1,279 @@ +/* + This file is part of KAddressBook. + Copyright (c) 2002 Mike Pilone <mpilone@slac.com> + + 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 <qbuttongroup.h> +#include <qhbox.h> +#include <qlabel.h> +#include <qlayout.h> +#include <qpushbutton.h> +#include <qradiobutton.h> +#include <qregexp.h> +#include <qstring.h> +#include <qtoolbutton.h> +#include <qtooltip.h> +#include <qwidget.h> + +#include <kapplication.h> +#include <kbuttonbox.h> +#include <kdebug.h> +#include <kiconloader.h> +#include <klineedit.h> +#include <klistbox.h> +#include <klistview.h> +#include <klocale.h> + +#include "kabprefs.h" +#include "filtereditdialog.h" + +FilterEditDialog::FilterEditDialog( QWidget *parent, const char *name ) + : KDialogBase( Plain, i18n( "Edit Address Book Filter" ), + Help | Ok | Cancel, Ok, parent, name, false, true ) +{ + initGUI(); + + const QStringList cats = KABPrefs::instance()->customCategories(); + + QStringList::ConstIterator it; + for ( it = cats.begin(); it != cats.end(); ++it ) + mCategoriesView->insertItem( new QCheckListItem( mCategoriesView, *it, QCheckListItem::CheckBox ) ); + + filterNameTextChanged( mNameEdit->text() ); +} + +FilterEditDialog::~FilterEditDialog() +{ +} + +void FilterEditDialog::setFilter( const Filter &filter ) +{ + mNameEdit->setText( filter.name() ); + + QStringList categories = filter.categories(); + QListViewItem *item = mCategoriesView->firstChild(); + while ( item != 0 ) { + if ( categories.contains( item->text( 0 ) ) ) { + QCheckListItem *checkItem = static_cast<QCheckListItem*>( item ); + checkItem->setOn( true ); + } + + item = item->nextSibling(); + } + + if ( filter.matchRule() == Filter::Matching ) + mMatchRuleGroup->setButton( 0 ); + else + mMatchRuleGroup->setButton( 1 ); +} + +Filter FilterEditDialog::filter() +{ + Filter filter; + + filter.setName( mNameEdit->text() ); + + QStringList categories; + QListViewItem *item = mCategoriesView->firstChild(); + while ( item != 0 ) { + QCheckListItem *checkItem = static_cast<QCheckListItem*>( item ); + if ( checkItem->isOn() ) + categories.append( item->text( 0 ) ); + + item = item->nextSibling(); + } + filter.setCategories( categories ); + + if ( mMatchRuleGroup->find( 0 )->isOn() ) + filter.setMatchRule( Filter::Matching ); + else + filter.setMatchRule( Filter::NotMatching ); + + return filter; +} + +void FilterEditDialog::initGUI() +{ + resize( 490, 300 ); + + QWidget *page = plainPage(); + QLabel *label; + + QGridLayout *topLayout = new QGridLayout( page, 3, 2, 0, spacingHint() ); + + label = new QLabel( i18n( "Name:" ), page ); + mNameEdit = new KLineEdit( page ); + mNameEdit->setFocus(); + topLayout->addWidget( label, 0, 0 ); + topLayout->addWidget( mNameEdit, 0, 1 ); + connect( mNameEdit, SIGNAL( textChanged( const QString& ) ), + SLOT( filterNameTextChanged( const QString&) ) ); + + mCategoriesView = new KListView( page ); + mCategoriesView->addColumn( i18n( "Category" ) ); + mCategoriesView->setFullWidth( true ); + topLayout->addMultiCellWidget( mCategoriesView, 1, 1, 0, 1 ); + + mMatchRuleGroup = new QButtonGroup( page ); + mMatchRuleGroup->setExclusive( true ); + + QBoxLayout *gbLayout = new QVBoxLayout( mMatchRuleGroup ); + gbLayout->setSpacing( KDialog::spacingHint() ); + gbLayout->setMargin( KDialog::marginHint() ); + + QRadioButton *radio = new QRadioButton( i18n( "Show only contacts matching the selected categories" ), mMatchRuleGroup ); + radio->setChecked( true ); + mMatchRuleGroup->insert( radio ); + gbLayout->addWidget( radio ); + + radio = new QRadioButton( i18n( "Show all contacts except those matching the selected categories" ), mMatchRuleGroup ); + mMatchRuleGroup->insert( radio ); + gbLayout->addWidget( radio ); + + topLayout->addMultiCellWidget( mMatchRuleGroup, 2, 2, 0, 1 ); +} + +void FilterEditDialog::filterNameTextChanged( const QString &text ) +{ + enableButtonOK( !text.isEmpty() ); +} + +void FilterEditDialog::slotHelp() +{ + kapp->invokeHelp( "using-filters" ); +} + +FilterDialog::FilterDialog( QWidget *parent, const char *name ) + : KDialogBase( Plain, i18n( "Edit Address Book Filters" ), + Ok | Cancel, Ok, parent, name, false, true ) +{ + initGUI(); +} + +FilterDialog::~FilterDialog() +{ +} + +void FilterDialog::setFilters( const Filter::List &list ) +{ + mFilterList.clear(); + mInternalFilterList.clear(); + + Filter::List::ConstIterator it; + for ( it = list.begin(); it != list.end(); ++it ) { + if ( (*it).isInternal() ) + mInternalFilterList.append( *it ); + else + mFilterList.append( *it ); + } + + refresh(); +} + +Filter::List FilterDialog::filters() const +{ + Filter::List list = mFilterList + mInternalFilterList; + return list; +} + +void FilterDialog::add() +{ + FilterEditDialog dlg( this ); + + if ( dlg.exec() ) + mFilterList.append( dlg.filter() ); + + refresh(); + + mFilterListBox->setCurrentItem( mFilterListBox->count() - 1 ); +} + +void FilterDialog::edit() +{ + FilterEditDialog dlg( this ); + + uint pos = mFilterListBox->currentItem(); + + dlg.setFilter( mFilterList[ pos ] ); + + if ( dlg.exec() ) { + mFilterList.remove( mFilterList.at( pos ) ); + mFilterList.insert( mFilterList.at( pos ), dlg.filter() ); + } + + refresh(); + + mFilterListBox->setCurrentItem( pos ); +} + +void FilterDialog::remove() +{ + mFilterList.remove( mFilterList.at( mFilterListBox->currentItem() ) ); + + selectionChanged( 0 ); + + refresh(); +} + +void FilterDialog::refresh() +{ + mFilterListBox->clear(); + + Filter::List::ConstIterator it; + for ( it = mFilterList.begin(); it != mFilterList.end(); ++it ) + mFilterListBox->insertItem( (*it).name() ); +} + +void FilterDialog::selectionChanged( QListBoxItem *item ) +{ + bool state = ( item != 0 ); + + mEditButton->setEnabled( state ); + mRemoveButton->setEnabled( state ); +} + +void FilterDialog::initGUI() +{ + resize( 330, 200 ); + + QWidget *page = plainPage(); + + QGridLayout *topLayout = new QGridLayout( page, 1, 2, 0, spacingHint() ); + + mFilterListBox = new KListBox( page ); + topLayout->addWidget( mFilterListBox, 0, 0 ); + connect( mFilterListBox, SIGNAL( selectionChanged( QListBoxItem * ) ), + SLOT( selectionChanged( QListBoxItem * ) ) ); + connect( mFilterListBox, SIGNAL( doubleClicked ( QListBoxItem * ) ), + SLOT( edit() ) ); + + KButtonBox *buttonBox = new KButtonBox( page, Vertical ); + buttonBox->addButton( i18n( "&Add..." ), this, SLOT( add() ) ); + mEditButton = buttonBox->addButton( i18n( "&Edit..." ), this, SLOT( edit() ) ); + mEditButton->setEnabled( false ); + mRemoveButton = buttonBox->addButton( i18n( "&Remove" ), this, SLOT( remove() ) ); + mRemoveButton->setEnabled( false ); + + buttonBox->layout(); + topLayout->addWidget( buttonBox, 0, 1 ); +} + +#include "filtereditdialog.moc" diff --git a/kaddressbook/filtereditdialog.h b/kaddressbook/filtereditdialog.h new file mode 100644 index 000000000..b61c36ca7 --- /dev/null +++ b/kaddressbook/filtereditdialog.h @@ -0,0 +1,96 @@ +/* + This file is part of KAddressBook. + Copyright (c) 2002 Mike Pilone <mpilone@slac.com> + + 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 FILTEREDITDIALOG_H +#define FILTEREDITDIALOG_H + +class QButtonGroup; +class QString; +class QToolButton; +class QWidget; + +class KLineEdit; +class KListBox; +class KListView; + +#include <kdialogbase.h> + +#include "filter.h" + +class FilterDialog : public KDialogBase +{ + Q_OBJECT + + public: + FilterDialog( QWidget *parent, const char *name = 0 ); + ~FilterDialog(); + + void setFilters( const Filter::List &list ); + Filter::List filters() const; + + protected slots: + void add(); + void edit(); + void remove(); + void selectionChanged( QListBoxItem* ); + + private: + void initGUI(); + void refresh(); + + Filter::List mFilterList; + Filter::List mInternalFilterList; + + KListBox *mFilterListBox; + QPushButton *mAddButton; + QPushButton *mEditButton; + QPushButton *mRemoveButton; +}; + +class FilterEditDialog : public KDialogBase +{ + Q_OBJECT + public: + FilterEditDialog( QWidget *parent, const char *name = 0 ); + ~FilterEditDialog(); + + void setFilter( const Filter &filter ); + Filter filter(); + + protected slots: + void filterNameTextChanged( const QString& ); + void slotHelp(); + + private: + void initGUI(); + + Filter mFilter; + + KLineEdit *mNameEdit; + KListView *mCategoriesView; + QButtonGroup *mMatchRuleGroup; + QPushButton *mEditButton; + QPushButton *mRemoveButton; +}; + +#endif diff --git a/kaddressbook/filterselectionwidget.cpp b/kaddressbook/filterselectionwidget.cpp new file mode 100644 index 000000000..ddd4fa2f2 --- /dev/null +++ b/kaddressbook/filterselectionwidget.cpp @@ -0,0 +1,65 @@ +/* + This file is part of KAddressBook. + Copyright (c) 2002 Mike Pilone <mpilone@slac.com> + + 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 <qlabel.h> + +#include <kcombobox.h> +#include <kdialog.h> +#include <klocale.h> + +#include "filterselectionwidget.h" + +FilterSelectionWidget::FilterSelectionWidget( QWidget *parent, const char *name ) + : QHBox( parent, name ) +{ + setSpacing( KDialog::spacingHint() ); + + QLabel *label = new QLabel( i18n( "Filter:" ), this, "kde toolbar widget" ); + + mFilterCombo = new KComboBox( this ); + label->setBuddy( mFilterCombo ); + connect( mFilterCombo, SIGNAL( activated( int ) ), + this, SIGNAL( filterActivated( int ) ) ); +} + +FilterSelectionWidget::~FilterSelectionWidget() +{ +} + +int FilterSelectionWidget::currentItem() const +{ + return mFilterCombo->currentItem(); +} + +void FilterSelectionWidget::setCurrentItem( int index ) +{ + mFilterCombo->setCurrentItem( index ); +} + +void FilterSelectionWidget::setItems( const QStringList &names ) +{ + mFilterCombo->clear(); + mFilterCombo->insertStringList( names ); +} + +#include "filterselectionwidget.moc" diff --git a/kaddressbook/filterselectionwidget.h b/kaddressbook/filterselectionwidget.h new file mode 100644 index 000000000..fcae42fc1 --- /dev/null +++ b/kaddressbook/filterselectionwidget.h @@ -0,0 +1,56 @@ +/* + This file is part of KAddressBook. + Copyright (c) 2002 Mike Pilone <mpilone@slac.com> + + 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 FILTERSELECTIONWIDGET_H +#define FILTERSELECTIONWIDGET_H + +#include <qhbox.h> + +class KComboBox; + +/** + A simple widget which consists of a label and a combo box in a + horizontal line. The combo box allows the user to select the active + filter. + */ +class FilterSelectionWidget : public QHBox +{ + Q_OBJECT + + public: + FilterSelectionWidget( QWidget *parent, const char *name = 0 ); + ~FilterSelectionWidget(); + + void setItems( const QStringList &names ); + + int currentItem() const; + void setCurrentItem( int index ); + + signals: + void filterActivated( int ); + + private: + KComboBox *mFilterCombo; +}; + +#endif diff --git a/kaddressbook/freebusywidget.cpp b/kaddressbook/freebusywidget.cpp new file mode 100644 index 000000000..d06a0ebd9 --- /dev/null +++ b/kaddressbook/freebusywidget.cpp @@ -0,0 +1,78 @@ +/* + This file is part of KAddressBook. + Copyright (c) 2004 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 <qlabel.h> +#include <qlayout.h> + +#include <kdialog.h> +#include <klocale.h> +#include <kstandarddirs.h> + +#include <libkcal/freebusyurlstore.h> + +#include "freebusywidget.h" + +FreeBusyWidget::FreeBusyWidget( KABC::AddressBook *ab, QWidget *parent, const char *name ) + : KAB::ContactEditorWidget( ab, parent, name ) +{ + QHBoxLayout *layout = new QHBoxLayout( this, KDialog::marginHint(), + KDialog::spacingHint() ); + + QLabel *label = new QLabel( i18n( "Location of Free/Busy information:" ), this ); + layout->addWidget( label ); + + mURL = new KURLRequester( this ); + label->setBuddy( mURL ); + layout->addWidget( mURL ); + + connect( mURL, SIGNAL( textChanged( const QString& ) ), + this, SLOT( setModified() ) ); +} + +FreeBusyWidget::~FreeBusyWidget() +{ +} + +void FreeBusyWidget::loadContact( KABC::Addressee *addr ) +{ + if ( addr->preferredEmail().isEmpty() ) + return; + + mURL->setURL( KCal::FreeBusyUrlStore::self()->readUrl( addr->preferredEmail() ) ); +} + +void FreeBusyWidget::storeContact( KABC::Addressee *addr ) +{ + if ( addr->preferredEmail().isEmpty() ) + return; + + KCal::FreeBusyUrlStore::self()->writeUrl( addr->preferredEmail(), mURL->url() ); + KCal::FreeBusyUrlStore::self()->sync(); +} + +void FreeBusyWidget::setReadOnly( bool readOnly ) +{ + mURL->setEnabled( !readOnly ); +} + +#include "freebusywidget.moc" diff --git a/kaddressbook/freebusywidget.h b/kaddressbook/freebusywidget.h new file mode 100644 index 000000000..99d32320d --- /dev/null +++ b/kaddressbook/freebusywidget.h @@ -0,0 +1,61 @@ +/* + This file is part of KAddressBook. + Copyright (c) 2004 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 FREEBUSYWIDGET_H +#define FREEBUSYWIDGET_H + +#include <kurlrequester.h> + +#include "contacteditorwidget.h" + +class FreeBusyWidget : public KAB::ContactEditorWidget +{ + Q_OBJECT + + public: + FreeBusyWidget( KABC::AddressBook *ab, QWidget *parent, const char *name = 0 ); + ~FreeBusyWidget(); + + void loadContact( KABC::Addressee *addr ); + void storeContact( KABC::Addressee *addr ); + + void setReadOnly( bool readOnly ); + + private: + KURLRequester *mURL; + + bool mReadOnly; +}; + +class FreeBusyWidgetFactory : public KAB::ContactEditorWidgetFactory +{ + public: + KAB::ContactEditorWidget *createWidget( KABC::AddressBook *ab, QWidget *parent, const char *name ) + { + return new FreeBusyWidget( ab, parent, name ); + } + + QString pageIdentifier() const { return "misc"; } +}; + +#endif diff --git a/kaddressbook/geowidget.cpp b/kaddressbook/geowidget.cpp new file mode 100644 index 000000000..3563f118e --- /dev/null +++ b/kaddressbook/geowidget.cpp @@ -0,0 +1,562 @@ +/* + This file is part of KAddressBook. + Copyright (c) 2002 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 <kabc/geo.h> +#include <kaccelmanager.h> +#include <kcombobox.h> +#include <kdebug.h> +#include <kiconloader.h> +#include <klocale.h> +#include <knuminput.h> +#include <kstandarddirs.h> + +#include <qcheckbox.h> +#include <qfile.h> +#include <qgroupbox.h> +#include <qlabel.h> +#include <qlayout.h> +#include <qlistbox.h> +#include <qpainter.h> +#include <qpixmap.h> +#include <qpushbutton.h> +#include <qregexp.h> +#include <qstring.h> + +#include "geowidget.h" + +GeoWidget::GeoWidget( KABC::AddressBook *ab, QWidget *parent, const char *name ) + : KAB::ContactEditorWidget( ab, parent, name ), mReadOnly( false ) +{ + QLabel *label = 0; + + QGridLayout *topLayout = new QGridLayout( this, 4, 3 ); + topLayout->setMargin( KDialog::marginHint() ); + topLayout->setSpacing( KDialog::spacingHint() ); + + label = new QLabel( this ); + label->setPixmap( KGlobal::iconLoader()->loadIcon( "package_network", + KIcon::Desktop, KIcon::SizeMedium ) ); + label->setAlignment( Qt::AlignTop ); + topLayout->addMultiCellWidget( label, 0, 3, 0, 0 ); + + mGeoIsValid = new QCheckBox( i18n( "Use geo data" ), this ); + topLayout->addMultiCellWidget( mGeoIsValid, 0, 0, 1, 2 ); + + label = new QLabel( i18n( "Latitude:" ), this ); + topLayout->addWidget( label, 1, 1 ); + + mLatitudeBox = new KDoubleSpinBox( -90, 90, 1, 0, 6, this ); + mLatitudeBox->setEnabled( false ); + mLatitudeBox->setSuffix( "" ); + topLayout->addWidget( mLatitudeBox, 1, 2 ); + label->setBuddy( mLatitudeBox ); + + label = new QLabel( i18n( "Longitude:" ), this ); + topLayout->addWidget( label, 2, 1 ); + + mLongitudeBox = new KDoubleSpinBox( -180, 180, 1, 0, 6, this ); + mLongitudeBox->setEnabled( false ); + mLongitudeBox->setSuffix( "" ); + topLayout->addWidget( mLongitudeBox, 2, 2 ); + label->setBuddy( mLongitudeBox ); + + mExtendedButton = new QPushButton( i18n( "Edit Geo Data..." ), this ); + mExtendedButton->setEnabled( false ); + topLayout->addMultiCellWidget( mExtendedButton, 3, 3, 1, 2 ); + + connect( mLatitudeBox, SIGNAL( valueChanged( double ) ), + SLOT( setModified() ) ); + connect( mLongitudeBox, SIGNAL( valueChanged( double ) ), + SLOT( setModified() ) ); + connect( mExtendedButton, SIGNAL( clicked() ), + SLOT( editGeoData() ) ); + + connect( mGeoIsValid, SIGNAL( toggled( bool ) ), + mLatitudeBox, SLOT( setEnabled( bool ) ) ); + connect( mGeoIsValid, SIGNAL( toggled( bool ) ), + mLongitudeBox, SLOT( setEnabled( bool ) ) ); + connect( mGeoIsValid, SIGNAL( toggled( bool ) ), + mExtendedButton, SLOT( setEnabled( bool ) ) ); + connect( mGeoIsValid, SIGNAL( toggled( bool ) ), + SLOT( setModified() ) ); +} + +GeoWidget::~GeoWidget() +{ +} + +void GeoWidget::loadContact( KABC::Addressee *addr ) +{ + KABC::Geo geo = addr->geo(); + + if ( geo.isValid() ) { + if ( !mReadOnly ) + mGeoIsValid->setChecked( true ); + mLatitudeBox->setValue( geo.latitude() ); + mLongitudeBox->setValue( geo.longitude() ); + } else + mGeoIsValid->setChecked( false ); +} + +void GeoWidget::storeContact( KABC::Addressee *addr ) +{ + KABC::Geo geo; + + if ( mGeoIsValid->isChecked() ) { + geo.setLatitude( mLatitudeBox->value() ); + geo.setLongitude( mLongitudeBox->value() ); + } else { + geo.setLatitude( 91 ); + geo.setLongitude( 181 ); + } + + addr->setGeo( geo ); +} + +void GeoWidget::setReadOnly( bool readOnly ) +{ + mReadOnly = readOnly; + + mGeoIsValid->setEnabled( !mReadOnly ); +} + +void GeoWidget::editGeoData() +{ + GeoDialog dlg( this ); + + dlg.setLatitude( mLatitudeBox->value() ); + dlg.setLongitude( mLongitudeBox->value() ); + + if ( dlg.exec() ) { + mLatitudeBox->setValue( dlg.latitude() ); + mLongitudeBox->setValue( dlg.longitude() ); + + setModified( true ); + } +} + + + +GeoDialog::GeoDialog( QWidget *parent, const char *name ) + : KDialogBase( Plain, i18n( "Geo Data Input" ), Ok | Cancel, Ok, + parent, name, true, true ), + mUpdateSexagesimalInput( true ) +{ + QFrame *page = plainPage(); + + QGridLayout *topLayout = new QGridLayout( page, 2, 2, marginHint(), + spacingHint() ); + topLayout->setRowStretch( 1, 1 ); + + mMapWidget = new GeoMapWidget( page ); + topLayout->addMultiCellWidget( mMapWidget, 0, 1, 0, 0 ); + + mCityCombo = new KComboBox( page ); + topLayout->addWidget( mCityCombo, 0, 1 ); + + QGroupBox *sexagesimalGroup = new QGroupBox( 0, Vertical, i18n( "Sexagesimal" ), page ); + QGridLayout *sexagesimalLayout = new QGridLayout( sexagesimalGroup->layout(), + 2, 5, spacingHint() ); + + QLabel *label = new QLabel( i18n( "Latitude:" ), sexagesimalGroup ); + sexagesimalLayout->addWidget( label, 0, 0 ); + + mLatDegrees = new QSpinBox( 0, 90, 1, sexagesimalGroup ); + mLatDegrees->setSuffix( "" ); + mLatDegrees->setWrapping( false ); + label->setBuddy( mLatDegrees ); + sexagesimalLayout->addWidget( mLatDegrees, 0, 1 ); + + mLatMinutes = new QSpinBox( 0, 59, 1, sexagesimalGroup ); + mLatMinutes->setSuffix( "'" ); + sexagesimalLayout->addWidget( mLatMinutes, 0, 2 ); + + mLatSeconds = new QSpinBox( 0, 59, 1, sexagesimalGroup ); + mLatSeconds->setSuffix( "\"" ); + sexagesimalLayout->addWidget( mLatSeconds, 0, 3 ); + + mLatDirection = new KComboBox( sexagesimalGroup ); + mLatDirection->insertItem( i18n( "North" ) ); + mLatDirection->insertItem( i18n( "South" ) ); + sexagesimalLayout->addWidget( mLatDirection, 0, 4 ); + + label = new QLabel( i18n( "Longitude:" ), sexagesimalGroup ); + sexagesimalLayout->addWidget( label, 1, 0 ); + + mLongDegrees = new QSpinBox( 0, 180, 1, sexagesimalGroup ); + mLongDegrees->setSuffix( "" ); + label->setBuddy( mLongDegrees ); + sexagesimalLayout->addWidget( mLongDegrees, 1, 1 ); + + mLongMinutes = new QSpinBox( 0, 59, 1, sexagesimalGroup ); + mLongMinutes->setSuffix( "'" ); + sexagesimalLayout->addWidget( mLongMinutes, 1, 2 ); + + mLongSeconds = new QSpinBox( 0, 59, 1, sexagesimalGroup ); + mLongSeconds->setSuffix( "\"" ); + sexagesimalLayout->addWidget( mLongSeconds, 1, 3 ); + + mLongDirection = new KComboBox( sexagesimalGroup ); + mLongDirection->insertItem( i18n( "East" ) ); + mLongDirection->insertItem( i18n( "West" ) ); + sexagesimalLayout->addWidget( mLongDirection, 1, 4 ); + + topLayout->addWidget( sexagesimalGroup, 1, 1 ); + + loadCityList(); + + connect( mMapWidget, SIGNAL( changed() ), + SLOT( geoMapChanged() ) ); + connect( mCityCombo, SIGNAL( activated( int ) ), + SLOT( cityInputChanged() ) ); + connect( mLatDegrees, SIGNAL( valueChanged( int ) ), + SLOT( sexagesimalInputChanged() ) ); + connect( mLatMinutes, SIGNAL( valueChanged( int ) ), + SLOT( sexagesimalInputChanged() ) ); + connect( mLatSeconds, SIGNAL( valueChanged( int ) ), + SLOT( sexagesimalInputChanged() ) ); + connect( mLatDirection, SIGNAL( activated( int ) ), + SLOT( sexagesimalInputChanged() ) ); + connect( mLongDegrees, SIGNAL( valueChanged( int ) ), + SLOT( sexagesimalInputChanged() ) ); + connect( mLongMinutes, SIGNAL( valueChanged( int ) ), + SLOT( sexagesimalInputChanged() ) ); + connect( mLongSeconds, SIGNAL( valueChanged( int ) ), + SLOT( sexagesimalInputChanged() ) ); + connect( mLongDirection, SIGNAL( activated( int ) ), + SLOT( sexagesimalInputChanged() ) ); + + KAcceleratorManager::manage( this ); +} + +GeoDialog::~GeoDialog() +{ +} + +void GeoDialog::setLatitude( double latitude ) +{ + mLatitude = latitude; + updateInputs(); +} + +double GeoDialog::latitude() const +{ + return mLatitude; +} + +void GeoDialog::setLongitude( double longitude ) +{ + mLongitude = longitude; + updateInputs(); +} + +double GeoDialog::longitude() const +{ + return mLongitude; +} + +void GeoDialog::sexagesimalInputChanged() +{ + mLatitude = (double)( mLatDegrees->value() + (double)mLatMinutes->value() / + 60 + (double)mLatSeconds->value() / 3600 ); + + mLatitude *= ( mLatDirection->currentItem() == 1 ? -1 : 1 ); + + mLongitude = (double)( mLongDegrees->value() + (double)mLongMinutes->value() / + 60 + (double)mLongSeconds->value() / 3600 ); + + mLongitude *= ( mLongDirection->currentItem() == 1 ? -1 : 1 ); + + mUpdateSexagesimalInput = false; + + updateInputs(); +} + +void GeoDialog::geoMapChanged() +{ + mLatitude = mMapWidget->latitude(); + mLongitude = mMapWidget->longitude(); + + updateInputs(); +} + +void GeoDialog::cityInputChanged() +{ + if ( mCityCombo->currentItem() != 0 ) { + GeoData data = mGeoDataMap[ mCityCombo->currentText() ]; + mLatitude = data.latitude; + mLongitude = data.longitude; + } else + mLatitude = mLongitude = 0; + + updateInputs(); +} + +void GeoDialog::updateInputs() +{ + // hmm, doesn't look nice, but there is no better way AFAIK + mCityCombo->blockSignals( true ); + mLatDegrees->blockSignals( true ); + mLatMinutes->blockSignals( true ); + mLatSeconds->blockSignals( true ); + mLatDirection->blockSignals( true ); + mLongDegrees->blockSignals( true ); + mLongMinutes->blockSignals( true ); + mLongSeconds->blockSignals( true ); + mLongDirection->blockSignals( true ); + + mMapWidget->setLatitude( mLatitude ); + mMapWidget->setLongitude( mLongitude ); + mMapWidget->update(); + + if ( mUpdateSexagesimalInput ) { + int degrees, minutes, seconds; + double latitude = mLatitude; + double longitude = mLongitude; + + latitude *= ( mLatitude < 0 ? -1 : 1 ); + longitude *= ( mLongitude < 0 ? -1 : 1 ); + + degrees = (int)( latitude * 1 ); + minutes = (int)( ( latitude - degrees ) * 60 ); + seconds = (int)( (double)( (double)latitude - (double)degrees - ( (double)minutes / (double)60 ) ) * (double)3600 ); + + mLatDegrees->setValue( degrees ); + mLatMinutes->setValue( minutes ); + mLatSeconds->setValue( seconds ); + + mLatDirection->setCurrentItem( mLatitude < 0 ? 1 : 0 ); + + degrees = (int)( longitude * 1 ); + minutes = (int)( ( longitude - degrees ) * 60 ); + seconds = (int)( (double)( longitude - (double)degrees - ( (double)minutes / 60 ) ) * 3600 ); + + mLongDegrees->setValue( degrees ); + mLongMinutes->setValue( minutes ); + mLongSeconds->setValue( seconds ); + mLongDirection->setCurrentItem( mLongitude < 0 ? 1 : 0 ); + } + mUpdateSexagesimalInput = true; + + int pos = nearestCity( mLongitude, mLatitude ); + if ( pos != -1 ) + mCityCombo->setCurrentItem( pos + 1 ); + else + mCityCombo->setCurrentItem( 0 ); + + mCityCombo->blockSignals( false ); + mLatDegrees->blockSignals( false ); + mLatMinutes->blockSignals( false ); + mLatSeconds->blockSignals( false ); + mLatDirection->blockSignals( false ); + mLongDegrees->blockSignals( false ); + mLongMinutes->blockSignals( false ); + mLongSeconds->blockSignals( false ); + mLongDirection->blockSignals( false ); +} + +void GeoDialog::loadCityList() +{ + mCityCombo->clear(); + mGeoDataMap.clear(); + + QFile file( locate( "data", "kaddressbook/zone.tab" ) ); + + if ( file.open( IO_ReadOnly ) ) { + QTextStream s( &file ); + + QString line, country; + QRegExp coord( "[+-]\\d+[+-]\\d+" ); + QRegExp name( "[^\\s]+/[^\\s]+" ); + int pos; + + while ( !s.eof() ) { + line = s.readLine().stripWhiteSpace(); + if ( line.isEmpty() || line[ 0 ] == '#' ) + continue; + + country = line.left( 2 ); + QString c, n; + pos = coord.search( line, 0 ); + if ( pos >= 0 ) + c = line.mid( pos, coord.matchedLength() ); + + pos = name.search(line, pos); + if ( pos > 0 ) { + n = line.mid( pos, name.matchedLength() ).stripWhiteSpace(); + n.replace( '_', " " ); + } + + if ( !c.isEmpty() && !n.isEmpty() ) { + pos = c.find( "+", 1 ); + if ( pos < 0 ) + pos = c.find( "-", 1 ); + if ( pos > 0 ) { + GeoData data; + data.latitude = calculateCoordinate( c.left( pos ) ); + data.longitude = calculateCoordinate( c.mid( pos ) ); + data.country = country; + + mGeoDataMap.insert( n, data ); + } + } + } + QStringList items( mGeoDataMap.keys() ); + items.prepend( i18n( "Undefined" ) ); + mCityCombo->insertStringList( items ); + + file.close(); + } +} + +double GeoDialog::calculateCoordinate( const QString &coordinate ) const +{ + int neg; + int d = 0, m = 0, s = 0; + QString str = coordinate; + + neg = str.left( 1 ) == "-"; + str.remove( 0, 1 ); + + switch ( str.length() ) { + case 4: + d = str.left( 2 ).toInt(); + m = str.mid( 2 ).toInt(); + break; + case 5: + d = str.left( 3 ).toInt(); + m = str.mid( 3 ).toInt(); + break; + case 6: + d = str.left( 2 ).toInt(); + m = str.mid( 2, 2 ).toInt(); + s = str.right( 2 ).toInt(); + break; + case 7: + d = str.left( 3 ).toInt(); + m = str.mid( 3, 2 ).toInt(); + s = str.right( 2 ).toInt(); + break; + default: + break; + } + + if ( neg ) + return - ( d + m / 60.0 + s / 3600.0 ); + else + return d + m / 60.0 + s / 3600.0; +} + +int GeoDialog::nearestCity( double x, double y ) const +{ + QMap<QString, GeoData>::ConstIterator it; + int pos = 0; + for ( it = mGeoDataMap.begin(); it != mGeoDataMap.end(); ++it, ++pos ) { + double dist = ( (*it).longitude - x ) * ( (*it).longitude - x ) + + ( (*it).latitude - y ) * ( (*it).latitude - y ); + if ( dist < 1.5 ) + return pos; + } + + return -1; +} + + +GeoMapWidget::GeoMapWidget( QWidget *parent, const char *name ) + : QWidget( parent, name ), mLatitude( 0 ), mLongitude( 0 ) +{ + setBackgroundMode( NoBackground ); + + setFixedSize( 400, 200 ); + + update(); +} + +GeoMapWidget::~GeoMapWidget() +{ +} + +void GeoMapWidget::setLatitude( double latitude ) +{ + mLatitude = latitude; +} + +double GeoMapWidget::latitude()const +{ + return mLatitude; +} + +void GeoMapWidget::setLongitude( double longitude ) +{ + mLongitude = longitude; +} + +double GeoMapWidget::longitude()const +{ + return mLongitude; +} + +void GeoMapWidget::mousePressEvent( QMouseEvent *event ) +{ + double latMid = height() / 2; + double longMid = width() / 2; + + double latOffset = latMid - event->y(); + double longOffset = event->x() - longMid; + + mLatitude = ( latOffset * 90 ) / latMid; + mLongitude = ( longOffset * 180 ) / longMid; + + emit changed(); +} + +void GeoMapWidget::paintEvent( QPaintEvent* ) +{ + uint w = width(); + uint h = height(); + + QPixmap pm( w, h ); + QPainter p; + p.begin( &pm, this ); + + p.setPen( QColor( 255, 0, 0 ) ); + p.setBrush( QColor( 255, 0, 0 ) ); + + QPixmap world( locate( "data", "kaddressbook/pics/world.jpg" ) ); + p.drawPixmap( 0, 0, world ); + + double latMid = h / 2; + double longMid = w / 2; + + double latOffset = ( mLatitude * latMid ) / 90; + double longOffset = ( mLongitude * longMid ) / 180; + + int x = (int)(longMid + longOffset); + int y = (int)(latMid - latOffset); + p.drawEllipse( x, y, 4, 4 ); + + p.end(); + bitBlt( this, 0, 0, &pm ); +} + +#include "geowidget.moc" diff --git a/kaddressbook/geowidget.h b/kaddressbook/geowidget.h new file mode 100644 index 000000000..85140849e --- /dev/null +++ b/kaddressbook/geowidget.h @@ -0,0 +1,159 @@ +/* + This file is part of KAddressBook. + Copyright (c) 2002 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 GEOWIDGET_H +#define GEOWIDGET_H + +#include <kdialogbase.h> + +#include "contacteditorwidget.h" + +namespace KABC { +class Geo; +} + +class GeoMapWidget; + +class KComboBox; +class KDoubleSpinBox; + +class QCheckBox; +class QLabel; +class QSpinBox; +class QPushButton; + +typedef struct { + double latitude; + double longitude; + QString country; +} GeoData; + +class GeoWidget : public KAB::ContactEditorWidget +{ + Q_OBJECT + + public: + GeoWidget( KABC::AddressBook *ab, QWidget *parent, const char *name = 0 ); + ~GeoWidget(); + + void loadContact( KABC::Addressee *addr ); + void storeContact( KABC::Addressee *addr ); + + void setReadOnly( bool readOnly ); + + private slots: + void editGeoData(); + + private: + KDoubleSpinBox *mLatitudeBox; + KDoubleSpinBox *mLongitudeBox; + + QCheckBox *mGeoIsValid; + QPushButton *mExtendedButton; + + bool mReadOnly; +}; + +class GeoDialog : public KDialogBase +{ + Q_OBJECT + + public: + GeoDialog( QWidget *parent, const char *name = 0 ); + ~GeoDialog(); + + void setLatitude( double latitude ); + double latitude() const; + + void setLongitude( double longitude ); + double longitude() const; + + private slots: + void updateInputs(); + + void sexagesimalInputChanged(); + void geoMapChanged(); + void cityInputChanged(); + + private: + void loadCityList(); + double calculateCoordinate( const QString& ) const; + int nearestCity( double, double ) const; + + GeoMapWidget *mMapWidget; + KComboBox *mCityCombo; + + QSpinBox *mLatDegrees; + QSpinBox *mLatMinutes; + QSpinBox *mLatSeconds; + KComboBox *mLatDirection; + + QSpinBox *mLongDegrees; + QSpinBox *mLongMinutes; + QSpinBox *mLongSeconds; + KComboBox *mLongDirection; + + double mLatitude; + double mLongitude; + QMap<QString, GeoData> mGeoDataMap; + bool mUpdateSexagesimalInput; +}; + +class GeoMapWidget : public QWidget +{ + Q_OBJECT + + public: + GeoMapWidget( QWidget *parent, const char *name = 0 ); + ~GeoMapWidget(); + + void setLatitude( double latitude ); + double latitude()const; + + void setLongitude( double longitude ); + double longitude()const; + + signals: + void changed(); + + protected: + virtual void mousePressEvent( QMouseEvent* ); + virtual void paintEvent( QPaintEvent* ); + + private: + double mLatitude; + double mLongitude; +}; + +class GeoWidgetFactory : public KAB::ContactEditorWidgetFactory +{ + public: + KAB::ContactEditorWidget *createWidget( KABC::AddressBook *ab, QWidget *parent, const char *name ) + { + return new GeoWidget( ab, parent, name ); + } + + QString pageIdentifier() const { return "misc"; } +}; + +#endif diff --git a/kaddressbook/hi128-app-kaddressbook.png b/kaddressbook/hi128-app-kaddressbook.png Binary files differnew file mode 100644 index 000000000..5ca543bef --- /dev/null +++ b/kaddressbook/hi128-app-kaddressbook.png diff --git a/kaddressbook/hi16-app-kaddressbook.png b/kaddressbook/hi16-app-kaddressbook.png Binary files differnew file mode 100644 index 000000000..b9bc82e02 --- /dev/null +++ b/kaddressbook/hi16-app-kaddressbook.png diff --git a/kaddressbook/hi32-app-kaddressbook.png b/kaddressbook/hi32-app-kaddressbook.png Binary files differnew file mode 100644 index 000000000..ff5cfdfc5 --- /dev/null +++ b/kaddressbook/hi32-app-kaddressbook.png diff --git a/kaddressbook/hi48-app-kaddressbook.png b/kaddressbook/hi48-app-kaddressbook.png Binary files differnew file mode 100644 index 000000000..c0525bc17 --- /dev/null +++ b/kaddressbook/hi48-app-kaddressbook.png diff --git a/kaddressbook/hi64-app-kaddressbook.png b/kaddressbook/hi64-app-kaddressbook.png Binary files differnew file mode 100644 index 000000000..672a7b485 --- /dev/null +++ b/kaddressbook/hi64-app-kaddressbook.png diff --git a/kaddressbook/imagewidget.cpp b/kaddressbook/imagewidget.cpp new file mode 100644 index 000000000..ad0fad55e --- /dev/null +++ b/kaddressbook/imagewidget.cpp @@ -0,0 +1,325 @@ +/* + 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 <kabc/picture.h> +#include <kdebug.h> +#include <kdialog.h> +#include <kfiledialog.h> +#include <kglobalsettings.h> +#include <kiconloader.h> +#include <kimageio.h> +#include <kio/netaccess.h> +#include <klocale.h> +#include <kmessagebox.h> +#include <kurldrag.h> +#include <libkdepim/kpixmapregionselectordialog.h> + +#include <qapplication.h> +#include <qdragobject.h> +#include <qeventloop.h> +#include <qgroupbox.h> +#include <qlabel.h> +#include <qlayout.h> +#include <qpixmap.h> +#include <qpopupmenu.h> + +#include <unistd.h> + +#include "imagewidget.h" + +ImageLoader::ImageLoader( QWidget *parent ) + : QObject( 0, "ImageLoader" ), mParent( parent ) +{ +} + +KABC::Picture ImageLoader::loadPicture( const KURL &url, bool *ok ) +{ + KABC::Picture picture; + QString tempFile; + + if ( url.isEmpty() ) + return picture; + + (*ok) = false; + + QImage image; + if ( url.isLocalFile() ) { + image.load( url.path() ); + picture.setData( image ); + (*ok) = true; + } else if ( KIO::NetAccess::download( url, tempFile, mParent ) ) { + image.load( tempFile ); + picture.setData( image ); + (*ok) = true; + KIO::NetAccess::removeTempFile( tempFile ); + } + + if ( !(*ok) ) { + // image does not exist (any more) + KMessageBox::sorry( mParent, i18n( "This contact's image cannot be found." ) ); + return picture; + } + + QPixmap pixmap = picture.data(); + + QPixmap selectedPixmap = KPIM::KPixmapRegionSelectorDialog::getSelectedImage( pixmap, 100, 140, mParent ); + if ( selectedPixmap.isNull() ) { + (*ok) = false; + return picture; + } + + image = selectedPixmap; + if ( image.height() != 140 || image.width() != 100 ) { + if ( image.height() > image.width() ) + image = image.scaleHeight( 140 ); + else + image = image.scaleWidth( 100 ); + } + + picture.setData( image ); + (*ok) = true; + + return picture; +} + + +ImageButton::ImageButton( const QString &title, QWidget *parent ) + : QPushButton( title, parent ), + mReadOnly( false ), mImageLoader( 0 ) +{ + setAcceptDrops( true ); + + connect( this, SIGNAL( clicked() ), SLOT( load() ) ); +} + +void ImageButton::setReadOnly( bool readOnly ) +{ + mReadOnly = readOnly; +} + +void ImageButton::setPicture( const KABC::Picture &picture ) +{ + mPicture = picture; + updateGUI(); +} + +KABC::Picture ImageButton::picture() const +{ + return mPicture; +} + +void ImageButton::setImageLoader( ImageLoader *loader ) +{ + mImageLoader = loader; +} + +void ImageButton::startDrag() +{ + if ( !mPicture.data().isNull() ) { + QImageDrag *drag = new QImageDrag( mPicture.data(), this ); + drag->dragCopy(); + } +} + +void ImageButton::updateGUI() +{ + if ( mPicture.data().isNull() ) + setPixmap( KGlobal::iconLoader()->iconPath( "personal", KIcon::Desktop ) ); + else + setPixmap( mPicture.data() ); +} + +void ImageButton::dragEnterEvent( QDragEnterEvent *event ) +{ + bool accepted = false; + + if ( QImageDrag::canDecode( event ) ) + accepted = true; + + if ( QUriDrag::canDecode( event ) ) + accepted = true; + + event->accept( accepted ); +} + +void ImageButton::dropEvent( QDropEvent *event ) +{ + if ( mReadOnly ) + return; + + if ( QImageDrag::canDecode( event ) ) { + QPixmap pm; + + if ( QImageDrag::decode( event, pm ) ) { + mPicture.setData( pm.convertToImage() ); + updateGUI(); + emit changed(); + } + } + + if ( QUriDrag::canDecode( event ) ) { + KURL::List urls; + if ( KURLDrag::decode( event, urls ) ) { + if ( urls.isEmpty() ) { // oops, no data + event->accept( false ); + return; + } + } + + if ( mImageLoader ) { + bool ok = false; + KABC::Picture pic = mImageLoader->loadPicture( urls[ 0 ], &ok ); + if ( ok ) { + mPicture = pic; + updateGUI(); + emit changed(); + } + } + } +} + +void ImageButton::mousePressEvent( QMouseEvent *event ) +{ + mDragStartPos = event->pos(); + QPushButton::mousePressEvent( event ); +} + +void ImageButton::mouseMoveEvent( QMouseEvent *event ) +{ + if ( (event->state() & LeftButton) && + (event->pos() - mDragStartPos).manhattanLength() > + KGlobalSettings::dndEventDelay() ) { + startDrag(); + } +} + +void ImageButton::contextMenuEvent( QContextMenuEvent *event ) +{ + QPopupMenu menu( this ); + menu.insertItem( i18n( "Reset" ), this, SLOT( clear() ) ); + menu.exec( event->globalPos() ); +} + +void ImageButton::load() +{ + KURL url = KFileDialog::getOpenURL( QString(), KImageIO::pattern(), this ); + if ( url.isValid() ) { + if ( mImageLoader ) { + bool ok = false; + KABC::Picture pic = mImageLoader->loadPicture( url, &ok ); + if ( ok ) { + mPicture = pic; + updateGUI(); + emit changed(); + } + } + } +} + +void ImageButton::clear() +{ + mPicture = KABC::Picture(); + updateGUI(); + + emit changed(); +} + +ImageBaseWidget::ImageBaseWidget( const QString &title, + QWidget *parent, const char *name ) + : QWidget( parent, name ), mReadOnly( false ) +{ + mImageLoader = new ImageLoader( this ); + + QVBoxLayout *topLayout = new QVBoxLayout( this, KDialog::marginHint(), + KDialog::spacingHint() ); + QGroupBox *box = new QGroupBox( 0, Qt::Vertical, title, this ); + QVBoxLayout *layout = new QVBoxLayout( box->layout(), KDialog::spacingHint() ); + + mImageButton = new ImageButton( i18n( "Picture" ), box ); + mImageButton->setFixedSize( 100, 140 ); + mImageButton->setImageLoader( mImageLoader ); + layout->addWidget( mImageButton ); + + topLayout->addWidget( box ); + + connect( mImageButton, SIGNAL( changed() ), SIGNAL( changed() ) ); +} + +ImageBaseWidget::~ImageBaseWidget() +{ + delete mImageLoader; + mImageLoader = 0; +} + +void ImageBaseWidget::setReadOnly( bool readOnly ) +{ + mReadOnly = readOnly; + mImageButton->setReadOnly( mReadOnly ); +} + +void ImageBaseWidget::setImage( const KABC::Picture &photo ) +{ + mImageButton->setPicture( photo ); +} + +KABC::Picture ImageBaseWidget::image() const +{ + return mImageButton->picture(); +} + + +ImageWidget::ImageWidget( KABC::AddressBook *ab, QWidget *parent, const char *name ) + : KAB::ContactEditorWidget( ab, parent, name ) +{ + QHBoxLayout *layout = new QHBoxLayout( this, KDialog::marginHint(), + KDialog::spacingHint() ); + + mPhotoWidget = new ImageBaseWidget( KABC::Addressee::photoLabel(), this ); + layout->addWidget( mPhotoWidget ); + + mLogoWidget = new ImageBaseWidget( KABC::Addressee::logoLabel(), this ); + layout->addWidget( mLogoWidget ); + + connect( mPhotoWidget, SIGNAL( changed() ), SLOT( setModified() ) ); + connect( mLogoWidget, SIGNAL( changed() ), SLOT( setModified() ) ); +} + +void ImageWidget::loadContact( KABC::Addressee *addr ) +{ + mPhotoWidget->setImage( addr->photo() ); + mLogoWidget->setImage( addr->logo() ); +} + +void ImageWidget::storeContact( KABC::Addressee *addr ) +{ + addr->setPhoto( mPhotoWidget->image() ); + addr->setLogo( mLogoWidget->image() ); +} + +void ImageWidget::setReadOnly( bool readOnly ) +{ + mPhotoWidget->setReadOnly( readOnly ); + mLogoWidget->setReadOnly( readOnly ); +} + +#include "imagewidget.moc" diff --git a/kaddressbook/imagewidget.h b/kaddressbook/imagewidget.h new file mode 100644 index 000000000..02a3577c1 --- /dev/null +++ b/kaddressbook/imagewidget.h @@ -0,0 +1,153 @@ +/* + 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 IMAGEWIDGET_H +#define IMAGEWIDGET_H + +#include <qlabel.h> +#include <qpushbutton.h> + +#include <kabc/picture.h> +#include <kdialogbase.h> + +#include "contacteditorwidget.h" + +/** + Small helper class + */ +class ImageLoader : public QObject +{ + Q_OBJECT + + public: + ImageLoader( QWidget *parent ); + + KABC::Picture loadPicture( const KURL &url, bool *ok ); + + private: + KABC::Picture mPicture; + QWidget *mParent; +}; + +/** + Small helper class + */ +class ImageButton : public QPushButton +{ + Q_OBJECT + + public: + ImageButton( const QString &title, QWidget *parent ); + + void setReadOnly( bool readOnly ); + + void setPicture( const KABC::Picture &picture ); + KABC::Picture picture() const; + + void setImageLoader( ImageLoader *loader ); + + signals: + void changed(); + void urlDropped( const KURL& ); + + protected: + virtual void dragEnterEvent( QDragEnterEvent *event ); + virtual void dropEvent( QDropEvent *event ); + virtual void mouseMoveEvent( QMouseEvent *event ); + virtual void mousePressEvent( QMouseEvent *event ); + virtual void contextMenuEvent( QContextMenuEvent *event ); + + private slots: + void load(); + void clear(); + + private: + void startDrag(); + void updateGUI(); + + bool mReadOnly; + QPoint mDragStartPos; + KABC::Picture mPicture; + + ImageLoader *mImageLoader; +}; + + +class ImageBaseWidget : public QWidget +{ + Q_OBJECT + + public: + ImageBaseWidget( const QString &title, QWidget *parent, const char *name = 0 ); + ~ImageBaseWidget(); + + /** + Sets the photo object. + */ + void setImage( const KABC::Picture &photo ); + + /** + Returns a photo object. + */ + KABC::Picture image() const; + + void setReadOnly( bool readOnly ); + + signals: + void changed(); + + private: + ImageButton *mImageButton; + ImageLoader *mImageLoader; + + bool mReadOnly; +}; + +class ImageWidget : public KAB::ContactEditorWidget +{ + public: + ImageWidget( KABC::AddressBook *ab, QWidget *parent, const char *name = 0 ); + + void loadContact( KABC::Addressee *addr ); + void storeContact( KABC::Addressee *addr ); + void setReadOnly( bool readOnly ); + + int logicalWidth() const { return 2; } + + private: + ImageBaseWidget *mPhotoWidget; + ImageBaseWidget *mLogoWidget; +}; + +class ImageWidgetFactory : public KAB::ContactEditorWidgetFactory +{ + public: + KAB::ContactEditorWidget *createWidget( KABC::AddressBook *ab, QWidget *parent, const char *name ) + { + return new ImageWidget( ab, parent, name ); + } + + QString pageIdentifier() const { return "misc"; } +}; + +#endif diff --git a/kaddressbook/imeditwidget.cpp b/kaddressbook/imeditwidget.cpp new file mode 100644 index 000000000..7e663d25f --- /dev/null +++ b/kaddressbook/imeditwidget.cpp @@ -0,0 +1,145 @@ +/* + This file is part of KAddressBook. + Copyright (c) 2002 Mike Pilone <mpilone@slac.com> + + 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 <qlabel.h> +#include <qlayout.h> +#include <qpainter.h> +#include <qpushbutton.h> +#include <qstring.h> +#include <qtoolbutton.h> +#include <qtooltip.h> + +#include <kaccelmanager.h> +#include <kconfig.h> +#include <kcombobox.h> +#include <kdebug.h> +#include <kdialog.h> +#include <kiconloader.h> +#include <klineedit.h> +#include <klocale.h> +#include <kmessagebox.h> + +#include "imeditwidget.h" +#include "imeditorwidget.h" + +IMEditWidget::IMEditWidget( QWidget *parent, KABC::Addressee &addr, const char *name ) + : QWidget( parent, name ), mAddressee(addr) +{ + QGridLayout *topLayout = new QGridLayout( this, 2, 2, KDialog::marginHint(), + KDialog::spacingHint() ); + + QLabel *label = new QLabel( i18n( "IM address:" ), this ); + topLayout->addWidget( label, 0, 0 ); + + mIMEdit = new KLineEdit( this ); + connect( mIMEdit, SIGNAL( textChanged( const QString& ) ), + SLOT( textChanged( const QString& ) ) ); + connect( mIMEdit, SIGNAL( textChanged( const QString& ) ), + SIGNAL( modified() ) ); + label->setBuddy( mIMEdit ); + topLayout->addWidget( mIMEdit, 0, 1 ); + + mEditButton = new QPushButton( i18n( "Edit IM Addresses..." ), this); + connect( mEditButton, SIGNAL( clicked() ), SLOT( edit() ) ); + topLayout->addMultiCellWidget( mEditButton, 1, 1, 0, 1 ); + + topLayout->activate(); +} + +IMEditWidget::~IMEditWidget() +{ +} + +void IMEditWidget::setReadOnly( bool readOnly ) +{ + mIMEdit->setReadOnly( readOnly ); + mReadOnly = readOnly; +// mEditButton->setEnabled( !readOnly ); +} +void IMEditWidget::setPreferredIM( const QString &addr ) +{ + bool blocked = mIMEdit->signalsBlocked(); + mIMEdit->blockSignals( true ); + mIMEdit->setText( addr ); + mIMEdit->blockSignals( blocked ); +} +void IMEditWidget::setIMs( const QStringList &list ) +{ + mIMList = list; + + bool blocked = mIMEdit->signalsBlocked(); + mIMEdit->blockSignals( true ); + if ( list.count() > 0 ) + mIMEdit->setText( list[ 0 ] ); + else + mIMEdit->setText( "" ); + mIMEdit->blockSignals( blocked ); +} + +QStringList IMEditWidget::ims() +{ + if ( mIMEdit->text().isEmpty() ) { + if ( mIMList.count() > 0 ) + mIMList.remove( mIMList.begin() ); + } else { + if ( mIMList.count() > 0 ) + mIMList.remove( mIMList.begin() ); + + mIMList.prepend( mIMEdit->text() ); + } + + return mIMList; +} +QString IMEditWidget::preferredIM() +{ + return mIMEdit->text(); +} +void IMEditWidget::edit() +{ + IMEditorWidget dlg(this, mIMEdit->text()); + dlg.loadContact(&mAddressee); + dlg.setReadOnly(mReadOnly); + + if ( dlg.exec() ) { + if ( dlg.isModified() ) { + //Stores the changes into mAddressee. mAddressee isn't actually saved to the addressbook + //until we save the record. + dlg.storeContact(&mAddressee); + mIMEdit->setText( dlg.preferred() ); + emit modified(); + } + } +} + +void IMEditWidget::textChanged( const QString &text ) +{ + if ( mIMList.count() > 0 ) + mIMList.remove( mIMList.begin() ); + + mIMList.prepend( text ); +} + + +#include "imeditwidget.moc" + diff --git a/kaddressbook/imeditwidget.h b/kaddressbook/imeditwidget.h new file mode 100644 index 000000000..8a20b9b2d --- /dev/null +++ b/kaddressbook/imeditwidget.h @@ -0,0 +1,75 @@ +/* + This file is part of KAddressBook. + Copyright (c) 2002 Mike Pilone <mpilone@slac.com> + + 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 IMEDITWIDGET_H +#define IMEDITWIDGET_H + +#include <kabc/addressee.h> +#include <kdialogbase.h> + +class QButtonGroup; +class QCheckBox; +class QListView; +class QTextEdit; +class QToolButton; + +class KComboBox; +class KLineEdit; +class KListView; + +/** + This widget displays a list box of the instant messaging addresses as well as buttons + to manipulate them (up, down, add, remove). +*/ +class IMEditWidget : public QWidget +{ + Q_OBJECT + + public: + IMEditWidget(QWidget *parent, KABC::Addressee &addr, const char *name = 0 ); + ~IMEditWidget(); + + void setIMs( const QStringList &list ); + QStringList ims(); + + void setPreferredIM( const QString &addr ); + QString preferredIM(); + void setReadOnly( bool readOnly ); + + signals: + void modified(); + + private slots: + void edit(); + void textChanged( const QString& ); + + private: + KLineEdit *mIMEdit; + QPushButton *mEditButton; + QStringList mIMList; + bool mReadOnly; + KABC::Addressee &mAddressee; +}; + + +#endif diff --git a/kaddressbook/incsearchwidget.cpp b/kaddressbook/incsearchwidget.cpp new file mode 100644 index 000000000..e435d100f --- /dev/null +++ b/kaddressbook/incsearchwidget.cpp @@ -0,0 +1,171 @@ +/* + This file is part of KAddressBook. + Copyright (c) 2002 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 <qapplication.h> +#include <qcombobox.h> +#include <qlabel.h> +#include <qlayout.h> +#include <qtimer.h> +#include <qtoolbutton.h> +#include <qtooltip.h> +#include <qwhatsthis.h> + +#include <kdialog.h> +#include <kiconloader.h> +#include <klineedit.h> +#include <klocale.h> + +#include "incsearchwidget.h" + +IncSearchWidget::IncSearchWidget( QWidget *parent, const char *name ) + : QWidget( parent, name ) +{ + QHBoxLayout *layout = new QHBoxLayout( this, 2, KDialog::spacingHint() ); + + QToolButton *button = new QToolButton( this ); + button->setSizePolicy( QSizePolicy::Minimum, QSizePolicy::Minimum ); + button->setPixmap( SmallIcon( QApplication::reverseLayout() ? "clear_left" : "locationbar_erase" ) ); + button->setAccel( QKeySequence( CTRL+ALT+Key_S ) ); + button->setAutoRaise( true ); + QToolTip::add( button, i18n( "Reset" ) ); + layout->addWidget( button ); + + QLabel *label = new QLabel( i18n( "Search:" ), this, "kde toolbar widget" ); + label->setAlignment( QLabel::AlignVCenter | QLabel::AlignRight ); + layout->addWidget( label ); + + mSearchText = new KLineEdit( this ); + mSearchText->setSizePolicy( QSizePolicy::MinimumExpanding, QSizePolicy::Preferred ); + QWhatsThis::add( mSearchText, i18n( "The incremental search<p>Enter some text here will start the search for the contact, which matches the search pattern best. The part of the contact, which will be used for matching, depends on the field selection." ) ); + label->setBuddy( mSearchText ); + layout->addWidget( mSearchText ); + + label = new QLabel( i18n( "as in 'Search in:'", "&in:" ), this, "kde toolbar widget" ); + label->setAlignment( QLabel::AlignVCenter | QLabel::AlignRight ); + layout->addWidget( label ); + + mFieldCombo = new QComboBox( false, this ); + layout->addWidget( mFieldCombo ); + label->setBuddy(mFieldCombo); + + QToolTip::add( mFieldCombo, i18n( "Select incremental search field" ) ); + QWhatsThis::add( mFieldCombo, i18n( "Here you can choose the field, which shall be used for incremental search." ) ); + + mInputTimer = new QTimer( this ); + + connect( mInputTimer, SIGNAL( timeout() ), + SLOT( timeout() ) ); + connect( mSearchText, SIGNAL( textChanged( const QString& ) ), + SLOT( announceDoSearch() ) ); + connect( mSearchText, SIGNAL( returnPressed() ), + SLOT( announceDoSearch() ) ); + connect( mFieldCombo, SIGNAL( activated( const QString& ) ), + SLOT( announceDoSearch() ) ); + connect( button, SIGNAL( clicked() ), + mSearchText, SLOT( clear() ) ); + connect( button, SIGNAL( clicked() ), + SLOT( announceDoSearch() ) ); + + initFields(); + + mSearchText->installEventFilter( this ); + + setFocusProxy( mSearchText ); +} + +IncSearchWidget::~IncSearchWidget() +{ +} + +void IncSearchWidget::announceDoSearch() +{ + if ( mInputTimer->isActive() ) + mInputTimer->stop(); + + mInputTimer->start( 0, true ); +} + +void IncSearchWidget::timeout() +{ + emit doSearch( mSearchText->text() ); +} + +void IncSearchWidget::initFields() +{ + mFieldList = KABC::Field::allFields(); + + mFieldCombo->clear(); + mFieldCombo->insertItem( i18n( "Visible Fields" ) ); + mFieldCombo->insertItem( i18n( "All Fields" ) ); + + KABC::Field::List::ConstIterator it; + for ( it = mFieldList.begin(); it != mFieldList.end(); ++it ) + mFieldCombo->insertItem( (*it)->label() ); + + announceDoSearch(); +} + +KABC::Field::List IncSearchWidget::currentFields() const +{ + KABC::Field::List fieldList; + + if ( mFieldCombo->currentItem() == 0 ) + fieldList = mViewFields; + else if ( mFieldCombo->currentItem() > 1 ) + fieldList.append( mFieldList[ mFieldCombo->currentItem() - 2 ] ); + + return fieldList; +} + +void IncSearchWidget::setCurrentItem( int pos ) +{ + mFieldCombo->setCurrentItem( pos ); +} + +int IncSearchWidget::currentItem() const +{ + return mFieldCombo->currentItem(); +} + +void IncSearchWidget::setViewFields( const KABC::Field::List &fields ) +{ + mViewFields = fields; +} + +void IncSearchWidget::clear() +{ + mSearchText->clear(); +} + +void IncSearchWidget::keyPressEvent( QKeyEvent *event ) +{ + if ( event->key() == Qt::Key_Up ) { + event->accept(); + emit scrollUp(); + } else if ( event->key() == Qt::Key_Down ) { + event->accept(); + emit scrollDown(); + } +} + +#include "incsearchwidget.moc" diff --git a/kaddressbook/incsearchwidget.h b/kaddressbook/incsearchwidget.h new file mode 100644 index 000000000..c4eb1936f --- /dev/null +++ b/kaddressbook/incsearchwidget.h @@ -0,0 +1,88 @@ +/* + This file is part of KAddressBook. + Copyright (c) 2002 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 INCSEARCHWIDGET_H +#define INCSEARCHWIDGET_H + +#include <qwidget.h> + +#include <kabc/field.h> + +class QComboBox; +class QTimer; +class KLineEdit; + +class IncSearchWidget : public QWidget +{ + Q_OBJECT + + public: + IncSearchWidget( QWidget *parent, const char *name = 0 ); + ~IncSearchWidget(); + + KABC::Field::List currentFields() const; + + void setCurrentItem( int pos ); + int currentItem() const; + + void clear(); + + signals: + /** + This signal is emitted whenever the text in the input + widget is changed. You can get the sorting field by + @ref currentField. + */ + void doSearch( const QString& text ); + + /** + Emitted when the up key is pressed. + */ + void scrollUp(); + + /** + Emitted when the down key is pressed. + */ + void scrollDown(); + + public slots: + void setViewFields( const KABC::Field::List& ); + + private slots: + void announceDoSearch(); + void timeout(); + + protected: + virtual void keyPressEvent( QKeyEvent* ); + + private: + void initFields(); + + QComboBox* mFieldCombo; + KLineEdit* mSearchText; + KABC::Field::List mFieldList; + KABC::Field::List mViewFields; + QTimer* mInputTimer; +}; + +#endif diff --git a/kaddressbook/interfaces/Makefile.am b/kaddressbook/interfaces/Makefile.am new file mode 100644 index 000000000..7b4373643 --- /dev/null +++ b/kaddressbook/interfaces/Makefile.am @@ -0,0 +1,18 @@ +INCLUDES = -I$(top_srcdir) $(all_includes) + +lib_LTLIBRARIES = libkabinterfaces.la + +libkabinterfaces_la_SOURCES = configurewidget.cpp contacteditorwidget.cpp \ + core.cpp extensionwidget.cpp xxport.cpp +libkabinterfaces_la_LDFLAGS = $(all_libraries) -version-info 1:0:0 -no-undefined +libkabinterfaces_la_LIBADD = $(LIB_KABC) + +kabincludedir = $(includedir)/kaddressbook +kabinclude_HEADERS = configurewidget.h contacteditorwidget.h core.h \ + extensionwidget.h xxport.h + +METASOURCES = AUTO + +servicetypedir = $(kde_servicetypesdir) +servicetype_DATA = kaddressbook_contacteditorwidget.desktop \ + kaddressbook_extension.desktop kaddressbook_xxport.desktop diff --git a/kaddressbook/interfaces/configurewidget.cpp b/kaddressbook/interfaces/configurewidget.cpp new file mode 100644 index 000000000..518a29538 --- /dev/null +++ b/kaddressbook/interfaces/configurewidget.cpp @@ -0,0 +1,53 @@ +/* + This file is part of KAddressBook. + Copyright (c) 2002 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 <kabc/addressbook.h> + +#include "configurewidget.h" + +using namespace KAB; + +ConfigureWidget::ConfigureWidget( KABC::AddressBook *ab, QWidget *parent, + const char *name ) + : QWidget( parent, name ), mAddressBook( ab ) +{ +} + +ConfigureWidget::~ConfigureWidget() +{ +} + +void ConfigureWidget::restoreSettings( KConfig* ) +{ + // should be reimplemented in the views, extensions etc. +} + +void ConfigureWidget::saveSettings( KConfig* ) +{ + // should be reimplemented in the views, extensions etc. +} + +KABC::AddressBook *ConfigureWidget::addressBook() const +{ + return mAddressBook; +} diff --git a/kaddressbook/interfaces/configurewidget.h b/kaddressbook/interfaces/configurewidget.h new file mode 100644 index 000000000..601adce97 --- /dev/null +++ b/kaddressbook/interfaces/configurewidget.h @@ -0,0 +1,72 @@ +/* + This file is part of KAddressBook. + Copyright (c) 2002 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 KAB_CONFIGUREWIDGET_H +#define KAB_CONFIGUREWIDGET_H + +#include <qwidget.h> + +#include <kconfig.h> +#include <kdepimmacros.h> + +namespace KABC { +class AddressBook; +} + +namespace KAB { + +class KDE_EXPORT ConfigureWidget : public QWidget +{ + public: + ConfigureWidget( KABC::AddressBook *ab, QWidget *parent, const char *name = 0 ); + ~ConfigureWidget(); + + /** + This method is called before the configure dialog is shown. + The widget should reimplement it and fill the GUI with the + values from the config file. + Important: Don't change the group of cfg! + */ + virtual void restoreSettings( KConfig *cfg ); + + /** + This method is called after the user clicked the 'Ok' button. + The widget should reimplement it and save all values from + the GUI to the config file. + Important: Don't change the group of cfg! + */ + virtual void saveSettings( KConfig *cfg ); + + + /** + Returns a pointer to the address book of this widget. + */ + KABC::AddressBook *addressBook() const; + + private: + KABC::AddressBook *mAddressBook; +}; + +} + +#endif diff --git a/kaddressbook/interfaces/contacteditorwidget.cpp b/kaddressbook/interfaces/contacteditorwidget.cpp new file mode 100644 index 000000000..366087c62 --- /dev/null +++ b/kaddressbook/interfaces/contacteditorwidget.cpp @@ -0,0 +1,60 @@ +/* + 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 "contacteditorwidget.h" + +using namespace KAB; + +ContactEditorWidget::ContactEditorWidget( KABC::AddressBook *ab, + QWidget *parent, const char *name ) + : QWidget( parent, name ), mAddressBook( ab ), mModified( false ) +{ +} + +ContactEditorWidget::~ContactEditorWidget() +{ +} + +KABC::AddressBook *ContactEditorWidget::addressBook() const +{ + return mAddressBook; +} + +bool ContactEditorWidget::modified() const +{ + return mModified; +} + +void ContactEditorWidget::setModified() +{ + setModified( true ); +} + +void ContactEditorWidget::setModified( bool modified ) +{ + mModified = modified; + if ( modified ) + emit changed(); +} + +#include "contacteditorwidget.moc" diff --git a/kaddressbook/interfaces/contacteditorwidget.h b/kaddressbook/interfaces/contacteditorwidget.h new file mode 100644 index 000000000..4b80b44f4 --- /dev/null +++ b/kaddressbook/interfaces/contacteditorwidget.h @@ -0,0 +1,143 @@ +/* + This file is part of KAddressbook. + Copyright (c) 2004 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 KAB_CONTACTEDITORWIDGET_H +#define KAB_CONTACTEDITORWIDGET_H + +#include <qwidget.h> + +#include <kabc/addressbook.h> +#include <klibloader.h> +#include <kdepimmacros.h> + +#define KAB_CEW_PLUGIN_VERSION 1 + +namespace KAB { + +class KDE_EXPORT ContactEditorWidget : public QWidget +{ + Q_OBJECT + + public: + typedef QValueList<ContactEditorWidget*> List; + + ContactEditorWidget( KABC::AddressBook *ab, QWidget *parent, const char *name = 0 ); + ~ContactEditorWidget(); + + /** + Return logical height of the widget. This is used to calculate how + much vertical space relative to other widgets this widget will use + in the summary view. + */ + virtual int logicalHeight() const { return 1; } + + /** + Return logical wide of the widget. This is used to calculate how + much horizontal space relative to other widgets this widget will use + in the summary view. + */ + virtual int logicalWidth() const { return 1; } + + /** + Load the contacts data into the GUI. + */ + virtual void loadContact( KABC::Addressee *addr ) = 0; + + /** + Save the data from the GUI into the passed contact + object. + */ + virtual void storeContact( KABC::Addressee *addr ) = 0; + + /** + Sets whether the contact should be presented as + read-only. You should update your GUI in the reimplemented + method. + */ + virtual void setReadOnly( bool readOnly ) = 0; + + /** + Returns whether this widget was modified. + */ + bool modified() const; + + signals: + /** + Emitted whenever the page has changed, do not emit it directly, + use setModified() instead. + */ + void changed(); + + public slots: + /** + Call this slot whenever the data were changed by the user. It + will emit the changed() signal and set the modified property. + + @param modified Set whether the widget was modified. + */ + void setModified( bool modified ); + + void setModified(); + + protected: + /** + Returns a pointer to the address book object. + */ + KABC::AddressBook *addressBook() const; + + private: + KABC::AddressBook *mAddressBook; + bool mModified; + + class ContactEditorWidgetPrivate; + ContactEditorWidgetPrivate *d; +}; + +class ContactEditorWidgetFactory : public KLibFactory +{ + public: + virtual ContactEditorWidget *createWidget( KABC::AddressBook *ab, QWidget *parent, + const char *name = 0 ) = 0; + + /** + Returns the i18ned title of this tab page. + */ + virtual QString pageTitle() const { return ""; } + + /** + Returns the identifier of the tab page where the widget + shall belong to. + */ + virtual QString pageIdentifier() const = 0; + + protected: + virtual QObject* createObject( QObject*, const char*, const char*, + const QStringList & ) + { + return 0; + } +}; + +} + +#endif diff --git a/kaddressbook/interfaces/core.cpp b/kaddressbook/interfaces/core.cpp new file mode 100644 index 000000000..6c8e10910 --- /dev/null +++ b/kaddressbook/interfaces/core.cpp @@ -0,0 +1,33 @@ +/* + 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 "core.h" + +using namespace KAB; + +Core::Core( KXMLGUIClient *client, QObject *parent, const char *name ) + : QObject( parent, name ), mGUIClient( client ) +{ +} + +#include "core.moc" diff --git a/kaddressbook/interfaces/core.h b/kaddressbook/interfaces/core.h new file mode 100644 index 000000000..276b20d61 --- /dev/null +++ b/kaddressbook/interfaces/core.h @@ -0,0 +1,203 @@ +/* + 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 KAB_CORE_H +#define KAB_CORE_H + +#include <config.h> // for KDEPIM_NEW_DISTRLISTS + +#ifdef KDEPIM_NEW_DISTRLISTS +#include <libkdepim/distributionlist.h> +#endif + +#include <qobject.h> + +#include <kabc/field.h> +#include <kcommand.h> +#include <kxmlguiclient.h> +#include <kdepimmacros.h> + +namespace KABC { +class AddressBook; +class Resource; +} + +class QWidget; + +class KActionCollection; +class KConfig; +class KURL; + +namespace KAB { + +class SearchManager; + +class KDE_EXPORT Core : public QObject +{ + Q_OBJECT + + public: + Core( KXMLGUIClient *client, QObject *parent, const char *name = 0 ); + + /** + Returns a pointer to the StdAddressBook of the application. + */ + virtual KABC::AddressBook *addressBook() const = 0; + + /** + Returns a pointer to the KConfig object of the application. + */ + virtual KConfig *config() const = 0; + + /** + Returns a pointer to the global KActionCollection object. So + other classes can register their actions easily. + */ + virtual KActionCollection *actionCollection() const = 0; + + /** + Returns a pointer to the gui client. + */ + virtual KXMLGUIClient *guiClient() const { return mGUIClient; } + + /** + Returns the current sort field. + */ + virtual KABC::Field *currentSortField() const = 0; + + /** + Returns the uid list of the currently selected contacts. + */ + virtual QStringList selectedUIDs() const = 0; + + /** + Displays a ResourceSelectDialog and returns the selected + resource or a null pointer if no resource was selected by + the user. + */ + virtual KABC::Resource *requestResource( QWidget *parent ) = 0; + + /** + Returns the parent widget. + */ + virtual QWidget *widget() const = 0; + + /** + Deletes given contacts from the address book. + + @param uids The uids of the contacts, which shall be deleted. + */ + virtual void deleteContacts( const QStringList &uids ) = 0; + + /** + Deletes given contacts from the address book. + + @param uids The uids of the contacts, which shall be deleted. + */ + virtual void deleteDistributionLists( const QStringList &uids ) = 0; + +#ifdef KDEPIM_NEW_DISTRLISTS + /** + Returns all the distribution lists. + */ + virtual KPIM::DistributionList::List distributionLists() const = 0; + + + /** + Returns the name of all the distribution lists. + */ + virtual QStringList distributionListNames() const = 0; + + /** + sets the distribution list to display. If null, the regular + address book is to be displayed. + */ + virtual void setSelectedDistributionList( const QString &name ) = 0; +#endif + + //// This class isn't part of interfaces/, so this method here isn't really useful + virtual SearchManager *searchManager() const = 0; + + virtual KCommandHistory *commandHistory() const = 0; + + signals: + /** + Forwarded from SearchManager + After it is emitted, distributionListNames() might have a different result. + */ + void contactsUpdated(); + + public slots: + /** + Is called whenever a contact is selected in the view. + */ + virtual void setContactSelected( const QString &uid ) = 0; + + /** + DCOP METHOD: Adds the given email address to address book. + */ + virtual void addEmail( const QString& addr ) = 0; + + /** + DCOP METHOD: Imports the vCard, located at the given url. + */ + virtual void importVCard( const KURL& url ) = 0; + + /** + DCOP METHOD: Imports the given vCard. + */ + virtual void importVCardFromData( const QString& vCard ) = 0; + + /** + DCOP METHOD: Opens contact editor to input a new contact. + */ + virtual void newContact() = 0; + + /** + DCOP METHOD: Opens distribution list editor to input a new distribution list. + */ + virtual void newDistributionList() = 0; + + /** + DCOP METHOD: Returns the name of the contact, that matches the given + phone number. + */ + virtual QString getNameByPhone( const QString& phone ) = 0; + + /** + Shows an edit dialog for the given uid. + */ + virtual void editContact( const QString &uid = QString::null ) = 0; + + /** + Shows an edit dialog for the given distribution list + */ + virtual void editDistributionList( const QString &name ) = 0; + + private: + KXMLGUIClient *mGUIClient; +}; + +} + +#endif diff --git a/kaddressbook/interfaces/extensionwidget.cpp b/kaddressbook/interfaces/extensionwidget.cpp new file mode 100644 index 000000000..b70291583 --- /dev/null +++ b/kaddressbook/interfaces/extensionwidget.cpp @@ -0,0 +1,68 @@ +/* + This file is part of KAddressBook. + Copyright (c) 2002 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 "core.h" + +#include "extensionwidget.h" + +using namespace KAB; + +ExtensionWidget::ExtensionWidget( Core *core, QWidget *parent, + const char *name ) + : QWidget( parent, name ), mCore( core ) +{ +} + +ExtensionWidget::~ExtensionWidget() +{ +} + +KAB::Core *ExtensionWidget::core() const +{ + return mCore; +} + +bool ExtensionWidget::contactsSelected() const +{ + return mCore->selectedUIDs().count() != 0; +} + +KABC::Addressee::List ExtensionWidget::selectedContacts() +{ + KABC::Addressee::List list; + + const QStringList uids = mCore->selectedUIDs(); + QStringList::ConstIterator it; + const QStringList::ConstIterator endIt = uids.end(); + for ( it = uids.begin(); it != endIt; ++it ) + list.append( mCore->addressBook()->findByUid( *it ) ); + + return list; +} + +void ExtensionWidget::contactsSelectionChanged() +{ + // do nothing +} + +#include "extensionwidget.moc" diff --git a/kaddressbook/interfaces/extensionwidget.h b/kaddressbook/interfaces/extensionwidget.h new file mode 100644 index 000000000..076defad2 --- /dev/null +++ b/kaddressbook/interfaces/extensionwidget.h @@ -0,0 +1,120 @@ +/* + This file is part of KAddressBook. + Copyright (c) 2002 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 KAB_EXTENSIONWIDGET_H +#define KAB_EXTENSIONWIDGET_H + +#include <qwidget.h> + +#include <kabc/addressbook.h> +#include <klibloader.h> +#include <kdepimmacros.h> + +#define KAB_EXTENSIONWIDGET_PLUGIN_VERSION 1 + +namespace KAB { +class Core; +class ConfigureWidget; + +class KDE_EXPORT ExtensionWidget : public QWidget +{ + Q_OBJECT + + public: + ExtensionWidget( Core *core, QWidget *parent, const char *name = 0 ); + ~ExtensionWidget(); + + /** + @return A pointer to the core object + */ + KAB::Core *core() const; + + /** + Returns whether there are selected contacts in the view. + */ + bool contactsSelected() const; + + /** + Returns a list of contacts that are selected in the view. + Use @ref addresseesSelected() to test if there exists selected + contacts. + */ + KABC::Addressee::List selectedContacts(); + + /** + This method is called whenever the selection in the view changed. + */ + virtual void contactsSelectionChanged(); + + /** + This method should be reimplemented and return the i18ned title of this + widget. + */ + virtual QString title() const = 0; + + /** + This method should be reimplemented and return a unique identifier. + */ + virtual QString identifier() const = 0; + + signals: + void modified( const KABC::Addressee::List &list ); + void deleted( const QStringList& uidList ); + + private: + KAB::Core *mCore; + + class ExtensionWidgetPrivate; + ExtensionWidgetPrivate *d; +}; + +class ExtensionFactory : public KLibFactory +{ + public: + virtual ExtensionWidget *extension( KAB::Core *core, QWidget *parent, + const char *name = 0 ) = 0; + + virtual ConfigureWidget *configureWidget( QWidget*, const char* = 0 ) + { + return 0; + } + + virtual bool configureWidgetAvailable() { return false; } + + /** + This method should return the same identifier like the config + widget. + */ + virtual QString identifier() const = 0; + + protected: + virtual QObject* createObject( QObject*, const char*, const char*, + const QStringList & ) + { + return 0; + } +}; + +} + +#endif diff --git a/kaddressbook/interfaces/kaddressbook_contacteditorwidget.desktop b/kaddressbook/interfaces/kaddressbook_contacteditorwidget.desktop new file mode 100644 index 000000000..bb646e78c --- /dev/null +++ b/kaddressbook/interfaces/kaddressbook_contacteditorwidget.desktop @@ -0,0 +1,55 @@ +[Desktop Entry] +Type=ServiceType +X-KDE-ServiceType=KAddressBook/ContactEditorWidget +Comment=KAddressBook Contact Editor Widget Plugin +Comment[af]=KAddressBook kontak redigeerder inprop module +Comment[bg]=Приставка за редактиране на контактите от адресника +Comment[bs]=KAddressBook dodatak za prozor za izmjenu kontakta +Comment[ca]=Endollable de l'estri editor de contactes de la llibreta d'adreces +Comment[cs]=Modul widgetu editoru kontaktů KAddressBook +Comment[da]=KAddressBook plugin til kontakteditorkontrol +Comment[de]=Adressbuch Kontakteditor-Modul +Comment[el]=Πρόσθετο επεξεργασίας επαφής του KAddressBook +Comment[eo]=Kromaĵo por KAddressBook Kontaktredaktila Fenestraĵo +Comment[es]=Accesorio de elemento de editor de contactos para KAddressBook +Comment[et]=KDE aadressiraamatu kontaktide redigeerimise plugin +Comment[eu]=KAddressBook-en kontaktu editore trepetaren plugin-a +Comment[fa]=وصلۀ عنصر ویرایشگر تماس KAddressBook +Comment[fi]=Osoitekirjan yhteystietojen muokkainliitännäinen +Comment[fr]=Module d'édition de contacts de KAddressBook +Comment[fy]=KAddressBook Kontaktbewurker-plugin +Comment[gl]=Extensión Editor de Contactos para KAddressBook +Comment[he]=תוסף תצוגה עבור עורך אנשי קשר של פנקס הכתובות +Comment[hu]=KAddressBook névjegyszerkesztő bővítőmodul +Comment[is]=KAddressbook tengiliðaritils íforrit +Comment[it]=Plugin editor dei contatti di KAddressbook +Comment[ja]=KAddressbook 連絡先エディタ ウィジェット プラグイン +Comment[ka]= KDE-ს წიგნაკის კონტაქტთა რედაქტირების ელემენტის მოდული +Comment[kk]=Адрестік кітапшаның контактты өңдеу модулі +Comment[km]=កម្មវិធីជំនួយធាតុក្រាហ្វិកកម្មវិធីនិពន្ធទំនាក់ទំនងរបស់ KAddressBook +Comment[lt]=KAddressBook kontaktų redaktoriaus valdiklių priedas +Comment[mk]=Приклучок за уредување контакти во КАдресар +Comment[ms]=Plugin Widget Editor Orang Hubungan KAddressBook +Comment[nb]=KAddressbook programtillegg for kontakt redigeringselement +Comment[nds]=Editormoduul för KAdressbook-Kontakten +Comment[ne]=केडीई ठेगाना पुस्तिका सम्पर्क सम्पादक विजेट प्लगइन +Comment[nl]=KAddressBook Contacteditor-plugin +Comment[nn]=Programtillegg for kontaktredigering i KDE-adresseboka +Comment[pl]=Wtyczka okna edycji wizytówki dla KAddressBook +Comment[pt]='Plugin' de Edição de 'Widgets' de Contacto do KAddressbook +Comment[pt_BR]=Plug-in do Editor de Contatos do KAddressBook +Comment[ru]=Редактор контакта адресной книги KDE +Comment[sk]=KAddressBook modul pre editor kontaktov +Comment[sl]=Vstavek gradnika urejevalnika stikov za Adresar +Comment[sr]=KAddressBook прикључак контроле едитора контаката +Comment[sr@Latn]=KAddressBook priključak kontrole editora kontakata +Comment[sv]=Kadressbok-insticksprogram för kontakteditor +Comment[ta]=கேமுகவரிபுத்தகம் தொடர்பு தொகுப்பான் சாளர சொருகுப்பொருள் +Comment[tg]=Муҳаррири алоқоти китоби адресии KDE +Comment[tr]=Adres Defteri Kişi Düzenleyici Parçacık Eklentisi +Comment[uk]=Втулок редагування контактів адресної книги +Comment[zh_CN]=KAddressBook 联系人编辑部件插件 +Comment[zh_TW]=KAddressBook 聯絡人編輯器外掛程式 + +[PropertyDef::X-KDE-KAddressBook-CEWPluginVersion] +Type=int diff --git a/kaddressbook/interfaces/kaddressbook_extension.desktop b/kaddressbook/interfaces/kaddressbook_extension.desktop new file mode 100644 index 000000000..55be3b71e --- /dev/null +++ b/kaddressbook/interfaces/kaddressbook_extension.desktop @@ -0,0 +1,59 @@ +[Desktop Entry] +Type=ServiceType +X-KDE-ServiceType=KAddressBook/Extension +Comment=KAddressBook Extension Plugin +Comment[af]=KAddressBook uitbrei inprop module +Comment[be]=Дапаўненне K Адраснай кнігі "Пашырэнне" +Comment[bg]=Приставка-разширение за адресника +Comment[bs]=KAddressBook dodatak proširenja +Comment[ca]=Endollable Extension per al KAddressBook +Comment[cs]=Rozšiřující modul pro Knihu adres +Comment[cy]=Ategyn Estyniad KLlyfrCyfeiriadau +Comment[da]=KAddressBook udvidelsesplugin +Comment[de]=Erweiterungsmodul für Adressbuch +Comment[el]=Πρόσθετο επέκτασης του KAddressBook +Comment[eo]=KAddressBook Etendiga Kromaĵo +Comment[es]=Plugin de extensión de KAddressBook +Comment[et]=KDE aadressiraamatu laiendi plugin +Comment[eu]=KAddressBook-en luzapen plugin-a +Comment[fa]=وصلۀ پسوند KAddressBook +Comment[fi]=KAddressbookin laajennusliitännäinen +Comment[fr]=Module d'extension pour KAddressBook +Comment[fy]=KAddressBook taheaksel plugin +Comment[gl]=Engadido de Extensión para KAddressBook +Comment[he]=תוסף הרחבה עבור פנקס הכתובות +Comment[hi]=के-एड्रेस-बुक विस्तार प्लगइन +Comment[hu]=KAddressBook kiegészítő modul +Comment[is]=KAddressbook viðbótar íforrit +Comment[it]=Plugin estensione di KAddressbook +Comment[ja]=KAddressbook 拡張プラグイン +Comment[ka]=KDE წიგნაკის გაფართოების მოდული +Comment[kk]=KAddressBook кеңейту модулі +Comment[km]=កម្មវិធីជំនួយផ្នែកបន្ថែមរបស់ KAddressBook +Comment[lt]=KAddressBook praplėtimo priedas +Comment[mk]=Приклучок за екстензии во КАдресар +Comment[ms]=Plug masuk Sambungan KAddressBook +Comment[nb]=KAddressbook-programtillegg for utvidelser +Comment[nds]=Verwiedernmodüul för KAdressbook +Comment[ne]=केडीई ठेगाना पुस्तिका विस्तार प्लगइन +Comment[nl]=KAddressBook Extensie Plugin +Comment[nn]=Programtillegg for utviding av KDE-adresseboka +Comment[pl]=Wtyczka rozszerzenia dla KAddressBook +Comment[pt]='Plugin' de Extensão do KAddressbook +Comment[pt_BR]=Plug-in de Extensão do KAddressBook +Comment[ro]=Modul de extensie KAddressBook +Comment[ru]=Расширение адресной книги KDE +Comment[sk]=KAddressBook plugin rozšírení +Comment[sl]=Razširitveni vstavek za Adresar +Comment[sr]=Прикључак KAddressBook-а за проширења +Comment[sr@Latn]=Priključak KAddressBook-a za proširenja +Comment[sv]=Kadressbok-utökningsinsticksprogram +Comment[ta]=கேமுகவரிப்புத்தகம் விரிவாக்க சொருகுப்பொருள் +Comment[tg]=Модули вусъатоти китоби адресии KDE +Comment[tr]=KAdresDefteri Uzantı Eklentisi +Comment[uk]=Втулок розширення адресної книги KAddressBook +Comment[zh_CN]=KAddressBook 扩展插件 +Comment[zh_TW]=KAddressBook 延伸外掛程式 + +[PropertyDef::X-KDE-KAddressBook-ExtensionPluginVersion] +Type=int diff --git a/kaddressbook/interfaces/kaddressbook_xxport.desktop b/kaddressbook/interfaces/kaddressbook_xxport.desktop new file mode 100644 index 000000000..fb2b03d0d --- /dev/null +++ b/kaddressbook/interfaces/kaddressbook_xxport.desktop @@ -0,0 +1,62 @@ +[Desktop Entry] +Type=ServiceType +X-KDE-ServiceType=KAddressBook/XXPort +Comment=KAddressBook Import/Export Plugin +Comment[af]=KAddressBook Invoer/Uitvoer inprop module +Comment[be]=Дапаўненне K Адраснай кнігі "Імпарт/Экспарт" +Comment[bg]=Приставка за импортиране/експортиране на данни от адресника +Comment[br]=Lugent enporzh/ezporzh evit KAddressBook +Comment[bs]=KAddressBook dodatak za uvoz/izvoz +Comment[ca]=Endollable d'importació/exportació per a la llibreta d'adreces +Comment[cs]=Modul knihy adres pro import/export +Comment[cy]=Ategyn Mewnforio/Allforio KLlyfrCyfeiriadau +Comment[da]=KAddressBook Import/Eksport-plugin +Comment[de]=Import/Export-Modul für Adressbuch +Comment[el]=Πρόσθετο εισαγωγής/εξαγωγής του KAddressBook +Comment[eo]=KAddressBook Import-/Eksport-Kromaĵo +Comment[es]=Plugin para importar/exportar en KAddressBook +Comment[et]=KDE aadressiraamatu import/eksportplugin +Comment[eu]=KAddressBook-en inportazio/esportazio plugin-a +Comment[fa]=وصلۀ صادرات/واردات KAddressBook +Comment[fi]=KAddressbookin tuonti/vienti-liitännäinen +Comment[fr]=Module d'import / export pour KAddressBook +Comment[fy]=KAddressBook Ymport/Eksport Plugin +Comment[gl]=Extensión de Importación/Exportación para KAddressBook +Comment[he]=תוסף ייבוא/יצוא עבור פנקס הכתובות +Comment[hi]=के-एड्रेस-बुक आयात/निर्यात प्लगइन +Comment[hu]=KAddressBook importálási/exportálási bővítőmodul +Comment[is]=KAddressbook flytja inn/út íforrit +Comment[it]=Plugin importa/esporta di KAddressbook +Comment[ja]=KAddressbook インポート/エクスポートプラグイン +Comment[ka]=წიგნაკის იმპორტ/ექსპორტის მოდული +Comment[kk]=KAddressBook импорт/экспорт модулі +Comment[km]=កម្មវិធីជំនួយនាំចូល/នាំចេញរបស់ KAddressBook +Comment[lt]=KAddressBook importo/eksporto priedas +Comment[mk]=Приклучок за внесување/изнесување во КАдресар +Comment[ms]=Plug masuk Import Eksport KAddressBook +Comment[nb]=KAddressbook-programtillegg for import/eksport +Comment[nds]=Import-/Exportmoduul för KAdressbook +Comment[ne]=केडीई ठेगाना पुस्तिका आयात/निर्यात प्लगइन +Comment[nn]=Programtillegg for importering/ekportering i KDE-adresseboka +Comment[pl]=Wtyczka importu/eksportu dla KAddressBook +Comment[pt]='Plugin' de Importação/Exportação do KAddressbook +Comment[pt_BR]=Plug-in de Importação/Exportação do KAddressBook +Comment[ro]=Modul de import/export pentru KAddressBook +Comment[ru]=Экспорт и импорт адресной книги +Comment[sk]=KAddressBook import/export plugin +Comment[sl]=Vstavek za uvoz in izvoz iz Adresarja +Comment[sr]=Прикључак KAddressBook-а за увоз/извоз +Comment[sr@Latn]=Priključak KAddressBook-a za uvoz/izvoz +Comment[sv]=Kadressbok-insticksprogram för import/export +Comment[ta]=கேமுகவரிப்புத்தகம் ஏற்றுமதி/இறக்குமதி சொருகுப்பொருள் +Comment[tg]=Содирот ва воридоти китоби адрес +Comment[tr]=KAdresDefteri Al/Gönder Eklentisi +Comment[uk]=Втулок імпорту/експорту адресної книги KAddressBook +Comment[uz]=Manzillar daftari uchun import/eksport plagini +Comment[uz@cyrillic]=Манзиллар дафтари учун импорт/экспорт плагини +Comment[zh_CN]=KAddressBook 导入/导出插件 +Comment[zh_TW]=KAddressBook 匯入/匯出外掛程式 + +[PropertyDef::X-KDE-KAddressBook-XXPortPluginVersion] +Type=int + diff --git a/kaddressbook/interfaces/xxport.cpp b/kaddressbook/interfaces/xxport.cpp new file mode 100644 index 000000000..0e9e515c2 --- /dev/null +++ b/kaddressbook/interfaces/xxport.cpp @@ -0,0 +1,128 @@ +/* + 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 <qmap.h> +#include <qsignalmapper.h> + +#include <kaction.h> +#include <kinstance.h> +#include <kmessagebox.h> +#include <kapplication.h> +#include "xxport.h" + +using namespace KAB; + +class XXPort::XXPortPrivate +{ + public: + QSignalMapper *mExportMapper; + QSignalMapper *mImportMapper; + KApplication *mKApp; +}; + +XXPort::XXPort( KABC::AddressBook *ab, QWidget *parent, + const char *name ) + : QObject( parent, name ), mAddressBook( ab ), mParentWidget( parent ), + d( new XXPortPrivate ) +{ + setInstance( new KInstance( "kaddressbook" ) ); + + d->mExportMapper = new QSignalMapper( this ); + d->mImportMapper = new QSignalMapper( this ); + + connect( d->mExportMapper, SIGNAL( mapped( const QString& ) ), + SLOT( slotExportActivated( const QString& ) ) ); + connect( d->mImportMapper, SIGNAL( mapped( const QString& ) ), + SLOT( slotImportActivated( const QString& ) ) ); +} + +XXPort::~XXPort() +{ + delete d; + d = 0; +} + +bool XXPort::exportContacts( const KABC::AddresseeList&, const QString& ) +{ + // do nothing + return false; +} + +KABC::AddresseeList XXPort::importContacts( const QString& ) const +{ + // do nothing + return KABC::AddresseeList(); +} + +void XXPort::createImportAction( const QString &label, const QString &data ) +{ + QString id = "file_import_" + identifier() + ( data.isEmpty() ? QString( "" ) : "_" + data ); + KAction *action = new KAction( label, 0, d->mImportMapper, SLOT( map() ), actionCollection(), id.latin1() ); + + d->mImportMapper->setMapping( action, ( data.isEmpty() ? QString( "<empty>" ) : data ) ); + + setXMLFile( identifier() + "_xxportui.rc" ); +} + +void XXPort::createExportAction( const QString &label, const QString &data ) +{ + QString id = "file_export_" + identifier() + ( data.isEmpty() ? QString( "" ) : "_" + data ); + KAction *action = new KAction( label, 0, d->mExportMapper, SLOT( map() ), actionCollection(), id.latin1() ); + + d->mExportMapper->setMapping( action, ( data.isEmpty() ? QString( "<empty>" ) : data ) ); + + setXMLFile( identifier() + "_xxportui.rc" ); +} + +KABC::AddressBook *XXPort::addressBook() const +{ + return mAddressBook; +} + +QWidget *XXPort::parentWidget() const +{ + return mParentWidget; +} + +void XXPort::setKApplication( KApplication *app ) +{ + d->mKApp = app; +} + +void XXPort::processEvents() const +{ + if ( d->mKApp ) + d->mKApp->processEvents(); +} + +void XXPort::slotExportActivated( const QString &data ) +{ + emit exportActivated( identifier(), ( data == "<empty>" ? QString::null : data ) ); +} + +void XXPort::slotImportActivated( const QString &data ) +{ + emit importActivated( identifier(), ( data == "<empty>" ? QString::null : data ) ); +} + +#include "xxport.moc" diff --git a/kaddressbook/interfaces/xxport.h b/kaddressbook/interfaces/xxport.h new file mode 100644 index 000000000..098688b94 --- /dev/null +++ b/kaddressbook/interfaces/xxport.h @@ -0,0 +1,179 @@ +/* + 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 KAB_XXPORT_H +#define KAB_XXPORT_H + +#include <qobject.h> + +#include <kabc/addressbook.h> +#include <kabc/addresseelist.h> +#include <klibloader.h> +#include <kxmlguiclient.h> +#include <kdepimmacros.h> + +#define KAB_XXPORT_PLUGIN_VERSION 1 + +class KApplication; + +/** + K_EXPORT_KADDRESSBOOK_XXFILTER_CATALOG() creates the stub for a KAddressbook import/export filter. + @libname filename of the shared library, e.g. libkaddrbk_bookmark_xxport + @XXPortClass the import/export class - derived from the XXPort class + @catalog catalog file to search for translation lookup (NULL if no catalog needed) + @see: K_EXPORT_COMPONENT_FACTORY() + */ +#define K_EXPORT_KADDRESSBOOK_XXFILTER_CATALOG( libname, XXPortClass, catalog ) \ + class KDE_NO_EXPORT localXXPortFactory : public KAB::XXPortFactory { \ + KAB::XXPort *xxportObject( KABC::AddressBook *ab, QWidget *parent, const char *name ) \ + { const char *cat = catalog; \ + if (cat) KGlobal::locale()->insertCatalogue(cat); \ + return new XXPortClass( ab, parent, name ); \ + } \ + }; \ + K_EXPORT_COMPONENT_FACTORY( libname, localXXPortFactory ) + +/** + K_EXPORT_KADDRESSBOOK_XXFILTER() creates the stub for a KAddressbook import/export filter. + @libname filename of the shared library, e.g. libkaddrbk_bookmark_xxport + @XXPortClass the import/export class - derived from the XXPort class + @see: K_EXPORT_COMPONENT_FACTORY() + */ +#define K_EXPORT_KADDRESSBOOK_XXFILTER( libname, XXPortClass ) \ + K_EXPORT_KADDRESSBOOK_XXFILTER_CATALOG( libname, XXPortClass, NULL ) + + +namespace KAB { + +class KDE_EXPORT XXPort : public QObject, virtual public KXMLGUIClient +{ + Q_OBJECT + + public: + XXPort( KABC::AddressBook *ab, QWidget *parent, const char *name = 0 ); + ~XXPort(); + + /** + Returns the unique identifier of this xxport modul, it should + be the lowercase name of the import/export format e.g. 'vcard' + */ + virtual QString identifier() const = 0; + + /** + Reimplement this method if the XXPortManager shall + pass a sorted list to @ref exportContacts(). + */ + virtual bool requiresSorting() const { return false; } + + /** + set the KApplication pointer. + @see: processEvents() + */ + void setKApplication( KApplication *app ); + + /** + Processes outstanding KApplication events. It should be called + occasionally when the import/export filter is busy performing + a long operation (e.g. reading from slow external devices). + @see: QApplication::processEvents() + */ + void processEvents() const; + + public slots: + /** + Reimplement this method for exporting the contacts. + */ + virtual bool exportContacts( const KABC::AddresseeList &list, const QString& identifier ); + + /** + Reimplement this method for importing the contacts. + */ + virtual KABC::AddresseeList importContacts( const QString& identifier ) const; + + signals: + /** + Emitted whenever the export action is activated. + The parameter contains the @ref identifier() for + unique identification. + */ + void exportActivated( const QString&, const QString& ); + + /** + Emitted whenever the import action is activated. + The parameter contains the @ref identifier() for + unique identification. + */ + void importActivated( const QString&, const QString& ); + + protected: + /** + Create the import action. The identifier is passed in the import slot. + */ + void createImportAction( const QString &label, const QString &identifier = QString::null ); + + /** + Create the export action. The identifier is passed in the export slot. + */ + void createExportAction( const QString &label, const QString &identifier = QString::null ); + + /** + Returns a pointer to the address book object. + */ + KABC::AddressBook *addressBook() const; + + /** + Returns a pointer to the parent widget. It can be used as parent for + message boxes. + */ + QWidget *parentWidget() const; + + private slots: + void slotImportActivated( const QString& ); + void slotExportActivated( const QString& ); + + private: + KABC::AddressBook *mAddressBook; + QWidget *mParentWidget; + + class XXPortPrivate; + XXPortPrivate *d; +}; + +class XXPortFactory : public KLibFactory +{ + public: + virtual XXPort *xxportObject( KABC::AddressBook *ab, QWidget *parent, + const char *name = 0 ) = 0; + + protected: + virtual QObject* createObject( QObject*, const char*, const char*, + const QStringList & ) + { + return 0; + } +}; + + +} /* namespace KAB */ + +#endif diff --git a/kaddressbook/jumpbuttonbar.cpp b/kaddressbook/jumpbuttonbar.cpp new file mode 100644 index 000000000..1c8eddbad --- /dev/null +++ b/kaddressbook/jumpbuttonbar.cpp @@ -0,0 +1,239 @@ +/* + This file is part of KAddressBook. + Copyright (c) 2002 Mike Pilone <mpilone@slac.com> + + 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 <qapplication.h> +#include <qbuttongroup.h> +#include <qevent.h> +#include <qlayout.h> +#include <qpushbutton.h> +#include <qstring.h> +#include <qstyle.h> + +#include <kabc/addressbook.h> +#include <kabc/field.h> +#include <kdebug.h> +#include <kdialog.h> +#include <klocale.h> + +#include "core.h" + +#include "jumpbuttonbar.h" + +class JumpButton : public QPushButton +{ + public: + JumpButton( const QString &firstChar, const QString &lastChar, + QWidget *parent ); + + QString firstChar() const { return mChar; } + + private: + QString mChar; +}; + +JumpButton::JumpButton( const QString &firstChar, const QString &lastChar, + QWidget *parent ) + : QPushButton( "", parent ), mChar( firstChar ) +{ + setToggleButton( true ); + if ( !lastChar.isEmpty() ) + setText( QString( "%1 - %2" ).arg( firstChar.upper() ).arg( lastChar.upper() ) ); + else + setText( firstChar.upper() ); +} + +JumpButtonBar::JumpButtonBar( KAB::Core *core, QWidget *parent, const char *name ) + : QWidget( parent, name ), mCore( core ) +{ + setMinimumSize( 1, 1 ); + + QVBoxLayout *layout = new QVBoxLayout( this, 0, 0 ); + layout->setAlignment( Qt::AlignTop ); + layout->setAutoAdd( true ); + layout->setResizeMode( QLayout::FreeResize ); + + mGroupBox = new QButtonGroup( 1, Qt::Horizontal, this ); + mGroupBox->setExclusive( true ); + mGroupBox->layout()->setSpacing( 0 ); + mGroupBox->layout()->setMargin( 0 ); + mGroupBox->setFrameStyle( QFrame::NoFrame ); +} + +JumpButtonBar::~JumpButtonBar() +{ +} + +void JumpButtonBar::updateButtons() +{ + int currentButton = mGroupBox->selectedId(); + + // the easiest way to remove all buttons ;) + mButtons.setAutoDelete( true ); + mButtons.clear(); + mButtons.setAutoDelete( false ); + + QStringList characters; + + // calculate how many buttons are possible + QFontMetrics fm = fontMetrics(); + QPushButton *btn = new QPushButton( "", this ); + btn->hide(); + QSize buttonSize = style().sizeFromContents( QStyle::CT_PushButton, btn, + fm.size( ShowPrefix, "X - X") ). + expandedTo( QApplication::globalStrut() ); + delete btn; + + int buttonHeight = buttonSize.height() + 8; + uint possibleButtons = (height() / buttonHeight) - 1; + + QString character; + KABC::AddressBook *ab = mCore->addressBook(); + KABC::AddressBook::Iterator it; + for ( it = ab->begin(); it != ab->end(); ++it ) { + KABC::Field *field = 0; + field = mCore->currentSortField(); + if ( field ) { + setEnabled( true ); + if ( !field->value( *it ).isEmpty() ) + character = field->value( *it )[ 0 ].lower(); + } else { + setEnabled( false ); + return; + } + + if ( !character.isEmpty() && !characters.contains( character ) ) + characters.append( character ); + } + + sortListLocaleAware( characters ); + + if ( characters.count() <= possibleButtons ) { + // at first the easy case: all buttons fits in window + for ( uint i = 0; i < characters.count(); ++i ) { + JumpButton *button = new JumpButton( characters[ i ], QString::null, + mGroupBox ); + connect( button, SIGNAL( clicked() ), this, SLOT( letterClicked() ) ); + mButtons.append( button ); + button->show(); + } + } else { + if ( possibleButtons == 0 ) // to avoid crashes on startup + return; + int offset = characters.count() / possibleButtons; + int odd = characters.count() % possibleButtons; + if ( odd ) + offset++; + + int current = 0; + for ( uint i = 0; i < possibleButtons; ++i ) { + if ( characters.count() - current == 0 ) + continue; + if ( characters.count() - current <= possibleButtons - i ) { + JumpButton *button = new JumpButton( characters[ current ], + QString::null, mGroupBox ); + connect( button, SIGNAL( clicked() ), this, SLOT( letterClicked() ) ); + mButtons.append( button ); + button->show(); + current++; + } else { + int pos = ( current + offset >= (int)characters.count() ? + characters.count() - 1 : current + offset - 1 ); + QString range; + for ( int j = current; j < pos + 1; ++j ) + range.append( characters[ j ] ); + JumpButton *button = new JumpButton( characters[ current ], + characters[ pos ], mGroupBox ); + connect( button, SIGNAL( clicked() ), this, SLOT( letterClicked() ) ); + mButtons.append( button ); + button->show(); + current = ( i + 1 ) * offset; + } + } + } + + if ( currentButton != -1 ) + mGroupBox->setButton( currentButton ); + else + mGroupBox->setButton( 0 ); + + int maxWidth = 0; + QPushButton *button; + for ( button = mButtons.first(); button; button = mButtons.next() ) + maxWidth = QMAX( maxWidth, button->sizeHint().width() ); + + setFixedWidth( maxWidth ); +} + +void JumpButtonBar::letterClicked() +{ + JumpButton *button = (JumpButton*)sender(); + QString character = button->firstChar(); + + emit jumpToLetter( character ); +} + +void JumpButtonBar::resizeEvent( QResizeEvent* ) +{ + updateButtons(); +} + +class SortContainer +{ + public: + SortContainer() {} + SortContainer( const QString &string ) + : mString( string ) + { + } + + bool operator< ( const SortContainer &cnt ) + { + return ( QString::localeAwareCompare( mString, cnt.mString ) < 0 ); + } + + QString data() const + { + return mString; + } + + private: + QString mString; +}; + +void JumpButtonBar::sortListLocaleAware( QStringList &list ) +{ + QValueList<SortContainer> sortList; + + QStringList::ConstIterator it; + for ( it = list.begin(); it != list.end(); ++it ) + sortList.append( SortContainer( *it ) ); + + qHeapSort( sortList ); + list.clear(); + + QValueList<SortContainer>::ConstIterator sortIt; + for ( sortIt = sortList.begin(); sortIt != sortList.end(); ++sortIt ) + list.append( (*sortIt).data() ); +} + +#include "jumpbuttonbar.moc" diff --git a/kaddressbook/jumpbuttonbar.h b/kaddressbook/jumpbuttonbar.h new file mode 100644 index 000000000..850b51b48 --- /dev/null +++ b/kaddressbook/jumpbuttonbar.h @@ -0,0 +1,79 @@ +/* + This file is part of KAddressBook. + Copyright (c) 2002 Mike Pilone <mpilone@slac.com> + + 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 JUMPBUTTONBAR_H +#define JUMPBUTTONBAR_H + +#include <qsizepolicy.h> +#include <qwidget.h> +#include <qptrlist.h> +#include <qstringlist.h> + +class QButtonGroup; +class QResizeEvent; +class QPushButton; + +namespace KAB { +class Core; +} + +namespace KABC { +class Field; +} + +/** + Used to draw the jump button bar on the right of the view. + */ +class JumpButtonBar : public QWidget +{ + Q_OBJECT + + public: + JumpButtonBar( KAB::Core *core, QWidget *parent, const char *name = 0 ); + ~JumpButtonBar(); + + public slots: + void updateButtons(); + + signals: + /** + Emitted whenever a letter is selected by the user. + */ + void jumpToLetter( const QString &character ); + + protected slots: + void letterClicked(); + + protected: + virtual void resizeEvent( QResizeEvent* ); + + private: + void sortListLocaleAware( QStringList &list ); + + KAB::Core *mCore; + + QButtonGroup *mGroupBox; + QPtrList<QPushButton> mButtons; +}; + +#endif diff --git a/kaddressbook/kabcore.cpp b/kaddressbook/kabcore.cpp new file mode 100644 index 000000000..0702ce04e --- /dev/null +++ b/kaddressbook/kabcore.cpp @@ -0,0 +1,1647 @@ +/* + This file is part of KAddressbook. + Copyright (c) 2003 - 2004 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. +*/ + +// Needed for ugly hack, to be removed in 4.0 +#include <unistd.h> // for usleep +#include <qeventloop.h> + +#include <qclipboard.h> +#include <qdir.h> +#include <qfile.h> +#include <qlabel.h> +#include <qlayout.h> +#include <qptrlist.h> +#include <qwidgetstack.h> +#include <qregexp.h> +#include <qvbox.h> + +#include <kabc/addresseelist.h> +#include <kabc/errorhandler.h> +#include <kabc/resource.h> +#include <kabc/stdaddressbook.h> +#include <kabc/vcardconverter.h> +#include <kabc/resourcefile.h> +#include <kaboutdata.h> +#include <kaccelmanager.h> +#include <kapplication.h> +#include <dcopclient.h> +#include <kactionclasses.h> +#include <kcmdlineargs.h> +#include <kcmultidialog.h> +#include <kdebug.h> +#include <kdeversion.h> +#include <kimproxy.h> +#include <klocale.h> +#include <kmessagebox.h> +#include <kprinter.h> +#include <kprotocolinfo.h> +#include <kpushbutton.h> +#include <kresources/selectdialog.h> +#include <kstandarddirs.h> +#include <kstatusbar.h> +#include <kstdguiitem.h> +#include <kxmlguiclient.h> +#include <ktoolbar.h> +#include <libkdepim/addresseeview.h> +#include <libkdepim/categoryeditdialog.h> +#include <libkdepim/categoryselectdialog.h> +#include <libkdepim/resourceabc.h> +#include "distributionlisteditor.h" + +#include "addresseeutil.h" +#include "addresseeeditordialog.h" +#include "distributionlistentryview.h" +#include "extensionmanager.h" +#include "filterselectionwidget.h" +#include "incsearchwidget.h" +#include "jumpbuttonbar.h" +#include "kablock.h" +#include "kabprefs.h" +#include "kabtools.h" +#include "kaddressbookservice.h" +#include "kaddressbookiface.h" +#include "ldapsearchdialog.h" +#include "locationmap.h" +#include "printing/printingwizard.h" +#include "searchmanager.h" +#include "undocmds.h" +#include "viewmanager.h" +#include "xxportmanager.h" + +#include "kabcore.h" + +KABCore::KABCore( KXMLGUIClient *client, bool readWrite, QWidget *parent, + const QString &file, const char *name ) + : KAB::Core( client, parent, name ), mStatusBar( 0 ), mViewManager( 0 ), + mExtensionManager( 0 ), mJumpButtonBar( 0 ), mCategorySelectDialog( 0 ), + mCategoryEditDialog( 0 ), mLdapSearchDialog( 0 ), mReadWrite( readWrite ), + mModified( false ) +{ + mWidget = new QWidget( parent, name ); + + mIsPart = !parent->isA( "KAddressBookMain" ); + + mAddressBookChangedTimer = new QTimer( this ); + connect( mAddressBookChangedTimer, SIGNAL( timeout() ), + this, SLOT( addressBookChanged() ) ); + + if ( file.isEmpty() ) { + mAddressBook = KABC::StdAddressBook::self( true ); + } else { + kdDebug(5720) << "KABCore(): document '" << file << "'" << endl; + mAddressBook = new KABC::AddressBook; + mAddressBook->addResource( new KABC::ResourceFile( file ) ); + if ( !mAddressBook->load() ) { + KMessageBox::error( parent, i18n("Unable to load '%1'.").arg( file ) ); + } + } + mAddressBook->setErrorHandler( new KABC::GuiErrorHandler( mWidget ) ); + +#if ! KDE_IS_VERSION(3,5,8) + mAddressBook->addCustomField( i18n( "Department" ), KABC::Field::Organization, + "X-Department", "KADDRESSBOOK" ); +#endif + mAddressBook->addCustomField( i18n( "Profession" ), KABC::Field::Organization, + "X-Profession", "KADDRESSBOOK" ); + mAddressBook->addCustomField( i18n( "Assistant's Name" ), KABC::Field::Organization, + "X-AssistantsName", "KADDRESSBOOK" ); + mAddressBook->addCustomField( i18n( "Manager's Name" ), KABC::Field::Organization, + "X-ManagersName", "KADDRESSBOOK" ); + mAddressBook->addCustomField( i18n( "Partner's Name" ), KABC::Field::Personal, + "X-SpousesName", "KADDRESSBOOK" ); + mAddressBook->addCustomField( i18n( "Office" ), KABC::Field::Personal, + "X-Office", "KADDRESSBOOK" ); + mAddressBook->addCustomField( i18n( "IM Address" ), KABC::Field::Personal, + "X-IMAddress", "KADDRESSBOOK" ); + mAddressBook->addCustomField( i18n( "Anniversary" ), KABC::Field::Personal, + "X-Anniversary", "KADDRESSBOOK" ); + mAddressBook->addCustomField( i18n( "Blog" ), KABC::Field::Personal, + "BlogFeed", "KADDRESSBOOK" ); + + mSearchManager = new KAB::SearchManager( mAddressBook, parent ); + + connect( mSearchManager, SIGNAL( contactsUpdated() ), + this, SLOT( slotContactsUpdated() ) ); + + initGUI(); + + connect( mAddressBook, SIGNAL( addressBookChanged( AddressBook* ) ), + SLOT( delayedAddressBookChanged() ) ); + connect( mAddressBook, SIGNAL( loadingFinished( Resource* ) ), + SLOT( delayedAddressBookChanged() ) ); + + mIncSearchWidget->setFocus(); + + connect( mViewManager, SIGNAL( selected( const QString& ) ), + SLOT( setContactSelected( const QString& ) ) ); + connect( mViewManager, SIGNAL( executed( const QString& ) ), + SLOT( editContact( const QString& ) ) ); + connect( mViewManager, SIGNAL( modified() ), + SLOT( setModified() ) ); + connect( mViewManager, SIGNAL( urlDropped( const KURL& ) ), + mXXPortManager, SLOT( importVCard( const KURL& ) ) ); + connect( mViewManager, SIGNAL( viewFieldsChanged() ), + SLOT( updateIncSearchWidget() ) ); + connect( mExtensionManager, SIGNAL( modified( const KABC::Addressee::List& ) ), + this, SLOT( extensionModified( const KABC::Addressee::List& ) ) ); + connect( mExtensionManager, SIGNAL( deleted( const QStringList& ) ), + this, SLOT( extensionDeleted( const QStringList& ) ) ); + + connect( mXXPortManager, SIGNAL( modified() ), + SLOT( setModified() ) ); + + connect( mDetailsViewer, SIGNAL( highlightedMessage( const QString& ) ), + SLOT( detailsHighlighted( const QString& ) ) ); + + connect( mIncSearchWidget, SIGNAL( scrollUp() ), + mViewManager, SLOT( scrollUp() ) ); + connect( mIncSearchWidget, SIGNAL( scrollDown() ), + mViewManager, SLOT( scrollDown() ) ); + + mAddressBookService = new KAddressBookService( this ); + + mCommandHistory = new KCommandHistory( actionCollection(), true ); + connect( mCommandHistory, SIGNAL( commandExecuted() ), + mSearchManager, SLOT( reload() ) ); + + mSearchManager->reload(); + + setModified( false ); + + KAcceleratorManager::manage( mWidget ); + + mKIMProxy = ::KIMProxy::instance( kapp->dcopClient() ); +} + +KABCore::~KABCore() +{ + mAddressBook->disconnect(); + + mAddressBook = 0; + KABC::StdAddressBook::close(); + mKIMProxy = 0; +} + +void KABCore::restoreSettings() +{ + bool state = KABPrefs::instance()->jumpButtonBarVisible(); + mActionJumpBar->setChecked( state ); + setJumpButtonBarVisible( state ); + + state = KABPrefs::instance()->detailsPageVisible(); + mActionDetails->setChecked( state ); + setDetailsVisible( state ); + + mViewManager->restoreSettings(); + mExtensionManager->restoreSettings(); + + updateIncSearchWidget(); + mIncSearchWidget->setCurrentItem( KABPrefs::instance()->currentIncSearchField() ); + + QValueList<int> splitterSize = KABPrefs::instance()->detailsSplitter(); + if ( splitterSize.count() == 0 ) { + splitterSize.append( 360 ); + splitterSize.append( 260 ); + } + mDetailsSplitter->setSizes( splitterSize ); + + const QValueList<int> leftSplitterSizes = KABPrefs::instance()->leftSplitter(); + if ( !leftSplitterSizes.isEmpty() ) + mLeftSplitter->setSizes( leftSplitterSizes ); +} + +void KABCore::saveSettings() +{ + KABPrefs::instance()->setJumpButtonBarVisible( mActionJumpBar->isChecked() ); + KABPrefs::instance()->setDetailsPageVisible( mActionDetails->isChecked() ); + KABPrefs::instance()->setDetailsSplitter( mDetailsSplitter->sizes() ); + KABPrefs::instance()->setLeftSplitter( mLeftSplitter->sizes() ); + + mExtensionManager->saveSettings(); + mViewManager->saveSettings(); + + KABPrefs::instance()->setCurrentIncSearchField( mIncSearchWidget->currentItem() ); +} + +KABC::AddressBook *KABCore::addressBook() const +{ + return mAddressBook; +} + +KConfig *KABCore::config() const +{ + return KABPrefs::instance()->config(); +} + +KActionCollection *KABCore::actionCollection() const +{ + return guiClient()->actionCollection(); +} + +KABC::Field *KABCore::currentSortField() const +{ + return mViewManager->currentSortField(); +} + +QStringList KABCore::selectedUIDs() const +{ + return mViewManager->selectedUids(); +} + +KABC::Resource *KABCore::requestResource( QWidget *parent ) +{ + QPtrList<KABC::Resource> kabcResources = addressBook()->resources(); + + QPtrList<KRES::Resource> kresResources; + QPtrListIterator<KABC::Resource> resIt( kabcResources ); + KABC::Resource *resource; + while ( ( resource = resIt.current() ) != 0 ) { + ++resIt; + if ( !resource->readOnly() ) { + KRES::Resource *res = resource; // downcast + kresResources.append( res ); + } + } + + KRES::Resource *res = KRES::SelectDialog::getResource( kresResources, parent ); + return static_cast<KABC::Resource*>( res ); // upcast +} + +QWidget *KABCore::widget() const +{ + return mWidget; +} + +KAboutData *KABCore::createAboutData() +{ + KAboutData *about = new KAboutData( "kaddressbook", I18N_NOOP( "KAddressBook" ), + "3.5.10", I18N_NOOP( "The KDE Address Book" ), + KAboutData::License_GPL_V2, + I18N_NOOP( "(c) 1997-2005, The KDE PIM Team" ) ); + about->addAuthor( "Tobias Koenig", I18N_NOOP( "Current maintainer" ), "tokoe@kde.org" ); + about->addAuthor( "Don Sanders", I18N_NOOP( "Original author" ) ); + about->addAuthor( "Cornelius Schumacher", + I18N_NOOP( "Co-maintainer, libkabc port, CSV import/export" ), + "schumacher@kde.org" ); + about->addAuthor( "Mike Pilone", I18N_NOOP( "GUI and framework redesign" ), + "mpilone@slac.com" ); + about->addAuthor( "Greg Stern", I18N_NOOP( "DCOP interface" ) ); + about->addAuthor( "Mark Westcott", I18N_NOOP( "Contact pinning" ) ); + about->addAuthor( "Mischel Boyer de la Giroday", I18N_NOOP( "LDAP Lookup" ), + "michel@klaralvdalens-datakonsult.se" ); + about->addAuthor( "Steffen Hansen", I18N_NOOP( "LDAP Lookup" ), + "hansen@kde.org" ); + + return about; +} + +void KABCore::setStatusBar( KStatusBar *statusBar ) +{ + mStatusBar = statusBar; +} + +KStatusBar *KABCore::statusBar() const +{ + return mStatusBar; +} + +void KABCore::setContactSelected( const QString &uid ) +{ + KABC::Addressee addr = mAddressBook->findByUid( uid ); + if ( !mDetailsViewer->isHidden() ) + mDetailsViewer->setAddressee( addr ); +#ifdef KDEPIM_NEW_DISTRLISTS + if ( !mSelectedDistributionList.isNull() && mDistListEntryView->isShown() ) { + showDistributionListEntry( uid ); + } +#endif + mExtensionManager->setSelectionChanged(); + + KABC::Addressee::List list = mViewManager->selectedAddressees(); + const bool someSelected = list.size() > 0; + const bool singleSelected = list.size() == 1; + bool writable = mReadWrite; + + if ( writable ) { + //check if every single (sub)resource is writable + //### We have a performance problem here - everytime *one* item is added or + // removed we re-check *all* items. If this turns out to be a bottleneck + // we need to keep some state and check new items only. + KABC::Addressee::List::ConstIterator addrIt = list.constBegin(); + for ( ; addrIt != list.constEnd(); ++addrIt ) { + KABC::Resource *res = ( *addrIt ).resource(); + if ( !res ) { + kdDebug() << "KABCore::setContactSelected: this addressee has no resource!" << endl; + writable = false; + break; + } + if ( res->readOnly() ) { + writable = false; + break; + } + //HACK: manual polymorphism + if ( res->inherits( "KPIM::ResourceABC" ) ) { + KPIM::ResourceABC *resAbc = static_cast<KPIM::ResourceABC *>( res ); + + QString subresource = resAbc->uidToResourceMap()[ ( *addrIt ).uid() ]; + if ( !subresource.isEmpty() && !resAbc->subresourceWritable( subresource ) ) { + writable = false; + break; + } + } + } + } + + bool moreThanOneResource = mAddressBook->resources().count() > 1; + if ( !moreThanOneResource && !mAddressBook->resources().isEmpty() ) { + KABC::Resource *res = mAddressBook->resources().first(); + if ( res->inherits( "KPIM::ResourceABC" ) ) { + KPIM::ResourceABC *resAbc = static_cast<KPIM::ResourceABC *>( res ); + const QStringList subresources = resAbc->subresources(); + int writeables = 0; + for ( QStringList::ConstIterator it = subresources.begin(); it != subresources.end(); ++it ) { + if ( resAbc->subresourceActive(*it) && resAbc->subresourceWritable(*it) ) { + writeables++; + } + } + moreThanOneResource = ( writeables >= 2 ); + } + } + + // update the actions + + mActionCopy->setEnabled( someSelected ); + mActionCut->setEnabled( someSelected && writable ); + mActionDelete->setEnabled( someSelected && writable ); + // the "edit" dialog doubles as the details dialog and it knows when the addressee is read-only + // (### this does not make much sense from the user perspective!) + mActionEditAddressee->setEnabled( singleSelected ); + mActionCopyAddresseeTo->setEnabled( someSelected && moreThanOneResource ); + mActionMoveAddresseeTo->setEnabled( someSelected && moreThanOneResource && writable ); + mActionMail->setEnabled( someSelected ); + mActionMailVCard->setEnabled( someSelected ); + mActionChat->setEnabled( singleSelected && mKIMProxy && mKIMProxy->initialize() ); + mActionWhoAmI->setEnabled( singleSelected ); + mActionCategories->setEnabled( someSelected && writable ); + mActionMerge->setEnabled( ( list.size() == 2 ) && writable ); + + if ( mReadWrite ) { + QClipboard *cb = QApplication::clipboard(); + list = AddresseeUtil::clipboardToAddressees( cb->text() ); + mActionPaste->setEnabled( !list.isEmpty() ); + } +} + +void KABCore::sendMail() +{ + //FIXME: breaks with email addresses containing "," + sendMail( mViewManager->selectedEmails().join( ", " ) ); +} + +void KABCore::sendMail( const QString& email ) +{ + kapp->invokeMailer( email, "" ); +} + +void KABCore::mailVCard() +{ + QStringList uids = mViewManager->selectedUids(); + if ( !uids.isEmpty() ) + mailVCard( uids ); +} + +void KABCore::mailVCard( const QStringList &uids ) +{ + KABTools::mailVCards( uids, mAddressBook ); +} + +void KABCore::startChat() +{ + QStringList uids = mViewManager->selectedUids(); + if ( !uids.isEmpty() ) + mKIMProxy->chatWithContact( uids.first() ); +} + +void KABCore::browse( const QString& url ) +{ + kapp->invokeBrowser( url ); +} + +void KABCore::selectAllContacts() +{ + mViewManager->setSelected( QString::null, true ); +} + +void KABCore::deleteContacts() +{ + QStringList uidList = mViewManager->selectedUids(); + + deleteContacts( uidList ); +} + +void KABCore::deleteDistributionLists( const QStringList & names ) +{ + if ( names.isEmpty() ) + return; + if ( KMessageBox::warningContinueCancelList( mWidget, i18n( "Do you really want to delete this distribution list?", + "Do you really want to delete these %n distribution lists?", names.count() ), + names, QString::null, KStdGuiItem::del() ) == KMessageBox::Cancel ) + return; + + QStringList uids; + for ( QStringList::ConstIterator it = names.begin(); it != names.end(); ++it ) { + uids.append( KPIM::DistributionList::findByName( mAddressBook, *it ).uid() ); + } + DeleteCommand *command = new DeleteCommand( mAddressBook, uids ); + mCommandHistory->addCommand( command ); + setModified( true ); +} + +void KABCore::deleteContacts( const QStringList &uids ) +{ + if ( uids.count() > 0 ) { + QStringList names; + QStringList::ConstIterator it = uids.begin(); + const QStringList::ConstIterator endIt( uids.end() ); + while ( it != endIt ) { + KABC::Addressee addr = mAddressBook->findByUid( *it ); + names.append( addr.realName().isEmpty() ? addr.preferredEmail() : addr.realName() ); + ++it; + } + + if ( KMessageBox::warningContinueCancelList( mWidget, i18n( "Do you really want to delete this contact?", + "Do you really want to delete these %n contacts?", uids.count() ), + names, QString::null, KStdGuiItem::del() ) == KMessageBox::Cancel ) + return; + + DeleteCommand *command = new DeleteCommand( mAddressBook, uids ); + mCommandHistory->addCommand( command ); + + // now if we deleted anything, refresh + setContactSelected( QString::null ); + setModified( true ); + } +} + +void KABCore::copyContacts() +{ + KABC::Addressee::List addrList = mViewManager->selectedAddressees(); + + QString clipText = AddresseeUtil::addresseesToClipboard( addrList ); + + kdDebug(5720) << "KABCore::copyContacts: " << clipText << endl; + + QClipboard *cb = QApplication::clipboard(); + cb->setText( clipText ); +} + +void KABCore::cutContacts() +{ + QStringList uidList = mViewManager->selectedUids(); + + if ( uidList.size() > 0 ) { + CutCommand *command = new CutCommand( mAddressBook, uidList ); + mCommandHistory->addCommand( command ); + + setModified( true ); + } +} + +void KABCore::pasteContacts() +{ + QClipboard *cb = QApplication::clipboard(); + + KABC::Addressee::List list = AddresseeUtil::clipboardToAddressees( cb->text() ); + + pasteContacts( list ); +} + +void KABCore::pasteContacts( KABC::Addressee::List &list ) +{ + KABC::Resource *resource = requestResource( mWidget ); + if ( !resource ) + return; + + KABC::Addressee::List::Iterator it; + const KABC::Addressee::List::Iterator endIt( list.end() ); + for ( it = list.begin(); it != endIt; ++it ) + (*it).setResource( resource ); + + PasteCommand *command = new PasteCommand( this, list ); + mCommandHistory->addCommand( command ); + + setModified( true ); +} + +void KABCore::mergeContacts() +{ + KABC::Addressee::List list = mViewManager->selectedAddressees(); + if ( list.count() < 2 ) + return; + + KABC::Addressee addr = KABTools::mergeContacts( list ); + + KABC::Addressee::List::Iterator it = list.begin(); + const KABC::Addressee::List::Iterator endIt( list.end() ); + KABC::Addressee origAddr = *it; + QStringList uids; + ++it; + while ( it != endIt ) { + uids.append( (*it).uid() ); + ++it; + } + + DeleteCommand *command = new DeleteCommand( mAddressBook, uids ); + mCommandHistory->addCommand( command ); + + EditCommand *editCommand = new EditCommand( mAddressBook, origAddr, addr ); + mCommandHistory->addCommand( editCommand ); + + mSearchManager->reload(); +} + +void KABCore::setWhoAmI() +{ + KABC::Addressee::List addrList = mViewManager->selectedAddressees(); + + if ( addrList.count() > 1 ) { + // can probably be removed because we now check the selection in setContactSelected(). + KMessageBox::sorry( mWidget, i18n( "Please select only one contact." ) ); + return; + } + + QString text( i18n( "<qt>Do you really want to use <b>%1</b> as your new personal contact?</qt>" ) ); + if ( KMessageBox::questionYesNo( mWidget, text.arg( addrList[ 0 ].assembledName() ), QString::null, i18n("Use"), i18n("Do Not Use") ) == KMessageBox::Yes ) + static_cast<KABC::StdAddressBook*>( KABC::StdAddressBook::self( true ) )->setWhoAmI( addrList[ 0 ] ); +} + +void KABCore::incrementalTextSearch( const QString& text ) +{ + setContactSelected( QString::null ); + mSearchManager->search( text, mIncSearchWidget->currentFields() ); +} + +void KABCore::incrementalJumpButtonSearch( const QString& character ) +{ + mViewManager->setSelected( QString::null, false ); + + KABC::AddresseeList list = mSearchManager->contacts(); + KABC::Field *field = mViewManager->currentSortField(); + if ( field ) { + list.sortByField( field ); + KABC::AddresseeList::ConstIterator it; + const KABC::AddresseeList::ConstIterator endIt( list.end() ); + for ( it = list.begin(); it != endIt; ++it ) { + if ( field->value( *it ).startsWith( character, false ) ) { + mViewManager->setSelected( (*it).uid(), true ); + return; + } + } + } +} + +void KABCore::setModified() +{ + setModified( true ); +} + +void KABCore::setModified( bool modified ) +{ + mModified = modified; + mActionSave->setEnabled( mModified ); + + mSearchManager->reload(); +} + +bool KABCore::modified() const +{ + return mModified; +} + +void KABCore::contactModified( const KABC::Addressee &addr ) +{ + Command *command = 0; + + // check if it exists already + KABC::Addressee origAddr = mAddressBook->findByUid( addr.uid() ); + if ( origAddr.isEmpty() ) { + KABC::Addressee::List addressees; + addressees.append( addr ); + command = new NewCommand( mAddressBook, addressees ); + } else { + command = new EditCommand( mAddressBook, origAddr, addr ); + } + + mCommandHistory->addCommand( command ); + + setContactSelected( addr.uid() ); + setModified( true ); +} + +void KABCore::newDistributionList() +{ +#ifdef KDEPIM_NEW_DISTRLISTS + QString name = i18n( "New Distribution List" ); + const KPIM::DistributionList distList = KPIM::DistributionList::findByName( addressBook(), name ); + if ( !distList.isEmpty() ) { + bool foundUnused = false; + int i = 1; + while ( !foundUnused ) { + name = i18n( "New Distribution List (%1)" ).arg( i++ ); + foundUnused = KPIM::DistributionList::findByName( addressBook(), name ).isEmpty(); + } + } + KPIM::DistributionList list; + list.setUid( KApplication::randomString( 10 ) ); + list.setName( name ); + editDistributionList( list ); +#endif +} + +void KABCore::newContact() +{ + AddresseeEditorDialog *dialog = 0; + + KABC::Resource* resource = requestResource( mWidget ); + + if ( resource ) { + KABC::Addressee addr; + addr.setResource( resource ); + + if ( !KABLock::self( mAddressBook )->lock( addr.resource() ) ) + return; + + dialog = createAddresseeEditorDialog( mWidget ); + dialog->setAddressee( addr ); + } else + return; + + mEditorDict.insert( dialog->addressee().uid(), dialog ); + + dialog->show(); +} + +void KABCore::addEmail( const QString &aStr ) +{ + QString fullName, email; + + KABC::Addressee::parseEmailAddress( aStr, fullName, email ); + +#if KDE_IS_VERSION(3,4,89) + // This ugly hack will be removed in 4.0 + // addressbook may not be reloaded yet, as done asynchronously sometimes, so wait + while ( !mAddressBook->loadingHasFinished() ) { + QApplication::eventLoop()->processEvents( QEventLoop::ExcludeUserInput ); + // use sleep here to reduce cpu usage + usleep( 100 ); + } +#endif + + // Try to lookup the addressee matching the email address + bool found = false; + QStringList emailList; + KABC::AddressBook::Iterator it; + const KABC::AddressBook::Iterator endIt( mAddressBook->end() ); + for ( it = mAddressBook->begin(); !found && (it != endIt); ++it ) { + emailList = (*it).emails(); + if ( emailList.contains( email ) > 0 ) { + found = true; + (*it).setNameFromString( fullName ); + editContact( (*it).uid() ); + } + } + + if ( !found ) { + KABC::Addressee addr; + addr.setNameFromString( fullName ); + addr.insertEmail( email, true ); + + mAddressBook->insertAddressee( addr ); + mViewManager->refreshView( addr.uid() ); + editContact( addr.uid() ); + } +} + +void KABCore::importVCard( const KURL &url ) +{ + mXXPortManager->importVCard( url ); +} + +void KABCore::importVCardFromData( const QString &vCard ) +{ + mXXPortManager->importVCardFromData( vCard ); +} + +void KABCore::editContact( const QString &uid ) +{ + if ( mExtensionManager->isQuickEditVisible() ) + return; + + // First, locate the contact entry + QString localUID = uid; + if ( localUID.isNull() ) { + QStringList uidList = mViewManager->selectedUids(); + if ( uidList.count() > 0 ) + localUID = *( uidList.at( 0 ) ); + } +#if KDE_IS_VERSION(3,4,89) + // This ugly hack will be removed in 4.0 + // for calls with given uid, as done from commandline and DCOP + // addressbook may not be reloaded yet, as done asynchronously, so wait + else while ( !mAddressBook->loadingHasFinished() ) { + QApplication::eventLoop()->processEvents( QEventLoop::ExcludeUserInput ); + // use sleep here to reduce cpu usage + usleep( 100 ); + } +#endif + + KABC::Addressee addr = mAddressBook->findByUid( localUID ); + if ( !addr.isEmpty() ) { + AddresseeEditorDialog *dialog = mEditorDict.find( addr.uid() ); + if ( !dialog ) { + + if ( !addr.resource()->readOnly() ) + if ( !KABLock::self( mAddressBook )->lock( addr.resource() ) ) { + return; + } + + dialog = createAddresseeEditorDialog( mWidget ); + + mEditorDict.insert( addr.uid(), dialog ); + + dialog->setAddressee( addr ); + } + + dialog->raise(); + dialog->show(); + } +} + + +void KABCore::copySelectedContactToResource() +{ + storeContactIn( QString(), true /*copy*/); +} + +void KABCore::moveSelectedContactToResource() +{ + storeContactIn( QString(), false /*copy*/); +} + +void KABCore::storeContactIn( const QString &uid, bool copy /*false*/ ) +{ + // First, locate the contact entry + QStringList uidList; + if ( uid.isNull() ) { + uidList = mViewManager->selectedUids(); + } else { + uidList << uid; + } + KABC::Resource *resource = requestResource( mWidget ); + if ( !resource ) + return; + + KABLock::self( mAddressBook )->lock( resource ); + QStringList::Iterator it( uidList.begin() ); + const QStringList::Iterator endIt( uidList.end() ); + while ( it != endIt ) { + KABC::Addressee addr = mAddressBook->findByUid( *it++ ); + if ( !addr.isEmpty() ) { + KABC::Addressee newAddr( addr ); + // We need to set a new uid, otherwise the insert below is + // ignored. This is bad for syncing, but unavoidable, afaiks + newAddr.setUid( KApplication::randomString( 10 ) ); + newAddr.setResource( resource ); + addressBook()->insertAddressee( newAddr ); + const bool inserted = addressBook()->find( newAddr ) != addressBook()->end(); + if ( !copy && inserted ) { + KABLock::self( mAddressBook )->lock( addr.resource() ); + addressBook()->removeAddressee( addr ); + KABLock::self( mAddressBook )->unlock( addr.resource() ); + } + } + } + KABLock::self( mAddressBook )->unlock( resource ); + + addressBookChanged(); + setModified( true ); +} + +void KABCore::save() +{ + QPtrList<KABC::Resource> resources = mAddressBook->resources(); + QPtrListIterator<KABC::Resource> it( resources ); + while ( it.current() && !it.current()->readOnly() ) { + KABC::Ticket *ticket = mAddressBook->requestSaveTicket( it.current() ); + if ( ticket ) { + if ( !mAddressBook->save( ticket ) ) { + KMessageBox::error( mWidget, + i18n( "<qt>Unable to save address book <b>%1</b>.</qt>" ).arg( it.current()->resourceName() ) ); + mAddressBook->releaseSaveTicket( ticket ); + } else { + setModified( false ); + } + } else { + KMessageBox::error( mWidget, + i18n( "<qt>Unable to get access for saving the address book <b>%1</b>.</qt>" ) + .arg( it.current()->resourceName() ) ); + } + + ++it; + } +} + +void KABCore::setJumpButtonBarVisible( bool visible ) +{ + if ( visible ) { + if ( !mJumpButtonBar ) + createJumpButtonBar(); + mJumpButtonBar->show(); + } else + if ( mJumpButtonBar ) + mJumpButtonBar->hide(); +} + +void KABCore::setDetailsVisible( bool visible ) +{ + if ( visible ) + mDetailsPage->show(); + else + mDetailsPage->hide(); +} + +void KABCore::extensionModified( const KABC::Addressee::List &list ) +{ + if ( list.count() != 0 ) { + KABC::Addressee::List::ConstIterator it; + const KABC::Addressee::List::ConstIterator endIt( list.end() ); + for ( it = list.begin(); it != endIt; ++it ) { + Command *command = 0; + + // check if it exists already + KABC::Addressee origAddr = mAddressBook->findByUid( (*it).uid() ); + if ( origAddr.isEmpty() ) { + KABC::Addressee::List addressees; + addressees.append( *it ); + command = new NewCommand( mAddressBook, addressees ); + } else + command = new EditCommand( mAddressBook, origAddr, *it ); + + mCommandHistory->blockSignals( true ); + mCommandHistory->addCommand( command ); + mCommandHistory->blockSignals( false ); + } + + setModified(true); + } +} + +void KABCore::extensionDeleted( const QStringList &uidList ) +{ + DeleteCommand *command = new DeleteCommand( mAddressBook, uidList ); + mCommandHistory->addCommand( command ); + + // now if we deleted anything, refresh + setContactSelected( QString::null ); + setModified( true ); +} + +QString KABCore::getNameByPhone( const QString &phone ) +{ +#if KDE_IS_VERSION(3,4,89) + // This ugly hack will be removed in 4.0 + // addressbook may not be reloaded yet, as done asynchronously, so wait + while ( !mAddressBook->loadingHasFinished() ) { + QApplication::eventLoop()->processEvents( QEventLoop::ExcludeUserInput ); + // use sleep here to reduce cpu usage + usleep( 100 ); + } +#endif + + QRegExp r( "[/*/-/ ]" ); + QString localPhone( phone ); + + bool found = false; + QString ownerName = ""; + KABC::PhoneNumber::List phoneList; + + KABC::AddressBook::ConstIterator iter; + const KABC::AddressBook::ConstIterator endIter( mAddressBook->end() ); + + for ( iter = mAddressBook->begin(); !found && ( iter != endIter ); ++iter ) { + phoneList = (*iter).phoneNumbers(); + KABC::PhoneNumber::List::Iterator phoneIter( phoneList.begin() ); + const KABC::PhoneNumber::List::Iterator phoneEndIter( phoneList.end() ); + for ( ; !found && ( phoneIter != phoneEndIter ); ++phoneIter) { + // Get rid of separator chars so just the numbers are compared. + if ( (*phoneIter).number().replace( r, "" ) == localPhone.replace( r, "" ) ) { + ownerName = (*iter).realName(); + found = true; + } + } + } + + return ownerName; +} + +void KABCore::openLDAPDialog() +{ + if ( !KProtocolInfo::isKnownProtocol( KURL( "ldap://localhost" ) ) ) { + KMessageBox::error( mWidget, i18n( "Your KDE installation is missing LDAP " + "support, please ask your administrator or distributor for more information." ), + i18n( "No LDAP IO Slave Available" ) ); + return; + } + + if ( !mLdapSearchDialog ) { + mLdapSearchDialog = new LDAPSearchDialog( mAddressBook, this, mWidget ); + connect( mLdapSearchDialog, SIGNAL( addresseesAdded() ), + SLOT( addressBookChanged() ) ); + connect( mLdapSearchDialog, SIGNAL( addresseesAdded() ), + SLOT( setModified() ) ); + } else + mLdapSearchDialog->restoreSettings(); + + if ( mLdapSearchDialog->isOK() ) + mLdapSearchDialog->exec(); +} + +void KABCore::configure() +{ + // Save the current config so we do not loose anything if the user accepts + saveSettings(); + + KCMultiDialog dlg( mWidget, "", true ); + connect( &dlg, SIGNAL( configCommitted() ), + this, SLOT( configurationChanged() ) ); + + dlg.addModule( "kabconfig.desktop" ); + dlg.addModule( "kabldapconfig.desktop" ); + dlg.addModule( "kabcustomfields.desktop" ); + + dlg.exec(); +} + +void KABCore::print() +{ + KPrinter printer; + printer.setDocName( i18n( "Address Book" ) ); + printer.setDocFileName( "addressbook" ); + + if ( !printer.setup( mWidget, i18n("Print Addresses") ) ) + return; + + KABPrinting::PrintingWizard wizard( &printer, mAddressBook, + mViewManager->selectedUids(), mWidget ); + + wizard.exec(); +} + +void KABCore::detailsHighlighted( const QString &msg ) +{ + if ( mStatusBar ) { + if ( !mStatusBar->hasItem( 2 ) ) + mStatusBar->insertItem( msg, 2 ); + else + mStatusBar->changeItem( msg, 2 ); + } +} + +void KABCore::showContactsAddress( const QString &addrUid ) +{ + QStringList uidList = mViewManager->selectedUids(); + if ( uidList.isEmpty() ) + return; + + KABC::Addressee addr = mAddressBook->findByUid( uidList.first() ); + if ( addr.isEmpty() ) + return; + + const KABC::Address::List list = addr.addresses(); + KABC::Address::List::ConstIterator it; + const KABC::Address::List::ConstIterator endIt( list.end() ); + for ( it = list.begin(); it != endIt; ++it ) + if ( (*it).id() == addrUid ) { + LocationMap::instance()->showAddress( *it ); + break; + } +} + +void KABCore::configurationChanged() +{ + mExtensionManager->reconfigure(); + mViewManager->refreshView(); +} + +bool KABCore::queryClose() +{ + saveSettings(); + KABPrefs::instance()->writeConfig(); + + QPtrList<KABC::Resource> resources = mAddressBook->resources(); + QPtrListIterator<KABC::Resource> it( resources ); + while ( it.current() ) { + it.current()->close(); + ++it; + } + + return true; +} + +void KABCore::reinitXMLGUI() +{ + mExtensionManager->createActions(); +} +void KABCore::delayedAddressBookChanged() +{ + mAddressBookChangedTimer->start( 1000 ); +} + +void KABCore::addressBookChanged() +{ + const QStringList selectedUids = mViewManager->selectedUids(); + + mAddressBookChangedTimer->stop(); + + if ( mJumpButtonBar ) + mJumpButtonBar->updateButtons(); + + mSearchManager->reload(); + + mViewManager->setSelected( QString::null, false ); + + QString uid = QString::null; + if ( !selectedUids.isEmpty() ) { + uid = selectedUids.first(); + mViewManager->setSelected( uid, true ); + } + + setContactSelected( uid ); + + updateCategories(); +} + +AddresseeEditorDialog *KABCore::createAddresseeEditorDialog( QWidget *parent, + const char *name ) +{ + AddresseeEditorDialog *dialog = new AddresseeEditorDialog( this, parent, + name ? name : "editorDialog" ); + connect( dialog, SIGNAL( contactModified( const KABC::Addressee& ) ), + SLOT( contactModified( const KABC::Addressee& ) ) ); + connect( dialog, SIGNAL( editorDestroyed( const QString& ) ), + SLOT( slotEditorDestroyed( const QString& ) ) ); + + return dialog; +} + +void KABCore::activateDetailsWidget( QWidget *widget ) +{ + if ( mDetailsStack->visibleWidget() == widget ) + return; + mDetailsStack->raiseWidget( widget ); +} + +void KABCore::deactivateDetailsWidget( QWidget *widget ) +{ + if ( mDetailsStack->visibleWidget() != widget ) + return; + mDetailsStack->raiseWidget( mDetailsWidget ); +} + +void KABCore::slotEditorDestroyed( const QString &uid ) +{ + AddresseeEditorDialog *dialog = mEditorDict.take( uid ); + + KABC::Addressee addr = dialog->addressee(); + + if ( !addr.resource()->readOnly() ) { + QApplication::setOverrideCursor( Qt::waitCursor ); + KABLock::self( mAddressBook )->unlock( addr.resource() ); + QApplication::restoreOverrideCursor(); + } +} + +void KABCore::initGUI() +{ + QVBoxLayout *topLayout = new QVBoxLayout( mWidget, 0, 0 ); + KToolBar* searchTB = new KToolBar( mWidget, "search toolbar"); + searchTB->boxLayout()->setSpacing( KDialog::spacingHint() ); + mIncSearchWidget = new IncSearchWidget( searchTB, "kde toolbar widget"); + searchTB->setStretchableWidget( mIncSearchWidget ); + connect( mIncSearchWidget, SIGNAL( doSearch( const QString& ) ), + SLOT( incrementalTextSearch( const QString& ) ) ); + + mDetailsSplitter = new QSplitter( mWidget ); + + mLeftSplitter = new QSplitter( mDetailsSplitter ); + mLeftSplitter->setOrientation( KABPrefs::instance()->contactListAboveExtensions() ? Qt::Vertical : Qt::Horizontal ); + + topLayout->addWidget( searchTB ); + topLayout->addWidget( mDetailsSplitter ); + + mDetailsStack = new QWidgetStack( mDetailsSplitter ); + mExtensionManager = new ExtensionManager( new QWidget( mLeftSplitter ), mDetailsStack, this, this ); + connect( mExtensionManager, SIGNAL( detailsWidgetDeactivated( QWidget* ) ), + this, SLOT( deactivateDetailsWidget( QWidget* ) ) ); + connect( mExtensionManager, SIGNAL( detailsWidgetActivated( QWidget* ) ), + this, SLOT( activateDetailsWidget( QWidget* ) ) ); + + QWidget *viewWidget = new QWidget( mLeftSplitter ); + if ( KABPrefs::instance()->contactListAboveExtensions() ) + mLeftSplitter->moveToFirst( viewWidget ); + QVBoxLayout *viewLayout = new QVBoxLayout( viewWidget ); + viewLayout->setSpacing( KDialog::spacingHint() ); + + mViewHeaderLabel = new QLabel( viewWidget ); +// mViewHeaderLabel->setSizePolicy( QSizePolicy::Minimum, QSizePolicy::Fixed ); + mViewHeaderLabel->setText( i18n( "Contacts" ) ); + viewLayout->addWidget( mViewHeaderLabel ); + mViewManager = new ViewManager( this, viewWidget ); + viewLayout->addWidget( mViewManager, 1 ); + +#ifdef KDEPIM_NEW_DISTRLISTS + mDistListButtonWidget = new QWidget( viewWidget ); + QHBoxLayout *buttonLayout = new QHBoxLayout( mDistListButtonWidget ); + buttonLayout->setSpacing( KDialog::spacingHint() ); + buttonLayout->addStretch( 1 ); + + KPushButton *addDistListButton = new KPushButton( mDistListButtonWidget ); + addDistListButton->setText( i18n( "Add" ) ); + connect( addDistListButton, SIGNAL( clicked() ), + this, SLOT( editSelectedDistributionList() ) ); + buttonLayout->addWidget( addDistListButton ); + mDistListButtonWidget->setShown( false ); + viewLayout->addWidget( mDistListButtonWidget ); + + KPushButton *removeDistListButton = new KPushButton( mDistListButtonWidget ); + removeDistListButton->setText( i18n( "Remove" ) ); + connect( removeDistListButton, SIGNAL( clicked() ), + this, SLOT( removeSelectedContactsFromDistList() ) ); + buttonLayout->addWidget( removeDistListButton ); +#endif + + mFilterSelectionWidget = new FilterSelectionWidget( searchTB , "kde toolbar widget" ); + mViewManager->setFilterSelectionWidget( mFilterSelectionWidget ); + + connect( mFilterSelectionWidget, SIGNAL( filterActivated( int ) ), + mViewManager, SLOT( setActiveFilter( int ) ) ); + + mDetailsWidget = new QWidget( mDetailsSplitter ); + mDetailsLayout = new QHBoxLayout( mDetailsWidget ); + + mDetailsPage = new QWidget( mDetailsWidget ); + mDetailsLayout->addWidget( mDetailsPage ); + + QHBoxLayout *detailsPageLayout = new QHBoxLayout( mDetailsPage, 0, 0 ); + mDetailsViewer = new KPIM::AddresseeView( mDetailsPage ); + mDetailsViewer->setVScrollBarMode( QScrollView::Auto ); + detailsPageLayout->addWidget( mDetailsViewer ); + + mDistListEntryView = new KAB::DistributionListEntryView( this, mWidget ); + connect( mDistListEntryView, SIGNAL( distributionListClicked( const QString& ) ), + this, SLOT( sendMailToDistributionList( const QString& ) ) ); + mDetailsStack->addWidget( mDistListEntryView ); + mDetailsStack->addWidget( mDetailsWidget ); + mDetailsStack->raiseWidget( mDetailsWidget ); + mDetailsSplitter->moveToLast( mDetailsStack ); + + connect( mDetailsViewer, SIGNAL( addressClicked( const QString&) ), + this, SLOT( showContactsAddress( const QString& ) ) ); + + topLayout->setStretchFactor( mDetailsSplitter, 1 ); + + mXXPortManager = new XXPortManager( this, mWidget ); + + initActions(); +} + +void KABCore::createJumpButtonBar() +{ + mJumpButtonBar = new JumpButtonBar( this, mDetailsWidget ); + mDetailsLayout->addWidget( mJumpButtonBar ); + mDetailsLayout->setStretchFactor( mJumpButtonBar, 1 ); + + connect( mJumpButtonBar, SIGNAL( jumpToLetter( const QString& ) ), + SLOT( incrementalJumpButtonSearch( const QString& ) ) ); + connect( mViewManager, SIGNAL( sortFieldChanged() ), + mJumpButtonBar, SLOT( updateButtons() ) ); +} + +void KABCore::initActions() +{ + connect( QApplication::clipboard(), SIGNAL( dataChanged() ), + SLOT( clipboardDataChanged() ) ); + + KAction *action; + + // file menu + mActionMail = new KAction( i18n( "&Send Email to Contact..." ), "mail_send", 0, + this, SLOT( sendMail() ), actionCollection(), "file_mail" ); + action = KStdAction::print( this, SLOT( print() ), actionCollection() ); + mActionMail->setWhatsThis( i18n( "Send a mail to all selected contacts." ) ); + action->setWhatsThis( i18n( "Print a special number of contacts." ) ); + + mActionSave = KStdAction::save( this, + SLOT( save() ), actionCollection(), "file_sync" ); + mActionSave->setWhatsThis( i18n( "Save all changes of the address book to the storage backend." ) ); + + action = new KAction( i18n( "&New Contact..." ), "identity", CTRL+Key_N, this, + SLOT( newContact() ), actionCollection(), "file_new_contact" ); + action->setWhatsThis( i18n( "Create a new contact<p>You will be presented with a dialog where you can add all data about a person, including addresses and phone numbers." ) ); + + action = new KAction( i18n( "&New Distribution List..." ), "kontact_contacts", 0, this, + SLOT( newDistributionList() ), actionCollection(), "file_new_distributionlist" ); + action->setWhatsThis( i18n( "Create a new distribution list<p>You will be presented with a dialog where you can create a new distribution list." ) ); + + mActionMailVCard = new KAction( i18n("Send &Contact..."), "mail_post_to", 0, + this, SLOT( mailVCard() ), + actionCollection(), "file_mail_vcard" ); + mActionMailVCard->setWhatsThis( i18n( "Send a mail with the selected contact as attachment." ) ); + + mActionChat = new KAction( i18n("Chat &With..."), 0, + this, SLOT( startChat() ), + actionCollection(), "file_chat" ); + mActionChat->setWhatsThis( i18n( "Start a chat with the selected contact." ) ); + + mActionEditAddressee = new KAction( i18n( "&Edit Contact..." ), "edit", 0, + this, SLOT( editContact() ), + actionCollection(), "file_properties" ); + mActionEditAddressee->setWhatsThis( i18n( "Edit a contact<p>You will be presented with a dialog where you can change all data about a person, including addresses and phone numbers." ) ); + + mActionMerge = new KAction( i18n( "&Merge Contacts" ), "", 0, + this, SLOT( mergeContacts() ), + actionCollection(), "edit_merge" ); + + // edit menu + mActionCopy = KStdAction::copy( this, SLOT( copyContacts() ), actionCollection() ); + mActionCut = KStdAction::cut( this, SLOT( cutContacts() ), actionCollection() ); + mActionPaste = KStdAction::paste( this, SLOT( pasteContacts() ), actionCollection() ); + action = KStdAction::selectAll( this, SLOT( selectAllContacts() ), actionCollection() ); + mActionCopy->setWhatsThis( i18n( "Copy the currently selected contact(s) to system clipboard in vCard format." ) ); + mActionCut->setWhatsThis( i18n( "Cuts the currently selected contact(s) to system clipboard in vCard format." ) ); + mActionPaste->setWhatsThis( i18n( "Paste the previously cut or copied contacts from clipboard." ) ); + action->setWhatsThis( i18n( "Selects all visible contacts from current view." ) ); +// mActionUndo->setWhatsThis( i18n( "Undoes the last <b>Cut</b>, <b>Copy</b> or <b>Paste</b>." ) ); +// mActionRedo->setWhatsThis( i18n( "Redoes the last <b>Cut</b>, <b>Copy</b> or <b>Paste</b>." ) ); + + mActionDelete = new KAction( i18n( "&Delete Contact" ), "editdelete", + Key_Delete, this, SLOT( deleteContacts() ), + actionCollection(), "edit_delete" ); + mActionDelete->setWhatsThis( i18n( "Delete all selected contacts." ) ); + + + mActionCopyAddresseeTo = new KAction( i18n( "&Copy Contact To..." ), "", 0, + this, SLOT( copySelectedContactToResource() ), + actionCollection(), "copy_contact_to" ); + const QString copyMoveWhatsThis = i18n( "Store a contact in a different Addressbook<p>You will be presented with a dialog where you can select a new storage place for this contact." ); + mActionCopyAddresseeTo->setWhatsThis( copyMoveWhatsThis ); + + mActionMoveAddresseeTo = new KAction( i18n( "M&ove Contact To..." ), "", 0, + this, SLOT( moveSelectedContactToResource() ), + actionCollection(), "move_contact_to" ); + mActionMoveAddresseeTo->setWhatsThis( copyMoveWhatsThis ); + + // settings menu + mActionJumpBar = new KToggleAction( i18n( "Show Jump Bar" ), "next", 0, + actionCollection(), "options_show_jump_bar" ); + mActionJumpBar->setWhatsThis( i18n( "Toggle whether the jump button bar shall be visible." ) ); + mActionJumpBar->setCheckedState( i18n( "Hide Jump Bar") ); + connect( mActionJumpBar, SIGNAL( toggled( bool ) ), SLOT( setJumpButtonBarVisible( bool ) ) ); + + mActionDetails = new KToggleAction( i18n( "Show Details" ), 0, 0, + actionCollection(), "options_show_details" ); + mActionDetails->setWhatsThis( i18n( "Toggle whether the details page shall be visible." ) ); + mActionDetails->setCheckedState( i18n( "Hide Details") ); + connect( mActionDetails, SIGNAL( toggled( bool ) ), SLOT( setDetailsVisible( bool ) ) ); + + if ( mIsPart ) + action = new KAction( i18n( "&Configure Address Book..." ), "configure", 0, + this, SLOT( configure() ), actionCollection(), + "kaddressbook_configure" ); + else + action = KStdAction::preferences( this, SLOT( configure() ), actionCollection() ); + + action->setWhatsThis( i18n( "You will be presented with a dialog, that offers you all possibilities to configure KAddressBook." ) ); + + // misc + action = new KAction( i18n( "&Lookup Addresses in LDAP Directory..." ), "find", 0, + this, SLOT( openLDAPDialog() ), actionCollection(), "ldap_lookup" ); + action->setWhatsThis( i18n( "Search for contacts on a LDAP server<p>You will be presented with a dialog, where you can search for contacts and select the ones you want to add to your local address book." ) ); + + mActionWhoAmI = new KAction( i18n( "Set as Personal Contact Data" ), "personal", 0, this, + SLOT( setWhoAmI() ), actionCollection(), + "edit_set_personal" ); + mActionWhoAmI->setWhatsThis( i18n( "Set the personal contact<p>The data of this contact will be used in many other KDE applications, so you do not have to input your personal data several times." ) ); + + mActionCategories = new KAction( i18n( "Select Categories..." ), 0, this, + SLOT( setCategories() ), actionCollection(), + "edit_set_categories" ); + mActionCategories->setWhatsThis( i18n( "Set the categories for all selected contacts." ) ); + + KAction *clearLocation = new KAction( i18n( "Clear Search Bar" ), + QApplication::reverseLayout() ? "clear_left" : "locationbar_erase", + CTRL+Key_L, this, SLOT( slotClearSearchBar() ), actionCollection(), "clear_search" ); + clearLocation->setWhatsThis( i18n( "Clear Search Bar<p>" + "Clears the content of the quick search bar." ) ); + + clipboardDataChanged(); +} + +void KABCore::clipboardDataChanged() +{ + if ( mReadWrite ) + mActionPaste->setEnabled( !QApplication::clipboard()->text().isEmpty() ); +} + +void KABCore::updateIncSearchWidget() +{ + mIncSearchWidget->setViewFields( mViewManager->viewFields() ); +} + +void KABCore::updateCategories() +{ + QStringList categories( allCategories() ); + categories.sort(); + + const QStringList customCategories( KABPrefs::instance()->customCategories() ); + QStringList::ConstIterator it; + const QStringList::ConstIterator endIt( customCategories.end() ); + for ( it = customCategories.begin(); it != endIt; ++it ) { + if ( categories.find( *it ) == categories.end() ) { + categories.append( *it ); + } + } + + KABPrefs::instance()->mCustomCategories = categories; + KABPrefs::instance()->writeConfig(); + + if ( mCategoryEditDialog ) + mCategoryEditDialog->reload(); +} + +QStringList KABCore::allCategories() const +{ + QStringList categories, allCategories; + QStringList::ConstIterator catIt; + + KABC::AddressBook::ConstIterator it; + const KABC::AddressBook::ConstIterator endIt( mAddressBook->end() ); + for ( it = mAddressBook->begin(); it != endIt; ++it ) { + categories = (*it).categories(); + const QStringList::ConstIterator catEndIt( categories.end() ); + for ( catIt = categories.begin(); catIt != catEndIt; ++catIt ) { + if ( !allCategories.contains( *catIt ) ) + allCategories.append( *catIt ); + } + } + + return allCategories; +} + +void KABCore::setCategories() +{ + // Show the category dialog + if ( mCategorySelectDialog == 0 ) { + mCategorySelectDialog = new KPIM::CategorySelectDialog( KABPrefs::instance(), mWidget ); + connect( mCategorySelectDialog, SIGNAL( categoriesSelected( const QStringList& ) ), + SLOT( categoriesSelected( const QStringList& ) ) ); + connect( mCategorySelectDialog, SIGNAL( editCategories() ), SLOT( editCategories() ) ); + } + + mCategorySelectDialog->show(); + mCategorySelectDialog->raise(); +} + +void KABCore::categoriesSelected( const QStringList &categories ) +{ + bool merge = false; + QString msg = i18n( "Merge with existing categories?" ); + if ( KMessageBox::questionYesNo( mWidget, msg, QString::null, i18n( "Merge" ), i18n( "Do Not Merge" ) ) == KMessageBox::Yes ) + merge = true; + + QStringList uids = mViewManager->selectedUids(); + QStringList::ConstIterator it; + const QStringList::ConstIterator endIt( uids.end() ); + for ( it = uids.begin(); it != endIt; ++it ) { + KABC::Addressee addr = mAddressBook->findByUid( *it ); + if ( !addr.isEmpty() ) { + if ( !merge ) + addr.setCategories( categories ); + else { + QStringList addrCategories = addr.categories(); + QStringList::ConstIterator catIt; + const QStringList::ConstIterator catEndIt( categories.end() ); + for ( catIt = categories.begin(); catIt != catEndIt; ++catIt ) { + if ( !addrCategories.contains( *catIt ) ) + addrCategories.append( *catIt ); + } + addr.setCategories( addrCategories ); + } + + mAddressBook->insertAddressee( addr ); + } + } + + if ( uids.count() > 0 ) + setModified( true ); +} + +void KABCore::editCategories() +{ + if ( mCategoryEditDialog == 0 ) { + mCategoryEditDialog = new KPIM::CategoryEditDialog( KABPrefs::instance(), mWidget ); + connect( mCategoryEditDialog, SIGNAL( categoryConfigChanged() ), + mCategorySelectDialog, SLOT( updateCategoryConfig() ) ); + } + + mCategoryEditDialog->show(); + mCategoryEditDialog->raise(); +} + +void KABCore::slotClearSearchBar() +{ + mIncSearchWidget->clear(); + mIncSearchWidget->setFocus(); +} + +void KABCore::slotContactsUpdated() +{ + if ( mStatusBar ) { + QString msg( i18n( "%n contact matches", "%n contacts matching", mSearchManager->contacts().count() ) ); + if ( !mStatusBar->hasItem( 1 ) ) + mStatusBar->insertItem( msg, 1 ); + else + mStatusBar->changeItem( msg, 1 ); + } + + emit contactsUpdated(); +} + +bool KABCore::handleCommandLine( KAddressBookIface* iface ) +{ + KCmdLineArgs *args = KCmdLineArgs::parsedArgs(); + QCString addrStr = args->getOption( "addr" ); + QCString uidStr = args->getOption( "uid" ); + + QString addr, uid, vcard; + if ( !addrStr.isEmpty() ) + addr = QString::fromLocal8Bit( addrStr ); + if ( !uidStr.isEmpty() ) + uid = QString::fromLocal8Bit( uidStr ); + + bool doneSomething = false; + + // Can not see why anyone would pass both a uid and an email address, so I'll leave it that two contact editors will show if they do + if ( !addr.isEmpty() ) { + iface->addEmail( addr ); + doneSomething = true; + } + + if ( !uid.isEmpty() ) { + iface->showContactEditor( uid ); + doneSomething = true; + } + + if ( args->isSet( "new-contact" ) ) { + iface->newContact(); + doneSomething = true; + } + + if ( args->count() >= 1 ) { + for ( int i = 0; i < args->count(); ++i ) + iface->importVCard( args->url( i ).url() ); + doneSomething = true; + } + return doneSomething; +} + +void KABCore::removeSelectedContactsFromDistList() +{ +#ifdef KDEPIM_NEW_DISTRLISTS + + KPIM::DistributionList dist = KPIM::DistributionList::findByName( addressBook(), mSelectedDistributionList ); + if ( dist.isEmpty() ) + return; + const QStringList uids = selectedUIDs(); + if ( uids.isEmpty() ) + return; + for ( QStringList::ConstIterator it = uids.begin(); it != uids.end(); ++it ) { + dist.removeEntry ( *it ); + } + addressBook()->insertAddressee( dist ); + setModified(); +#endif +} + +void KABCore::sendMailToDistributionList( const QString &name ) +{ +#ifdef KDEPIM_NEW_DISTRLISTS + KPIM::DistributionList dist = KPIM::DistributionList::findByName( addressBook(), name ); + if ( dist.isEmpty() ) + return; + typedef KPIM::DistributionList::Entry::List EntryList; + QStringList mails; + const EntryList entries = dist.entries( addressBook() ); + for ( EntryList::ConstIterator it = entries.begin(); it != entries.end(); ++it ) + mails += (*it).addressee.fullEmail( (*it).email ); + sendMail( mails.join( ", " ) ); +#endif +} + +void KABCore::editSelectedDistributionList() +{ +#ifdef KDEPIM_NEW_DISTRLISTS + editDistributionList( KPIM::DistributionList::findByName( addressBook(), mSelectedDistributionList ) ); +#endif +} + + +void KABCore::editDistributionList( const QString &name ) +{ +#ifdef KDEPIM_NEW_DISTRLISTS + editDistributionList( KPIM::DistributionList::findByName( addressBook(), name ) ); +#endif +} + +#ifdef KDEPIM_NEW_DISTRLISTS + +void KABCore::showDistributionListEntry( const QString& uid ) +{ + KPIM::DistributionList dist = KPIM::DistributionList::findByName( addressBook(), mSelectedDistributionList ); + if ( !dist.isEmpty() ) { + mDistListEntryView->clear(); + typedef KPIM::DistributionList::Entry::List EntryList; + const EntryList entries = dist.entries( addressBook() ); + for (EntryList::ConstIterator it = entries.begin(); it != entries.end(); ++it ) { + if ( (*it).addressee.uid() == uid ) { + mDistListEntryView->setEntry( dist, *it ); + break; + } + } + } +} + +void KABCore::editDistributionList( const KPIM::DistributionList &dist ) +{ + if ( dist.isEmpty() ) + return; + QGuardedPtr<KPIM::DistributionListEditor::EditorWidget> dlg = new KPIM::DistributionListEditor::EditorWidget( addressBook(), widget() ); + dlg->setDistributionList( dist ); + if ( dlg->exec() == QDialog::Accepted && dlg ) { + const KPIM::DistributionList newDist = dlg->distributionList(); + if ( newDist != dist ) { + addressBook()->insertAddressee( newDist ); + setModified(); + } + } + delete dlg; +} + + +KPIM::DistributionList::List KABCore::distributionLists() const +{ + return mSearchManager->distributionLists(); +} + +void KABCore::setSelectedDistributionList( const QString &name ) +{ + mSelectedDistributionList = name; + mSearchManager->setSelectedDistributionList( name ); + mViewHeaderLabel->setText( name.isNull() ? i18n( "Contacts" ) : i18n( "Distribution List: %1" ).arg( name ) ); + mDistListButtonWidget->setShown( !mSelectedDistributionList.isNull() ); + if ( !name.isNull() ) { + mDetailsStack->raiseWidget( mDistListEntryView ); + const QStringList selectedUids = selectedUIDs(); + showDistributionListEntry( selectedUids.isEmpty() ? QString() : selectedUids.first() ); + } + else + mDetailsStack->raiseWidget( mExtensionManager->activeDetailsWidget() ? mExtensionManager->activeDetailsWidget() : mDetailsWidget ); +} + +QStringList KABCore::distributionListNames() const +{ + return mSearchManager->distributionListNames(); +} +#endif + +#include "kabcore.moc" diff --git a/kaddressbook/kabcore.h b/kaddressbook/kabcore.h new file mode 100644 index 000000000..8cb2bc4d5 --- /dev/null +++ b/kaddressbook/kabcore.h @@ -0,0 +1,497 @@ +/* + 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 KABCORE_H +#define KABCORE_H + +#include <kabc/field.h> + +#include <qdict.h> +#include <qlabel.h> +#include <qwidget.h> + +#include "core.h" +#include <kdepimmacros.h> + +namespace KABC { +class AddressBook; +class Ticket; +} + +namespace KPIM { +class AddresseeView; +class CategoryEditDialog; +class CategorySelectDialog; +} + +class KAboutData; +class KAction; +class KActionCollection; +class KConfig; +class KStatusBar; +class KToggleAction; +class KXMLGUIClient; + +class QSplitter; +class QHBoxLayout; +class QWidgetStack; + +class AddresseeEditorDialog; +class ExtensionManager; +class FilterSelectionWidget; +class IncSearchWidget; +class JumpButtonBar; +class KAddressBookIface; +class KAddressBookService; +class KIMProxy; +class LDAPSearchDialog; +class ViewManager; +class XXPortManager; + +namespace KAB { + class DistributionListEntryView; +} + +typedef struct { + KABC::Ticket *ticket; + int counter; +} ResourceMapEntry; + +class KDE_EXPORT KABCore : public KAB::Core +{ + Q_OBJECT + + public: + KABCore( KXMLGUIClient *client, bool readWrite, QWidget *parent, + const QString &file = QString::null, const char *name = 0 ); + ~KABCore(); + + /** + Restores the global settings. + */ + void restoreSettings(); + + /** + Saves the global settings. + */ + void saveSettings(); + + /** + Returns a pointer to the StdAddressBook of the application. + */ + KABC::AddressBook *addressBook() const; + + /** + Returns a pointer to the KConfig object of the application. + */ + KConfig *config() const; + + /** + Returns a pointer to the global KActionCollection object. So + other classes can register their actions easily. + */ + KActionCollection *actionCollection() const; + + /** + Returns the current sort field of the view. + */ + KABC::Field *currentSortField() const; + + /** + Returns the uid list of the currently selected contacts. + */ + QStringList selectedUIDs() const; + + /** + Displays the ResourceSelectDialog and returns the selected + resource or a null pointer if no resource was selected by + the user. + */ + KABC::Resource *requestResource( QWidget *parent ); + + /** + Returns the parent widget. + */ + QWidget *widget() const; + + static KAboutData *createAboutData(); + + void setStatusBar( KStatusBar *statusBar ); + + KStatusBar *statusBar() const; + + KAB::SearchManager *searchManager() const { return mSearchManager; } + + KCommandHistory *commandHistory() const { return mCommandHistory; } + +#ifdef KDEPIM_NEW_DISTRLISTS + /** + Returns all the distribution lists. + */ + virtual KPIM::DistributionList::List distributionLists() const; + + /** + Returns the name of all the distribution lists. + */ + virtual QStringList distributionListNames() const; + + /** + sets the distribution list to display. If null, the regular + address book is to be displayed. + */ + virtual void setSelectedDistributionList( const QString &name ); +#endif + + public slots: + /** + Is called whenever a contact is selected in the view. + */ + void setContactSelected( const QString &uid ); + + /** + Opens the preferred mail composer with all selected contacts as + arguments. + */ + void sendMail(); + + /** + Opens the preferred mail composer with the given contacts as + arguments. + */ + void sendMail( const QString& email ); + + + void mailVCard(); + void mailVCard(const QStringList& uids); + + /** + * Start an Instant Messaging chat with the selected contacts + */ + void startChat(); + + /** + Starts the preferred web browser with the given URL as argument. + */ + void browse( const QString& url ); + + /** + Select all contacts in the view. + */ + void selectAllContacts(); + + /** + Deletes all selected contacts from the address book. + */ + void deleteContacts(); + + /** + Deletes given contacts from the address book. + + @param uids The uids of the contacts, which shall be deleted. + */ + void deleteContacts( const QStringList &uids ); + + /** + Deletes given distribution lists from the address book. + + @param uids The names of the distribution lists which shall be deleted. + */ + void deleteDistributionLists( const QStringList &names ); + + + /** + Copys the selected contacts into clipboard for later pasting. + */ + void copyContacts(); + + /** + Cuts the selected contacts and stores them for later pasting. + */ + void cutContacts(); + + /** + Paste contacts from clipboard into the address book. + */ + void pasteContacts(); + + /** + Paste given contacts into the address book. + + @param list The list of addressee, which shall be pasted. + */ + void pasteContacts( KABC::Addressee::List &list ); + + + /** + Merge the selected contacts in a single one. + */ + void mergeContacts(); + + /** + Sets the whoAmI contact, that is used by many other programs to + get personal information about the current user. + */ + void setWhoAmI(); + + /** + Displays the category dialog and applies the result to all + selected contacts. + */ + void setCategories(); + + /** + Search with the current search field for a contact, that matches + the given text, and selects it in the view. + */ + void incrementalTextSearch( const QString& text ); + + void incrementalJumpButtonSearch( const QString& characters ); + + /** + Marks the address book as modified. + */ + void setModified(); + + /** + Marks the address book as modified concerning the argument. + */ + void setModified( bool modified ); + + /** + Returns whether the address book is modified. + */ + bool modified() const; + + /** + Called whenever an contact is modified in the contact editor + dialog or the quick edit. + */ + void contactModified( const KABC::Addressee &addr ); + + /** + DCOP METHOD: Adds the given email address to address book. + */ + virtual void addEmail( const QString& addr ); + + /** + DCOP METHOD: Imports the vCard, located at the given url. + */ + virtual void importVCard( const KURL& url ); + + /** + DCOP METHOD: Imports the given vCard. + */ + virtual void importVCardFromData( const QString& vCard ); + + /** + DCOP METHOD: Opens contact editor to input a new contact. + */ + virtual void newContact(); + + /** + DCOP METHOD: Opens distribution list editor to create a new distribution list + */ + virtual void newDistributionList(); + + /** + DCOP METHOD: Returns the name of the contact, that matches the given + phone number. + */ + virtual QString getNameByPhone( const QString& phone ); + + /** + DCOP METHOD: Handle command line arguments, return true if handled + and false if no args was given. The iface is either the mainwin or the part. + */ + bool handleCommandLine( KAddressBookIface* iface ); + + + /** + Saves the contents of the AddressBook back to disk. + */ + void save(); + + /** + Shows the edit dialog for the given uid. If the uid is QString::null, + the method will try to find a selected addressee in the view. + */ + void editContact( const QString &uid = QString::null ); + + /** + * Let the user chose a different resource for the selected contacts. + * If the adding to the new resource is successfull, the contact is + * removed from the old one, unless the Copy flag is given. */ + void storeContactIn( const QString &uid = QString::null, bool copy = false ); + + /** + * Lets the user chose a different resource for the selected contacts and + * copies it there. + */ + void copySelectedContactToResource(); + + /** + * Lets the user chose a different resource for the selected contacts and + * moves it there. + */ + void moveSelectedContactToResource(); + + /** + Launches the ldap search dialog. + */ + void openLDAPDialog(); + + /** + Opens the settings dialog. + */ + void configure(); + + /** + Creates a KAddressBookPrinter, which will display the print + dialog and do the printing. + */ + void print(); + + void detailsHighlighted( const QString& ); + + void showContactsAddress( const QString &uid ); + + void configurationChanged(); + + bool queryClose(); + + /** + Is called whenever the xmlgui has to be rebuild after a part switch. + */ + void reinitXMLGUI(); + + private: + +#ifdef KDEPIM_NEW_DISTRLISTS + void editDistributionList( const KPIM::DistributionList &list ); + void showDistributionListEntry( const QString &uid ); +#endif + + private slots: + void setJumpButtonBarVisible( bool visible ); + void setDetailsVisible( bool visible ); + + void extensionModified( const KABC::Addressee::List &list ); + void extensionDeleted( const QStringList &uidList ); + void clipboardDataChanged(); + void updateIncSearchWidget(); + + void slotEditorDestroyed( const QString &uid ); + void delayedAddressBookChanged(); + void addressBookChanged(); + + void categoriesSelected( const QStringList& ); + void editCategories(); + void slotClearSearchBar(); + void slotContactsUpdated(); + + void activateDetailsWidget( QWidget *widget ); + void deactivateDetailsWidget( QWidget *widget ); + + void editDistributionList( const QString &name ); + + void removeSelectedContactsFromDistList(); + void editSelectedDistributionList(); + void sendMailToDistributionList( const QString &id ); + + private: + void initGUI(); + void createJumpButtonBar(); + void initActions(); + + void updateCategories(); + QStringList allCategories() const; + + AddresseeEditorDialog *createAddresseeEditorDialog( QWidget *parent, + const char *name = 0 ); + + QWidget *mWidget; + KABC::AddressBook *mAddressBook; + KStatusBar *mStatusBar; + + ViewManager *mViewManager; + QLabel *mViewHeaderLabel; + +#ifdef KDEPIM_NEW_DISTRLISTS + QString mSelectedDistributionList; + QWidget *mDistListButtonWidget; +#endif + + ExtensionManager *mExtensionManager; + XXPortManager *mXXPortManager; + + JumpButtonBar *mJumpButtonBar; + FilterSelectionWidget *mFilterSelectionWidget; + IncSearchWidget *mIncSearchWidget; + KAB::DistributionListEntryView* mDistListEntryView; + KPIM::AddresseeView *mDetailsViewer; + KPIM::CategorySelectDialog *mCategorySelectDialog; + KPIM::CategoryEditDialog *mCategoryEditDialog; + QWidget *mDetailsPage; + QWidget *mDetailsWidget; + QHBoxLayout *mDetailsLayout; + QSplitter *mDetailsSplitter; + QSplitter *mLeftSplitter; + QWidgetStack *mDetailsStack; + LDAPSearchDialog *mLdapSearchDialog; + QDict<AddresseeEditorDialog> mEditorDict; + + bool mReadWrite; + bool mModified; + bool mIsPart; + + QTimer *mAddressBookChangedTimer; + + KAction *mActionPaste; + KAction *mActionCut; + KAction *mActionDelete; + KAction *mActionCopy; + KAction *mActionEditAddressee; + KAction *mActionMoveAddresseeTo; + KAction *mActionCopyAddresseeTo; + KAction *mActionMerge; + KAction *mActionMail; + KAction *mActionMailVCard; + KAction *mActionChat; + KAction *mActionSave; + KAction *mActionDeleteView; + KAction *mActionWhoAmI; + KAction *mActionCategories; + KToggleAction *mActionJumpBar; + KToggleAction *mActionDetails; + KCommandHistory *mCommandHistory; + + KAddressBookService *mAddressBookService; + + KAB::SearchManager *mSearchManager; + // KIMProxy provides access to up to date instant messaging presence data + ::KIMProxy *mKIMProxy; + class KABCorePrivate; + KABCorePrivate *d; +}; + +#endif diff --git a/kaddressbook/kablock.cpp b/kaddressbook/kablock.cpp new file mode 100644 index 000000000..acb6c2870 --- /dev/null +++ b/kaddressbook/kablock.cpp @@ -0,0 +1,108 @@ +/* + 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 <kabc/addressbook.h> +#include <kabc/resource.h> +#include <klocale.h> +#include <kmessagebox.h> +#include <kstaticdeleter.h> + +#include "kablock.h" + +class AddressBookWrapper : public KABC::AddressBook +{ + public: + AddressBookWrapper( KABC::AddressBook* ); + + KABC::Resource* getStandardResource() + { + return standardResource(); + } +}; + +KABLock *KABLock::mSelf = 0; + +static KStaticDeleter<KABLock> kabLockDeleter; + +KABLock::KABLock( KABC::AddressBook *ab ) + : mAddressBook( ab ) +{ +} + +KABLock::~KABLock() +{ +} + +KABLock *KABLock::self( KABC::AddressBook *ab ) +{ + if ( !mSelf ) + kabLockDeleter.setObject( mSelf, new KABLock( ab ) ); + else + mSelf->mAddressBook = ab; + + return mSelf; +} + +bool KABLock::lock( KABC::Resource *resource ) +{ + if ( mLocks.find( resource ) == mLocks.end() ) { // not locked yet + KABC::Ticket *ticket = mAddressBook->requestSaveTicket( resource ); + if ( !ticket ) { + return false; + } else { + LockEntry entry; + entry.ticket = ticket; + entry.counter = 1; + mLocks.insert( resource, entry ); + } + } else { + LockEntry &entry = mLocks[ resource ]; + entry.counter++; + } + + return true; +} + +bool KABLock::unlock( KABC::Resource *resource ) +{ + AddressBookWrapper *wrapper = static_cast<AddressBookWrapper*>( mAddressBook ); + if ( resource == 0 ) + resource = wrapper->getStandardResource(); + + if ( mLocks.find( resource ) == mLocks.end() ) { // hmm, not good... + return false; + } else { + LockEntry &entry = mLocks[ resource ]; + entry.counter--; + + if ( entry.counter == 0 ) { + mAddressBook->save( entry.ticket ); +// # Activate in KDE 4.0 +// mAddressBook->releaseSaveTicket( entry.ticket ); + + mLocks.remove( resource ); + } + } + + return true; +} diff --git a/kaddressbook/kablock.h b/kaddressbook/kablock.h new file mode 100644 index 000000000..d75d963af --- /dev/null +++ b/kaddressbook/kablock.h @@ -0,0 +1,58 @@ +/* + 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 KABLOCK_H +#define KABLOCK_H + +namespace KABC { +class AddressBook; +class Resource; +class Ticket; +} + +typedef struct { + KABC::Ticket *ticket; + uint counter; +} LockEntry; + +class KABLock +{ + public: + ~KABLock(); + + static KABLock *self( KABC::AddressBook *ab ); + + bool lock( KABC::Resource* ); + bool unlock( KABC::Resource* ); + + protected: + KABLock( KABC::AddressBook *ab ); + + private: + static KABLock *mSelf; + + QMap<KABC::Resource*, LockEntry> mLocks; + KABC::AddressBook *mAddressBook; +}; + +#endif diff --git a/kaddressbook/kabtools.cpp b/kaddressbook/kabtools.cpp new file mode 100644 index 000000000..c3b1d05bc --- /dev/null +++ b/kaddressbook/kabtools.cpp @@ -0,0 +1,268 @@ +/* + This file is part of KAddressBook. + Copyright (c) 2005 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 <kabc/addressbook.h> +#include <kabc/vcardconverter.h> +#include <kapplication.h> +#include <kdebug.h> +#include <ktempdir.h> + +#include <qfile.h> + +#include "kabtools.h" + +static QString uniqueFileName( const KABC::Addressee &addressee, QStringList &existingFiles ) +{ + QString name; + QString uniquePart; + + uint number = 0; + do { + name = addressee.givenName() + "_" + addressee.familyName() + uniquePart + ".vcf"; + name.replace( ' ', '_' ); + name.replace( '/', '_' ); + + ++number; + uniquePart = QString( "_%1" ).arg( number ); + } while ( existingFiles.contains( name ) ); + + existingFiles.append( name ); + + return name; +} + +void KABTools::mailVCards( const QStringList &uids, KABC::AddressBook *ab ) +{ + KURL::List urls; + + KTempDir tempDir; + if ( tempDir.status() != 0 ) { + kdWarning() << strerror( tempDir.status() ) << endl; + return; + } + + QStringList existingFiles; + QStringList::ConstIterator it( uids.begin() ); + const QStringList::ConstIterator endIt( uids.end() ); + for ( ; it != endIt; ++it ) { + KABC::Addressee addressee = ab->findByUid( *it ); + + if ( addressee.isEmpty() ) + continue; + + QString fileName = uniqueFileName( addressee, existingFiles ); + + QString path = tempDir.name() + "/" + fileName; + + QFile file( path ); + + if ( file.open( IO_WriteOnly ) ) { + KABC::VCardConverter converter; + KABC::Addressee::List list; + list.append( addressee ); + QString vcard = converter.createVCards( list, KABC::VCardConverter::v3_0 ); + + QTextStream t( &file ); + t.setEncoding( QTextStream::UnicodeUTF8 ); + t << vcard; + + file.close(); + + KURL url( path ); + url.setFileEncoding( "UTF-8" ); + urls.append( url ); + } + } + + kapp->invokeMailer( QString::null, QString::null, QString::null, + QString::null, + QString::null, + QString::null, + urls.toStringList() ); +} + +static void mergePictures( KABC::Picture &master, const KABC::Picture &slave ) +{ + if ( master.isIntern() ) { + if ( master.data().isNull() ) { + if ( slave.isIntern() && !slave.data().isNull() ) + master.setData( slave.data() ); + else if ( !slave.isIntern() && !slave.url().isEmpty() ) + master.setUrl( slave.url() ); + } + } else { + if ( master.url().isEmpty() ) { + if ( slave.isIntern() && !slave.data().isNull() ) + master.setData( slave.data() ); + else if ( !slave.isIntern() && !slave.url().isEmpty() ) + master.setUrl( slave.url() ); + } + } +} + +KABC::Addressee KABTools::mergeContacts( const KABC::Addressee::List &list ) +{ + if ( list.count() == 0 ) //emtpy + return KABC::Addressee(); + else if ( list.count() == 1 ) // nothing to merge + return list.first(); + + KABC::Addressee masterAddressee = list.first(); + + KABC::Addressee::List::ConstIterator contactIt( list.begin() ); + const KABC::Addressee::List::ConstIterator contactEndIt( list.end() ); + for ( ++contactIt; contactIt != contactEndIt; ++contactIt ) { + // ADR + LABEL + const KABC::Address::List addresses = (*contactIt).addresses(); + KABC::Address::List masterAddresses = masterAddressee.addresses(); + KABC::Address::List::ConstIterator addrIt( addresses.begin() ); + const KABC::Address::List::ConstIterator addrEndIt( addresses.end() ); + for ( ; addrIt != addrEndIt; ++addrIt ) { + if ( !masterAddresses.contains( *addrIt ) ) + masterAddressee.insertAddress( *addrIt ); + } + + // BIRTHDAY + if ( masterAddressee.birthday().isNull() && !(*contactIt).birthday().isNull() ) + masterAddressee.setBirthday( (*contactIt).birthday() ); + + // CATEGORIES + const QStringList categories = (*contactIt).categories(); + const QStringList masterCategories = masterAddressee.categories(); + QStringList newCategories( masterCategories ); + QStringList::ConstIterator it( categories.begin() ); + QStringList::ConstIterator endIt( categories.end() ); + for ( it = categories.begin(); it != endIt; ++it ) + if ( !masterCategories.contains( *it ) ) + newCategories.append( *it ); + masterAddressee.setCategories( newCategories ); + + // CLASS + if ( !masterAddressee.secrecy().isValid() && (*contactIt).secrecy().isValid() ) + masterAddressee.setSecrecy( (*contactIt).secrecy() ); + + // EMAIL + const QStringList emails = (*contactIt).emails(); + const QStringList masterEmails = masterAddressee.emails(); + endIt = emails.end(); + for ( it = emails.begin(); it != endIt; ++it ) + if ( !masterEmails.contains( *it ) ) + masterAddressee.insertEmail( *it, false ); + + // FN + if ( masterAddressee.formattedName().isEmpty() && !(*contactIt).formattedName().isEmpty() ) + masterAddressee.setFormattedName( (*contactIt).formattedName() ); + + // GEO + if ( !masterAddressee.geo().isValid() && (*contactIt).geo().isValid() ) + masterAddressee.setGeo( (*contactIt).geo() ); + +/* + // KEY +*/ + // LOGO + KABC::Picture logo = masterAddressee.logo(); + mergePictures( logo, (*contactIt).logo() ); + masterAddressee.setLogo( logo ); + + // MAILER + if ( masterAddressee.mailer().isEmpty() && !(*contactIt).mailer().isEmpty() ) + masterAddressee.setMailer( (*contactIt).mailer() ); + + // N + if ( masterAddressee.assembledName().isEmpty() && !(*contactIt).assembledName().isEmpty() ) + masterAddressee.setNameFromString( (*contactIt).assembledName() ); + + // NICKNAME + if ( masterAddressee.nickName().isEmpty() && !(*contactIt).nickName().isEmpty() ) + masterAddressee.setNickName( (*contactIt).nickName() ); + + // NOTE + if ( masterAddressee.note().isEmpty() && !(*contactIt).note().isEmpty() ) + masterAddressee.setNote( (*contactIt).note() ); + + // ORG + if ( masterAddressee.organization().isEmpty() && !(*contactIt).organization().isEmpty() ) + masterAddressee.setOrganization( (*contactIt).organization() ); + + // PHOTO + KABC::Picture photo = masterAddressee.photo(); + mergePictures( photo, (*contactIt).photo() ); + masterAddressee.setPhoto( photo ); + + // PROID + if ( masterAddressee.productId().isEmpty() && !(*contactIt).productId().isEmpty() ) + masterAddressee.setProductId( (*contactIt).productId() ); + + // REV + if ( masterAddressee.revision().isNull() && !(*contactIt).revision().isNull() ) + masterAddressee.setRevision( (*contactIt).revision() ); + + // ROLE + if ( masterAddressee.role().isEmpty() && !(*contactIt).role().isEmpty() ) + masterAddressee.setRole( (*contactIt).role() ); + + // SORT-STRING + if ( masterAddressee.sortString().isEmpty() && !(*contactIt).sortString().isEmpty() ) + masterAddressee.setSortString( (*contactIt).sortString() ); + +/* + // SOUND +*/ + + // TEL + const KABC::PhoneNumber::List phones = (*contactIt).phoneNumbers(); + const KABC::PhoneNumber::List masterPhones = masterAddressee.phoneNumbers(); + KABC::PhoneNumber::List::ConstIterator phoneIt( phones.begin() ); + const KABC::PhoneNumber::List::ConstIterator phoneEndIt( phones.end() ); + for ( ; phoneIt != phoneEndIt; ++phoneIt ) + if ( !masterPhones.contains( *phoneIt ) ) + masterAddressee.insertPhoneNumber( *phoneIt ); + + // TITLE + if ( masterAddressee.title().isEmpty() && !(*contactIt).title().isEmpty() ) + masterAddressee.setTitle( (*contactIt).title() ); + + // TZ + if ( !masterAddressee.timeZone().isValid() && (*contactIt).timeZone().isValid() ) + masterAddressee.setTimeZone( (*contactIt).timeZone() ); + + // UID // ignore UID + + // URL + if ( masterAddressee.url().isEmpty() && !(*contactIt).url().isEmpty() ) + masterAddressee.setUrl( (*contactIt).url() ); + + // X- + const QStringList customs = (*contactIt).customs(); + const QStringList masterCustoms = masterAddressee.customs(); + QStringList newCustoms( masterCustoms ); + endIt = customs.end(); + for ( it = customs.begin(); it != endIt; ++it ) + if ( !masterCustoms.contains( *it ) ) + newCustoms.append( *it ); + masterAddressee.setCustoms( newCustoms ); + } + + return masterAddressee; +} diff --git a/kaddressbook/kabtools.h b/kaddressbook/kabtools.h new file mode 100644 index 000000000..5cf402925 --- /dev/null +++ b/kaddressbook/kabtools.h @@ -0,0 +1,45 @@ +/* + This file is part of KAddressBook. + Copyright (c) 2005 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 KABTOOLS_H +#define KABTOOLS_H + +namespace KABC { +class AddressBook; +} + +class KABTools +{ + public: + /** + Sends a mail with vCards as attachments for all given UIDs. + */ + static void mailVCards( const QStringList &uids, KABC::AddressBook *ab ); + + /** + Merges all passed contacts to a single one. + */ + static KABC::Addressee mergeContacts( const KABC::Addressee::List &list ); +}; + +#endif diff --git a/kaddressbook/kaddressbook.desktop b/kaddressbook/kaddressbook.desktop new file mode 100644 index 000000000..92a1ee73a --- /dev/null +++ b/kaddressbook/kaddressbook.desktop @@ -0,0 +1,82 @@ +[Desktop Entry] +Name=KAddressBook +Name[cy]=KAddressBook/LlyfrKyfeiriadau +Name[de]=Adressbuch +Name[et]=KDE aadressiraamat +Name[eu]=Helbide-liburua +Name[fi]=Osoitekirja +Name[fr]=Carnet d'adresses +Name[he]=פנקס כתובות +Name[mk]=КАдресар +Name[nds]=KAdressbook +Name[ne]=केडीई ठेगाना पुस्तिका +Name[nn]=KDE-adressebok +Name[pl]=Książka adresowa +Name[sk]=Adresár +Name[sv]=Adressbok +Name[ta]=கேமுகவரிப் புத்தகம் +Name[tr]=KDE Adres Defteri +Name[zh_TW]=KAddressBook 通訊錄 +GenericName=Address Manager +GenericName[af]=Adres Bestuurder +GenericName[bg]=Адресник +GenericName[br]=Merour ar chomlec'hioù +GenericName[ca]=Gestor d'adreces +GenericName[cs]=Správce adres +GenericName[cy]=Rheolydd Cyfeiriadau +GenericName[da]=Adressehåndtering +GenericName[de]=Adressverwaltung +GenericName[el]=Διαχειριστής διευθύνσεων +GenericName[eo]=Adresadministrilo +GenericName[es]=Gestor de direcciones +GenericName[et]=Aadressihaldur +GenericName[eu]=Helbide kudeatzailea +GenericName[fa]=مدیر نشانی +GenericName[fi]=Osoitteenhallinta +GenericName[fr]=Gestionnaire d'adresses +GenericName[fy]=Adresboekbehearder +GenericName[ga]=Bainisteoir na Seoltaí +GenericName[gl]=Xestor de Enderezos +GenericName[he]=מנהל הכתובות +GenericName[hu]=Címjegyzékkezelő +GenericName[is]=Vistfangastjóri +GenericName[it]=Gestore degli indirizzi +GenericName[ja]=アドレスマネージャ +GenericName[ka]=წიგნაკის მმართველი +GenericName[kk]=Адрестік кітапшасы +GenericName[km]=កម្មវិធីគ្រប់គ្រងអាសយដ្ឋាន +GenericName[lt]=Adresų tvarkyklė +GenericName[mk]=Менаџер на адреси +GenericName[ms]=Pengurus Alamat +GenericName[nb]=Addressehåndterer +GenericName[nds]=Adresspleger +GenericName[ne]=ठेगाना प्रबन्धक +GenericName[nl]=Adresboekbeheerder +GenericName[nn]=Adressehandterar +GenericName[pa]=ਸਿਰਨਾਵਾਂ ਪ੍ਰਬੰਧਕ +GenericName[pl]=Menedżer adresów +GenericName[pt]=Livro de Endereços +GenericName[pt_BR]=Livro de Endereços +GenericName[ru]=Адресная книга +GenericName[se]=Čujuhusgieđahalli +GenericName[sk]=Správca adries +GenericName[sl]=Upravitelj naslovov +GenericName[sr]=Менаџер адреса +GenericName[sr@Latn]=Menadžer adresa +GenericName[sv]=Adresshanterare +GenericName[ta]=முகவரி மேலாளர் +GenericName[tr]=Adres Yöneticisi +GenericName[uk]=Менеджер адрес +GenericName[zh_CN]=地址管理器 +Exec=kaddressbook %u +Icon=kaddressbook +Type=Application +DocPath=kaddressbook/index.html +Terminal=false +X-KDE-StartupNotify=true +X-DCOP-ServiceType=Unique +X-DCOP-ServiceName=kaddressbook +MimeType=text/x-vcard;text/x-ldif; +ServiceTypes=KParts/ReadOnlyPart,Browser/View,DCOP/AddressBook +X-KDE-Library=libkaddressbookpart +Categories=Qt;KDE;Office;ContactManagement; diff --git a/kaddressbook/kaddressbook_options.h b/kaddressbook/kaddressbook_options.h new file mode 100644 index 000000000..9439870bb --- /dev/null +++ b/kaddressbook/kaddressbook_options.h @@ -0,0 +1,43 @@ +/* + This file is part of KAddressBook. + Copyright (C) 1999 Don Sanders <sanders@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 KADDRESSBOOK_OPTIONS_H +#define KADDRESSBOOK_OPTIONS_H + +#include <kcmdlineargs.h> +#include <klocale.h> + +static KCmdLineOptions kaddressbook_options[] = +{ + { "a", 0 , 0 }, + { "addr <email>", I18N_NOOP( "Shows contact editor with given email address" ), 0 }, + { "uid <uid>", I18N_NOOP( "Shows contact editor with given uid" ), 0 }, + { "editor-only", I18N_NOOP( "Launches in editor only mode" ), 0 }, + { "new-contact", I18N_NOOP( "Launches editor for the new contact" ), 0 }, + { "document <file>", I18N_NOOP( "Work on given file" ), 0 }, + { "+[URL]", I18N_NOOP( "Import the given vCard" ), 0 }, + KCmdLineLastOption +}; + +#endif /* KADDRESSBOOK_OPTIONS_H */ + diff --git a/kaddressbook/kaddressbook_part.cpp b/kaddressbook/kaddressbook_part.cpp new file mode 100644 index 000000000..f2a23ec4f --- /dev/null +++ b/kaddressbook/kaddressbook_part.cpp @@ -0,0 +1,179 @@ +/* + This file is part of KAddressbook. + Copyright (c) 2000 Cornelius Schumacher <schumacher@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 <qlayout.h> + +#include <kaction.h> +#include <kapplication.h> +#include <kdebug.h> +#include <kiconloader.h> +#include <kinstance.h> +#include <klocale.h> +#include <kparts/genericfactory.h> +#include <kparts/statusbarextension.h> +#include <kstatusbar.h> + +#include "kabcore.h" +#include "kabprefs.h" +#include "kaddressbookiface.h" + +#include "kaddressbook_part.h" + +typedef KParts::GenericFactory< KAddressbookPart > KAddressbookFactory; +K_EXPORT_COMPONENT_FACTORY( libkaddressbookpart, KAddressbookFactory ) + +KAddressbookPart::KAddressbookPart( QWidget *parentWidget, const char *widgetName, + QObject *parent, const char *name, + const QStringList & ) + : DCOPObject( "KAddressBookIface" ), KParts::ReadOnlyPart( parent, name ) +{ + setInstance( KAddressbookFactory::instance() ); + + // create a canvas to insert our widget + QWidget *canvas = new QWidget( parentWidget, widgetName ); + canvas->setFocusPolicy( QWidget::ClickFocus ); + setWidget( canvas ); + + QVBoxLayout *topLayout = new QVBoxLayout( canvas ); + + KGlobal::iconLoader()->addAppDir( "kaddressbook" ); + + mCore = new KABCore( this, true, canvas ); + mCore->restoreSettings(); + topLayout->addWidget( mCore->widget() ); + + KParts::StatusBarExtension *statusBar = new KParts::StatusBarExtension( this ); + mCore->setStatusBar( statusBar->statusBar() ); + + setXMLFile( "kaddressbook_part.rc" ); +} + +KAddressbookPart::~KAddressbookPart() +{ + mCore->save(); + mCore->saveSettings(); + + KABPrefs::instance()->writeConfig(); + closeURL(); +} + +KAboutData *KAddressbookPart::createAboutData() +{ + return KABCore::createAboutData(); +} + +void KAddressbookPart::addEmail( QString addr ) +{ + mCore->addEmail( addr ); +} + +void KAddressbookPart::importVCard( const KURL& url ) +{ + mCore->importVCard( url ); +} + +void KAddressbookPart::importVCardFromData( const QString& vCard ) +{ + mCore->importVCardFromData( vCard ); +} + +ASYNC KAddressbookPart::showContactEditor( QString uid ) +{ + mCore->editContact( uid ); +} + +void KAddressbookPart::newContact() +{ + mCore->newContact(); +} + + +void KAddressbookPart::newDistributionList() +{ + mCore->newDistributionList(); +} + +QString KAddressbookPart::getNameByPhone( QString phone ) +{ + return mCore->getNameByPhone( phone ); +} + +void KAddressbookPart::save() +{ + mCore->save(); +} + +void KAddressbookPart::exit() +{ + mCore->queryClose(); + + delete this; +} + +bool KAddressbookPart::openURL( const KURL &url ) +{ + kdDebug(5720) << "KAddressbookPart:openFile()" << endl; + + mCore->widget()->show(); + + if ( !url.isEmpty() ) + mCore->importVCard( url ); + + emit setWindowCaption( url.prettyURL() ); + + return true; +} + +bool KAddressbookPart::openFile() +{ + return false; +} + +bool KAddressbookPart::handleCommandLine() +{ + return mCore->handleCommandLine( this ); +} + +void KAddressbookPart::guiActivateEvent( KParts::GUIActivateEvent *e ) +{ + kdDebug(5720) << "KAddressbookPart::guiActivateEvent" << endl; + KParts::ReadOnlyPart::guiActivateEvent( e ); + + if ( e->activated() ) + mCore->reinitXMLGUI(); + + if ( !e->activated() ) { + mCore->statusBar()->removeItem( 1 ); + mCore->statusBar()->removeItem( 2 ); + } +} + +void KAddressbookPart::loadProfile( const QString& ) +{ +} + +void KAddressbookPart::saveToProfile( const QString& ) const +{ +} + +#include "kaddressbook_part.moc" diff --git a/kaddressbook/kaddressbook_part.h b/kaddressbook/kaddressbook_part.h new file mode 100644 index 000000000..da1fbf6fc --- /dev/null +++ b/kaddressbook/kaddressbook_part.h @@ -0,0 +1,71 @@ +/* + This file is part of KAddressbook. + Copyright (c) 2000 Cornelius Schumacher <schumacher@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 KADDRESSBOOK_PART_H +#define KADDRESSBOOK_PART_H + +#include <kparts/event.h> +#include <kparts/factory.h> +#include <kparts/part.h> + +#include "kaddressbookiface.h" + +class KAboutData; +class KInstance; + +class KABCore; + +class KAddressbookPart: public KParts::ReadOnlyPart, virtual public KAddressBookIface +{ + Q_OBJECT + + public: + KAddressbookPart( QWidget *parentWidget, const char *widgetName, + QObject *parent, const char *name, const QStringList& ); + virtual ~KAddressbookPart(); + + static KAboutData *createAboutData(); + + virtual void saveToProfile( const QString& path ) const; + virtual void loadProfile( const QString& path ); + public slots: + virtual void addEmail( QString addr ); + virtual void importVCard( const KURL& url ); + virtual void importVCardFromData( const QString& vCard ); + virtual ASYNC showContactEditor( QString uid ); + virtual void newContact(); + virtual void newDistributionList(); + virtual QString getNameByPhone( QString phone ); + virtual void save(); + virtual void exit(); + virtual bool openURL( const KURL &url ); + virtual bool handleCommandLine(); + + protected: + virtual bool openFile(); + virtual void guiActivateEvent( KParts::GUIActivateEvent* ); + + private: + KABCore *mCore; +}; + +#endif diff --git a/kaddressbook/kaddressbook_part.rc b/kaddressbook/kaddressbook_part.rc new file mode 100644 index 000000000..42b8074c1 --- /dev/null +++ b/kaddressbook/kaddressbook_part.rc @@ -0,0 +1,112 @@ +<!DOCTYPE kpartgui> +<kpartgui name="kaddressbook" version="23"> + + <MenuBar> + <Menu name="file" noMerge="1"><text>&File</text> + <Menu name="file_new_actions_menu"><text>New</text> + <Action name="file_new_contact"/> + <Action name="file_new_distributionlist"/> + </Menu> + <Separator/> + <Action name="file_sync"/> + <Menu name="file_import"><text>&Import</text> + </Menu> + <Menu name="file_export"><text>&Export</text> + </Menu> + <Separator/> + <Action name="file_print"/> + <Action name="file_mail"/> + <Action name="file_mail_vcard"/> + <Action name="file_chat"/> + <Separator/> + <Action name="file_quit"/> + </Menu> + + <Menu name="edit" noMerge="1"><text>&Edit</text> + <Action name="edit_undo"/> + <Action name="edit_redo"/> + <Separator/> + <Action name="edit_cut"/> + <Action name="edit_copy"/> + <Action name="edit_paste"/> + <Action name="copy_contact_to"/> + <Action name="move_contact_to"/> + <Separator/> + <Action name="edit_delete" append="edit_paste_merge"/> + <Separator/> + <Action name="edit_select_all"/> + <Separator/> + <Action name="edit_merge"/> + <Action name="edit_set_categories"/> + <Action name="edit_set_personal"/> + </Menu> + + <Menu name="view" noMerge="1"><text>&View</text> + <Action name="select_view"/> + <Action name="view_add"/> + <Action name="view_modify"/> + <Action name="view_delete"/> + <Separator/> + <ActionList name="extensions_list"/> + <Separator/> + <Action name="view_refresh"/> + </Menu> + + <Menu name="tools" noMerge="1"><text>Tools</text> + <Action name="ldap_lookup"/> + </Menu> + + <Menu name="settings" noMerge="1"><text>&Settings</text> + <Merge name="StandardToolBarMenuHandler" /> + <Action name="options_show_jump_bar"/> + <Action name="options_show_details"/> + <Action name="options_show_statusbar"/> + <Merge name="show_merge"/> + <Separator/> + <Merge/> + <Action name="options_edit_filters"/> + <Separator/> + <Action name="kaddressbook_configure" group="settings_configure"/> + </Menu> + </MenuBar> + + <Menu name="RMBPopup"> + <Action name="file_properties"/> + <Action name="file_new_contact"/> + <Separator/> + <Action name="edit_cut"/> + <Action name="edit_copy"/> + <Action name="edit_paste"/> + <Action name="copy_contact_to"/> + <Action name="move_contact_to"/> + <Separator/> + <Action name="edit_delete"/> + <Separator/> + <Action name="file_mail"/> + <Action name="file_mail_vcard"/> + <Action name="file_chat"/> + </Menu> + + <ToolBar name="mainToolBar" noMerge="1"><text>Main Toolbar</text> + <Action name="file_new_contact"/> + <Action name="file_new_distributionlist"/> + <Action name="file_properties"/> + <Separator/> + <Action name="file_sync" /> + <Action name="file_print" /> + <Separator/> + <Action name="ldap_lookup"/> + </ToolBar> + + <ToolBar name="addresseeToolBar" noMerge="1"><text>Contact Toolbar</text> + <Action name="edit_undo"/> + <Action name="edit_redo"/> + <Separator/> + <Action name="edit_cut"/> + <Action name="edit_copy"/> + <Action name="edit_paste"/> + <Separator/> + <Action name="edit_delete"/> + </ToolBar> + +</kpartgui> diff --git a/kaddressbook/kaddressbook_view.desktop b/kaddressbook/kaddressbook_view.desktop new file mode 100644 index 000000000..05e445e39 --- /dev/null +++ b/kaddressbook/kaddressbook_view.desktop @@ -0,0 +1,60 @@ +[Desktop Entry] +Type=ServiceType +X-KDE-ServiceType=KAddressBook/View +Comment=KAddressBook View Plugin +Comment[af]=KAddressBook besigtig inprop module +Comment[be]=Дапаўненне K Адраснай кнігі "Выгляд" +Comment[bg]=Приставка за преглед на адресника +Comment[br]=Lugent gwell KAddressBook +Comment[bs]=KAddressBook dodatak za pregledanje +Comment[ca]=Endollable visor de la llibreta d'adreces +Comment[cs]=Modul knihu adres pro zobrazování +Comment[cy]=Ategyn Golwg KLlyfrCyfeiriadau +Comment[da]=KAddressBook visningsplugin +Comment[de]=Betrachter-Modul für Adressbuch +Comment[el]=Πρόσθετο προβολής του KAddressBook +Comment[eo]=KAddressBook Rigardo-Kromaĵo +Comment[es]=Plugin del visor de KAddressBook +Comment[et]=KDE aadressiraamatu vaatamise plugin +Comment[eu]=KAddressBook-en bistaratze plugin-a +Comment[fa]=وصلۀ نمای KAddressBook +Comment[fi]=KAddressbook näyttöliitännäinen +Comment[fr]=Module d'affichage pour KAddressBook +Comment[fy]=KAddressBook Werjefte Plugin +Comment[gl]=Extensión de Visualización para KAddressBook +Comment[he]=תוסף תצוגה עבור פנקס הכתובות +Comment[hi]=के-एड्रेस-बुक दृश्य प्लगइन +Comment[hu]=KAddressBook nézeti bővítőmodul +Comment[is]=KAddressbook birtingar íforrit +Comment[it]=Plugin visualizzazione di KAddressbook +Comment[ja]=Addressbook ビュープラグイン +Comment[ka]= KDE წიგნაკის ჩვენების მოდული +Comment[kk]=Адрестік кітапшасын қарау модулі +Comment[km]=កម្មវិធីជំនួយទិដ្ឋភាពរបស់ KAddressBook +Comment[lt]=KAddressBook peržiūros priedas +Comment[mk]=Приклучок за преглед на КАдресар +Comment[ms]=Plug masuk Pelihat KAddressBook +Comment[nb]=KAddressbook-programtillegg for visning +Comment[nds]=Kiekermoduul för KAdressbook +Comment[ne]=केडीई ठेगाना पुस्तिका दृश्य प्लगइन +Comment[nl]=KAddressBook Weergave Plugin +Comment[nn]=Programtillegg for vising av KDE-adresseboka +Comment[pl]=Wtyczka widoku KAddressBook +Comment[pt]='Plugin' da Janela do KAddressBook +Comment[pt_BR]=Plug-in de Visualização do KAddressBook +Comment[ro]=Modul de vizualizare KAddressBook +Comment[ru]=Просмотр адресной книги KDE +Comment[sk]=KAddressBook plugin prehliadača +Comment[sl]=Vstavek za ogled v Adresarju +Comment[sr]=Прикључак KAddressBook-а за преглед +Comment[sr@Latn]=Priključak KAddressBook-a za pregled +Comment[sv]=Kadressbok-visningsinsticksprogram +Comment[ta]=கேமுகவரிப்புத்தகம் காட்சி சொருகுப்பொருள் +Comment[tg]=Модули намоиши китоби адресии KDE +Comment[tr]=KAdresDefteri Gösterim Eklentisi +Comment[uk]=Втулок перегляду адресної книги KAddressBook +Comment[zh_CN]=KAddressBook 查看插件 +Comment[zh_TW]=KAddressBook 檢視外掛程式 + +[PropertyDef::X-KDE-KAddressBook-ViewPluginVersion] +Type=int diff --git a/kaddressbook/kaddressbookiface.h b/kaddressbook/kaddressbookiface.h new file mode 100644 index 000000000..914cd0299 --- /dev/null +++ b/kaddressbook/kaddressbookiface.h @@ -0,0 +1,72 @@ +/* + This file is part of KAddressBook. + Copyright (c) 2003 - 2004 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 KADDRESSBOOKIFACE_H +#define KADDRESSBOOKIFACE_H + +#include <dcopobject.h> +#include <kurl.h> +#include <qstringlist.h> +#include <kdepimmacros.h> + +class KDE_EXPORT KAddressBookIface : virtual public DCOPObject +{ + K_DCOP + + k_dcop: + virtual void addEmail( QString addr ) = 0; + virtual void importVCard( const KURL& url ) = 0; + virtual void importVCardFromData( const QString& vCard ) = 0; + + virtual ASYNC showContactEditor( QString uid ) = 0; + + /** + Shows dialog for creation of a new contact. Returns once a contact + is created (or canceled). + */ + virtual void newContact() = 0; + + /** + Shows dialog for creation of a new distribution list. Returns once a distribution list + is created (or canceled). + */ + virtual void newDistributionList() = 0; + + /** + Save changes to the address book files. + */ + virtual QString getNameByPhone( QString phone ) = 0; + virtual void save() = 0; + virtual void exit() = 0; + + /** + * Internal, DCOP-enabled for the kontact plugin. + * Return true if handled, false if command-line was empty. + */ + virtual bool handleCommandLine() = 0; + + virtual void loadProfile( const QString& path ) = 0; + virtual void saveToProfile( const QString& path ) const = 0; +}; + +#endif diff --git a/kaddressbook/kaddressbookmain.cpp b/kaddressbook/kaddressbookmain.cpp new file mode 100644 index 000000000..a3a145b3c --- /dev/null +++ b/kaddressbook/kaddressbookmain.cpp @@ -0,0 +1,186 @@ +/* + This file is part of KAddressbook. + Copyright (c) 1999 Don Sanders <dsanders@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 <kedittoolbar.h> +#include <kkeydialog.h> +#include <klocale.h> +#include <kmessagebox.h> +#include <kstatusbar.h> + +#include <libkdepim/statusbarprogresswidget.h> +#include <libkdepim/progressdialog.h> + +#include "kabcore.h" + +#include "kaddressbookmain.h" + +KAddressBookMain::KAddressBookMain( const QString &file ) + : DCOPObject( "KAddressBookIface" ), KMainWindow( 0 ) +{ + // Set this to be the group leader for all subdialogs - this means + // modal subdialogs will only affect this dialog, not the other windows + setWFlags( getWFlags() | WGroupLeader ); + + setCaption( i18n( "Address Book Browser" ) ); + + mCore = new KABCore( this, true, this, file ); + mCore->restoreSettings(); + + initActions(); + + setCentralWidget( mCore->widget() ); + + statusBar()->show(); + statusBar()->insertItem( "", 1 ); + + KPIM::ProgressDialog *progressDialog = new KPIM::ProgressDialog( statusBar(), + this ); + progressDialog->hide(); + + KPIM::StatusbarProgressWidget *progressWidget; + progressWidget = new KPIM::StatusbarProgressWidget( progressDialog, + statusBar() ); + progressWidget->show(); + + statusBar()->addWidget( progressWidget, 0, true ); + + mCore->setStatusBar( statusBar() ); + + setStandardToolBarMenuEnabled( true ); + + createGUI( "kaddressbookui.rc", false ); + + resize( 400, 300 ); // initial size + setAutoSaveSettings(); +} + +KAddressBookMain::~KAddressBookMain() +{ + mCore->saveSettings(); +} + +void KAddressBookMain::addEmail( QString addr ) +{ + mCore->addEmail( addr ); +} + +void KAddressBookMain::importVCard( const KURL& url ) +{ + mCore->importVCard( url ); +} + +void KAddressBookMain::importVCardFromData( const QString& vCard ) +{ + mCore->importVCardFromData( vCard ); +} + +ASYNC KAddressBookMain::showContactEditor( QString uid ) +{ + mCore->editContact( uid ); +} + +void KAddressBookMain::newDistributionList() +{ + mCore->newDistributionList(); +} + +void KAddressBookMain::newContact() +{ + mCore->newContact(); +} + +QString KAddressBookMain::getNameByPhone( QString phone ) +{ + return mCore->getNameByPhone( phone ); +} + +void KAddressBookMain::save() +{ + mCore->save(); +} + +void KAddressBookMain::exit() +{ + close(); +} + +bool KAddressBookMain::handleCommandLine() +{ + return mCore->handleCommandLine( this ); +} + +void KAddressBookMain::saveProperties( KConfig* ) +{ +} + +void KAddressBookMain::readProperties( KConfig* ) +{ +} + +bool KAddressBookMain::queryClose() +{ + return mCore->queryClose(); +} + +void KAddressBookMain::initActions() +{ + KStdAction::quit( this, SLOT( close() ), actionCollection() ); + + KAction *action; + action = KStdAction::keyBindings( this, SLOT( configureKeyBindings() ), actionCollection() ); + action->setWhatsThis( i18n( "You will be presented with a dialog, where you can configure the application wide shortcuts." ) ); + + KStdAction::configureToolbars( this, SLOT( configureToolbars() ), actionCollection() ); +} + +void KAddressBookMain::configureKeyBindings() +{ + KKeyDialog::configure( actionCollection(), this ); +} + +void KAddressBookMain::loadProfile( const QString& ) +{ +} + +void KAddressBookMain::saveToProfile( const QString& ) const +{ +} + +void KAddressBookMain::configureToolbars() +{ + saveMainWindowSettings( KGlobal::config(), "MainWindow" ); + + KEditToolbar edit( factory() ); + connect( &edit, SIGNAL( newToolbarConfig() ), + this, SLOT( newToolbarConfig() ) ); + + edit.exec(); +} + +void KAddressBookMain::newToolbarConfig() +{ + createGUI( "kaddressbookui.rc", false ); + applyMainWindowSettings( KGlobal::config(), "MainWindow" ); +} + +#include "kaddressbookmain.moc" diff --git a/kaddressbook/kaddressbookmain.h b/kaddressbook/kaddressbookmain.h new file mode 100644 index 000000000..8c0e3c726 --- /dev/null +++ b/kaddressbook/kaddressbookmain.h @@ -0,0 +1,98 @@ +/* + This file is part of KAddressbook. + Copyright (c) 1999 Don Sanders <dsanders@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 KADDRESSBOOKMAIN_H +#define KADDRESSBOOKMAIN_H + +#include <qptrlist.h> + +#include <kaction.h> +#include <kapplication.h> +#include <kmainwindow.h> + +#include "kaddressbookiface.h" + +class KABCore; + +/** + This class serves as the main window for KAddressBook. It handles the + menus, toolbars, and status bars. + + @short Main window class + @author Don Sanders <dsanders@kde.org> + @version 0.1 + */ +class KAddressBookMain : public KMainWindow, virtual public KAddressBookIface +{ + Q_OBJECT + + public: + KAddressBookMain( const QString &file = QString::null ); + virtual ~KAddressBookMain(); + + public slots: + virtual void addEmail( QString addr ); + virtual void importVCard( const KURL& url ); + virtual void importVCardFromData( const QString& vCard ); + virtual ASYNC showContactEditor( QString uid ); + virtual void newContact(); + virtual void newDistributionList(); + virtual QString getNameByPhone( QString phone ); + virtual void save(); + virtual void exit(); + virtual bool handleCommandLine(); + + protected: + void initActions(); + + /** + This function is called when it is time for the app to save its + properties for session management purposes. + */ + void saveProperties( KConfig* ); + + /** + This function is called when this app is restored. The KConfig + object points to the session management config file that was saved + with @ref saveProperties + */ + void readProperties( KConfig* ); + + virtual bool queryClose(); + + //override + void loadProfile( const QString& path ); + + //override + void saveToProfile( const QString& path ) const; + + private slots: + void configureKeyBindings(); + void configureToolbars(); + void newToolbarConfig(); + + private: + KABCore *mCore; +}; + +#endif diff --git a/kaddressbook/kaddressbookservice.cpp b/kaddressbook/kaddressbookservice.cpp new file mode 100644 index 000000000..3d8139e65 --- /dev/null +++ b/kaddressbook/kaddressbookservice.cpp @@ -0,0 +1,41 @@ +/* + 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 "core.h" + +#include "kaddressbookservice.h" + +KAddressBookService::KAddressBookService( KAB::Core *core ) + : DCOPObject( "AddressBookServiceIface" ), mCore( core ) +{ +} + +void KAddressBookService::importVCardFromData( const QString& vCard ) +{ + mCore->importVCardFromData( vCard ); +} + +void KAddressBookService::importVCard( const KURL& url ) +{ + mCore->importVCard( url ); +} diff --git a/kaddressbook/kaddressbookservice.h b/kaddressbook/kaddressbookservice.h new file mode 100644 index 000000000..004a4733c --- /dev/null +++ b/kaddressbook/kaddressbookservice.h @@ -0,0 +1,56 @@ +/* + 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 KADDRESSBOOKSERVICE_H +#define KADDRESSBOOKSERVICE_H + +#include <libkdepim/interfaces/AddressBookServiceIface.h> + +namespace KAB { +class Core; +} + +class KAddressBookService : virtual public KPIM::AddressBookServiceIface +{ + public: + KAddressBookService( KAB::Core *core ); + + /** + This method will add a vcard to the address book. + + @param vCard The vCard in string representation. + */ + void importVCardFromData( const QString& vCard ); + + /** + This method will add a vcard to the address book. + + @param url The url where the vcard is located. + */ + void importVCard( const KURL& url ); + + private: + KAB::Core *mCore; +}; + +#endif diff --git a/kaddressbook/kaddressbookui.rc b/kaddressbook/kaddressbookui.rc new file mode 100644 index 000000000..ec8a153c5 --- /dev/null +++ b/kaddressbook/kaddressbookui.rc @@ -0,0 +1,116 @@ +<!DOCTYPE kpartgui> +<kpartgui name="kaddressbook" version="23"> + + <MenuBar> + <Menu name="file" noMerge="1"><text>&File</text> + <Menu name="file_new_actions_menu"><text>New</text> + <Action name="file_new_contact"/> + <Action name="file_new_distributionlist"/> + </Menu> + <Separator/> + <Action name="file_sync"/> + <Menu name="file_import"><text>&Import</text> + </Menu> + <Menu name="file_export"><text>&Export</text> + </Menu> + <Separator/> + <Action name="file_print"/> + <Action name="file_mail"/> + <Action name="file_mail_vcard"/> + <Action name="file_chat"/> + <Separator/> + <Action name="file_quit"/> + </Menu> + + <Menu name="edit" noMerge="1"><text>&Edit</text> + <Action name="edit_undo"/> + <Action name="edit_redo"/> + <Separator/> + <Action name="edit_cut"/> + <Action name="edit_copy"/> + <Action name="edit_paste"/> + <Action name="copy_contact_to"/> + <Action name="move_contact_to"/> + <Separator/> + <Action name="edit_delete" append="edit_paste_merge"/> + <Separator/> + <Action name="edit_select_all"/> + <Separator/> + <Action name="edit_merge"/> + <Action name="edit_set_categories"/> + <Action name="edit_set_personal"/> + </Menu> + + <Menu name="view" noMerge="1"><text>&View</text> + <Action name="select_view"/> + <Action name="view_add"/> + <Action name="view_modify"/> + <Action name="view_delete"/> + <Separator/> + <ActionList name="extensions_list"/> + <Separator/> + <Action name="view_refresh"/> + </Menu> + + <Menu name="tools" noMerge="1"><text>&Tools</text> + <Action name="ldap_lookup"/> + </Menu> + + <Menu name="settings" noMerge="1"><text>&Settings</text> + <Merge name="StandardToolBarMenuHandler" /> + <Action name="options_show_jump_bar"/> + <Action name="options_show_details"/> + <Action name="options_show_statusbar"/> + <Merge name="show_merge"/> + <Separator/> + <Merge/> + <Action name="options_edit_filters"/> + <Separator/> + <Action name="options_configure_keybinding"/> + <Action name="options_configure_toolbars"/> + <Action name="options_configure"/> + <Merge name="configure_merge"/> + </Menu> + + </MenuBar> + + <Menu name="RMBPopup"> + <Action name="file_properties"/> + <Action name="file_new_contact"/> + <Separator/> + <Action name="edit_cut"/> + <Action name="edit_copy"/> + <Action name="edit_paste"/> + <Action name="copy_contact_to"/> + <Action name="move_contact_to"/> + <Separator/> + <Action name="edit_delete"/> + <Separator/> + <Action name="file_mail"/> + <Action name="file_mail_vcard"/> + <Action name="file_chat"/> + </Menu> + + <ToolBar name="mainToolBar" noMerge="1"><text>Main Toolbar</text> + <Action name="file_new_contact"/> + <Action name="file_new_distributionlist"/> + <Action name="file_properties"/> + <Separator/> + <Action name="file_sync" /> + <Action name="file_print" /> + <Separator/> + <Action name="ldap_lookup"/> + </ToolBar> + + <ToolBar name="addresseeToolBar" noMerge="1"><text>Contact Toolbar</text> + <Action name="edit_undo"/> + <Action name="edit_redo"/> + <Separator/> + <Action name="edit_cut"/> + <Action name="edit_copy"/> + <Action name="edit_paste"/> + <Separator/> + <Action name="edit_delete"/> + </ToolBar> + +</kpartgui> diff --git a/kaddressbook/kaddressbookview.cpp b/kaddressbook/kaddressbookview.cpp new file mode 100644 index 000000000..72e70675f --- /dev/null +++ b/kaddressbook/kaddressbookview.cpp @@ -0,0 +1,203 @@ +/* + This file is part of KAddressBook. + Copyright (c) 2002 Mike Pilone <mpilone@slac.com> + + 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 <qlayout.h> +#include <qpopupmenu.h> + +#include <kabc/addressbook.h> +#include <kabc/distributionlistdialog.h> +#include <kconfig.h> +#include <kdebug.h> +#include <klocale.h> +#include <kxmlguifactory.h> +#include <kxmlguiclient.h> + +#include "core.h" +#include "searchmanager.h" + +#include "kaddressbookview.h" + +KAddressBookView::KAddressBookView( KAB::Core *core, QWidget *parent, + const char *name ) + : QWidget( parent, name ), mCore( core ), mFieldList() +{ + initGUI(); + + connect( mCore->searchManager(), SIGNAL( contactsUpdated() ), + SLOT( updateView() ) ); +} + +KAddressBookView::~KAddressBookView() +{ + kdDebug(5720) << "KAddressBookView::~KAddressBookView: destroying - " + << name() << endl; +} + +void KAddressBookView::readConfig( KConfig *config ) +{ + mFieldList = KABC::Field::restoreFields( config, "KABCFields" ); + + if ( mFieldList.isEmpty() ) + mFieldList = KABC::Field::defaultFields(); + + mDefaultFilterType = (DefaultFilterType)config->readNumEntry( "DefaultFilterType", 1 ); + mDefaultFilterName = config->readEntry( "DefaultFilterName" ); +} + +void KAddressBookView::writeConfig( KConfig* ) +{ + // Most of writing the config is handled by the ConfigureViewDialog +} + +QString KAddressBookView::selectedEmails() +{ + bool first = true; + QString emailAddrs; + const QStringList uidList = selectedUids(); + KABC::Addressee addr; + QString email; + + QStringList::ConstIterator it; + for ( it = uidList.begin(); it != uidList.end(); ++it ) { + addr = mCore->addressBook()->findByUid( *it ); + + if ( !addr.isEmpty() ) { + QString m = QString::null; + + if ( addr.emails().count() > 1 ) + m = KABC::EmailSelector::getEmail( addr.emails(), addr.preferredEmail(), this ); + + email = addr.fullEmail( m ); + + if ( !first ) + emailAddrs += ", "; + else + first = false; + + emailAddrs += email; + } + } + + return emailAddrs; +} + +KABC::Addressee::List KAddressBookView::addressees() +{ + if ( mFilter.isEmpty() ) + return mCore->searchManager()->contacts(); + + KABC::Addressee::List addresseeList; + const KABC::Addressee::List contacts = mCore->searchManager()->contacts(); + + KABC::Addressee::List::ConstIterator it; + KABC::Addressee::List::ConstIterator contactsEnd( contacts.end() ); + for ( it = contacts.begin(); it != contactsEnd; ++it ) { + if ( mFilter.filterAddressee( *it ) ) + addresseeList.append( *it ); + } + + return addresseeList; +} + +void KAddressBookView::initGUI() +{ + // Create the layout + QVBoxLayout *layout = new QVBoxLayout( this ); + + // Add the view widget + mViewWidget = new QWidget( this ); + layout->addWidget( mViewWidget ); +} + +KABC::Field::List KAddressBookView::fields() const +{ + return mFieldList; +} + +void KAddressBookView::setFilter( const Filter &filter ) +{ + mFilter = filter; +} + +KAddressBookView::DefaultFilterType KAddressBookView::defaultFilterType() const +{ + return mDefaultFilterType; +} + +const QString &KAddressBookView::defaultFilterName() const +{ + return mDefaultFilterName; +} + +KAB::Core *KAddressBookView::core() const +{ + return mCore; +} + +void KAddressBookView::popup( const QPoint &point ) +{ + if ( !mCore->guiClient() ) { + kdWarning() << "No GUI client set!" << endl; + return; + } + + QPopupMenu *menu = static_cast<QPopupMenu*>( mCore->guiClient()->factory()->container( "RMBPopup", + mCore->guiClient() ) ); + if ( menu ) + menu->popup( point ); +} + +QWidget *KAddressBookView::viewWidget() +{ + return mViewWidget; +} + +void KAddressBookView::updateView() +{ + const QStringList uidList = selectedUids(); + + refresh(); // This relists and deselects everything, in all views + + if ( !uidList.isEmpty() ) { + // Keep previous selection + QStringList::ConstIterator it, uidListEnd( uidList.end() ); + for ( it = uidList.begin(); it != uidListEnd; ++it ) + setSelected( *it, true ); + + } else { + const KABC::Addressee::List contacts = mCore->searchManager()->contacts(); + if ( !contacts.isEmpty() ) + setFirstSelected( true ); + else + emit selected( QString::null ); + } +} + +ViewConfigureWidget *ViewFactory::configureWidget( KABC::AddressBook *ab, + QWidget *parent, + const char *name ) +{ + return new ViewConfigureWidget( ab, parent, name ); +} + +#include "kaddressbookview.moc" diff --git a/kaddressbook/kaddressbookview.h b/kaddressbook/kaddressbookview.h new file mode 100644 index 000000000..89ddca944 --- /dev/null +++ b/kaddressbook/kaddressbookview.h @@ -0,0 +1,314 @@ +/* + This file is part of KAddressBook. + Copyright (c) 2002 Mike Pilone <mpilone@slac.com> + + 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 KADDRESSBOOKVIEW_H +#define KADDRESSBOOKVIEW_H + +#define KAB_VIEW_PLUGIN_VERSION 1 + +#include <qstringlist.h> +#include <qwidget.h> + +#include <kabc/field.h> +#include <klibloader.h> +#include <kdepimmacros.h> + +#include "filter.h" +#include "viewconfigurewidget.h" + +class KConfig; +class KXMLGUIClient; + +class QDropEvent; + +namespace KAB { class Core; } +namespace KABC { class AddressBook; } + +/** + Base class for all views in kaddressbook. This class implements + all the common methods needed to provide a view to the user. + + To implement a specific view (table, card, etc), just inherit from + this class and implement all the pure virtuals. + + @author Mike Pilone <mpilone@slac.com> + */ +class KDE_EXPORT KAddressBookView : public QWidget +{ + Q_OBJECT + + public: + enum DefaultFilterType { None = 0, Active = 1, Specific = 2 }; + + KAddressBookView( KAB::Core *core, QWidget *parent, const char *name ); + virtual ~KAddressBookView(); + + /** + Must be overloaded in subclasses. Should return a list of + all the uids of selected contacts. + */ + virtual QStringList selectedUids() = 0; + + /** + Called whenever this view should read the config. This can be used + as a sign that the config has changed, therefore the view should + assume the worst and rebuild itself if necessary. For example, + in a table view this method may be called when the user adds or + removes columns from the view. + + If overloaded in the subclass, do not forget to call super class's + method. + + @param config The KConfig object to read from. The group will already + be set, so do not change the group. + */ + virtual void readConfig( KConfig *config ); + + /** + Called whenever this view should write the config. The view should not + write out information handled by the application, such as which fields + are visible. The view should only write out information specific + to itself (i.e.: All information in the ViewConfigWidget) + + If overloaded in the subclass, do not forget to call the super class's + method. + */ + // The KConfig object is unused so we do not document it + // else doxygen will complain. + virtual void writeConfig( KConfig * ); + + /** + Returns a QString with all the selected email addresses concatenated + together with a ',' seperator. + */ + virtual QString selectedEmails(); + + /** + Return the type of the view: Icon, Table, etc. Please make sure that + this is the same value that ViewWrapper::type() will return for your + view. + */ + virtual QString type() const = 0; + + /** + Returns a list of the fields that should be displayed. The list + is composed of the fields proper names (ie: Home Address), so + the view may need to translate them in order to get the + value from the addressee. + + This list is generated from the config file, so it is advisable to call + this method whenever a readConfig() is called in order to get the newest + list of fields. + */ + KABC::Field::List fields() const; + + /** + Sets the active filter. This filter will be used for filtering + the list of addressees to display. The view will <b>not</b> + automatically refresh itself, so in most cases you will want to call + KAddressBookView::refresh() after this method. + */ + void setFilter( const Filter& ); + + /** + @return The default filter type selection. If the selection + is SpecificFilter, the name of the filter can be retrieved with + defaultFilterName() + */ + DefaultFilterType defaultFilterType() const; + + /** + @return The name of the default filter. This string is + only valid if defaultFilterType() is returning SpecificFilter. + */ + const QString &defaultFilterName() const; + + /** + @return The Core object. + */ + KAB::Core *core() const; + + /** + @return The current sort field. + */ + virtual KABC::Field *sortField() const = 0; + + virtual void scrollUp() = 0; + virtual void scrollDown() = 0; + + public slots: + /** + Must be overloaded in subclasses to refresh the view. + Refreshing includes updating the view to ensure that only items + in the document are visible. If <i>uid</i> is valid, only the + addressee with uid needs to be refreshed. This is an optimization + only. + */ + virtual void refresh( const QString &uid = QString() ) = 0; + + /** + This method must be overloaded in subclasses. Select (highlight) + the addressee matching <i>uid</i>. If uid + is equal to QString::null, then all addressees should be selected. + */ + virtual void setSelected( const QString &uid = QString(), bool selected = true ) = 0; + + /** + Selects the first contact in the view. + */ + virtual void setFirstSelected( bool selected = true ) = 0; + + /** + Call this slot to popup a rmb menu. + + @param point The position where the menu shall appear. + */ + void popup( const QPoint &point ); + + signals: + /** + This signal should be emitted by a subclass whenever an addressee + is modified. + */ + void modified(); + + /** + This signal should be emitted by a subclass whenever an addressee + is selected. Selected means that the addressee was given the focus. + Some widgets may call this 'highlighted'. The view is responsible for + emitting this signal multiple times if multiple items are selected, + with the last item selected being the last emit. + + @param uid The uid of the selected addressee. + + @see KListView + */ + void selected( const QString &uid ); + + /** + This signal should be emitted by a subclass whenever an addressee + is executed. This is defined by the KDE system wide config, but it + either means single or doubleclicked. + + @param uid The uid of the selected addressee + + @see KListView + */ + void executed( const QString &uid ); + + /** + This signal is emitted whenever a user attempts to start a drag + in the view. The slot connected to this signal would usually want + to create a QDragObject. + */ + void startDrag(); + + /** + This signal is emitted whenever the user drops something on the + view. The individual view should handle checking if the item is + droppable (ie: if it is a vcard). + */ + void dropped( QDropEvent* ); + + /** + This signal is emitted whenever the sort field changed. + */ + void sortFieldChanged(); + + /** + Emitted whenever the view fields changed. + */ + void viewFieldsChanged(); + + protected: + /** + Returns a list of the addressees that should be displayed. This method + should always be used by the subclass to get a list of addressees. This + method internally takes many factors into account, including the current + filter. + */ + KABC::Addressee::List addressees(); + + /** + This method returns the widget that should be used as the parent for + all view components. By using this widget as the parent and not + 'this', the view subclass has the option of placing other widgets + around the view (ie: search fields, etc). Do not delete this widget! + */ + QWidget *viewWidget(); + + private slots: + void updateView(); + + private: + void initGUI(); + + DefaultFilterType mDefaultFilterType; + Filter mFilter; + QString mDefaultFilterName; + KAB::Core *mCore; + KABC::Field::List mFieldList; + + QWidget *mViewWidget; +}; + +class KDE_EXPORT ViewFactory : public KLibFactory +{ + public: + virtual KAddressBookView *view( KAB::Core *core, QWidget *parent, + const char *name = 0 ) = 0; + /** + @return The type of the view. This is normally a small one word + string (ie: Table, Icon, Tree, etc). + */ + virtual QString type() const = 0; + + /** + @return The description of the view. This should be a 3 to + 4 line string (don't actually use return characters in the string) + describing the features offered by the view. + */ + virtual QString description() const = 0; + + /** + Creates a config dialog for the view type. The default + implementation will return a ViewConfigDialog. This default + dialog will allow the user to set the visible fields only. If + you need more config options (as most views will), this method + can be overloaded to return your sublcass of ViewConfigDialog. + If this method is over loaded the base classes method should + <B>not</B> be called. + */ + virtual ViewConfigureWidget *configureWidget( KABC::AddressBook *ab, + QWidget *parent, + const char *name = 0 ); + + protected: + virtual QObject* createObject( QObject*, const char*, const char*, + const QStringList & ) + { + return 0; + } +}; + +#endif diff --git a/kaddressbook/kcmconfigs/Makefile.am b/kaddressbook/kcmconfigs/Makefile.am new file mode 100644 index 000000000..a465740c0 --- /dev/null +++ b/kaddressbook/kcmconfigs/Makefile.am @@ -0,0 +1,38 @@ +INCLUDES= -I$(top_builddir)/kaddressbook -I$(top_srcdir)/kaddressbook \ + -I$(top_srcdir)/kaddressbook/common \ + -I$(top_srcdir)/kaddressbook/interfaces \ + -I$(top_srcdir) -I$(top_builddir)/kaddressbook/common $(all_includes) + +kde_module_LTLIBRARIES = kcm_kabconfig.la kcm_kabldapconfig.la \ + kcm_kabcustomfields.la + +kcm_kabconfig_la_SOURCES = kcmkabconfig.cpp kabconfigwidget.cpp \ + extensionconfigdialog.cpp addresseewidget.cpp +kcm_kabconfig_la_LDFLAGS = -module $(KDE_PLUGIN) $(KDE_RPATH) $(all_libraries) \ + -avoid-version -no-undefined +kcm_kabconfig_la_LIBADD = $(LIB_KIO) \ + $(top_builddir)/kaddressbook/interfaces/libkabinterfaces.la \ + $(top_builddir)/libkdepim/libkdepim.la \ + $(top_builddir)/kaddressbook/common/libkabcommon.la +kcm_kabconfig_la_COMPILE_FIRST = $(top_builddir)/kaddressbook/common/kabprefs_base.h + +kcm_kabldapconfig_la_SOURCES = addhostdialog.cpp kcmkabldapconfig.cpp \ + ldapoptionswidget.cpp +kcm_kabldapconfig_la_LDFLAGS = -module $(KDE_PLUGIN) $(KDE_RPATH) $(all_libraries) \ + -avoid-version -no-undefined +kcm_kabldapconfig_la_LIBADD = $(LIB_KIO) $(LIB_KABC) $(top_builddir)/libkdepim/libkdepim.la + +kcm_kabcustomfields_la_SOURCES = kcmkabcustomfields.cpp +kcm_kabcustomfields_la_LDFLAGS = -module $(KDE_PLUGIN) $(KDE_RPATH) $(all_libraries) \ + -avoid-version -no-undefined +kcm_kabcustomfields_la_LIBADD = $(LIB_KDEUI) -lqui \ + $(top_builddir)/kaddressbook/common/libkabcommon.la +kcm_kabcustomfields_la_COMPILE_FIRST = $(top_builddir)/kaddressbook/common/kabprefs_base.h + +METASOURCES = AUTO + +messages: rc.cpp + $(XGETTEXT) *.cpp -o $(podir)/kcmkabconfig.pot + +kde_services_DATA = kabconfig.desktop kabldapconfig.desktop \ + kabcustomfields.desktop diff --git a/kaddressbook/kcmconfigs/addhostdialog.cpp b/kaddressbook/kcmconfigs/addhostdialog.cpp new file mode 100644 index 000000000..b3eb60bcf --- /dev/null +++ b/kaddressbook/kcmconfigs/addhostdialog.cpp @@ -0,0 +1,127 @@ +/* + This file is part of KAddressBook. + Copyright (c) 2002 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 <qlabel.h> +#include <qlayout.h> +#include <qpushbutton.h> +#include <qspinbox.h> +#include <qtooltip.h> + +#include <kaccelmanager.h> +#include <kbuttonbox.h> +#include <klineedit.h> +#include <klocale.h> +#include "addhostdialog.h" + +AddHostDialog::AddHostDialog( KPIM::LdapServer *server, QWidget* parent, const char* name ) + : KDialogBase( Plain, i18n( "Add Host" ), Ok | Cancel, Ok, parent, name, true, true ) +{ + mServer = server; + + QWidget *page = plainPage(); + QHBoxLayout *layout = new QHBoxLayout( page, marginHint(), spacingHint() ); + + mCfg = new KABC::LdapConfigWidget( + KABC::LdapConfigWidget::W_USER | + KABC::LdapConfigWidget::W_PASS | + KABC::LdapConfigWidget::W_BINDDN | + KABC::LdapConfigWidget::W_REALM | + KABC::LdapConfigWidget::W_HOST | + KABC::LdapConfigWidget::W_PORT | + KABC::LdapConfigWidget::W_VER | + KABC::LdapConfigWidget::W_TIMELIMIT | + KABC::LdapConfigWidget::W_SIZELIMIT | + KABC::LdapConfigWidget::W_DN | + KABC::LdapConfigWidget::W_SECBOX | + KABC::LdapConfigWidget::W_AUTHBOX, + page ); + + layout->addWidget( mCfg ); + mCfg->setHost( mServer->host() ); + mCfg->setPort( mServer->port() ); + mCfg->setDn( mServer->baseDN() ); + mCfg->setUser( mServer->user() ); + mCfg->setBindDN( mServer->bindDN() ); + mCfg->setPassword( mServer->pwdBindDN() ); + mCfg->setTimeLimit( mServer->timeLimit() ); + mCfg->setSizeLimit( mServer->sizeLimit() ); + mCfg->setVer( mServer->version() ); + + switch ( mServer->security() ) { + case KPIM::LdapServer::TLS: + mCfg->setSecTLS(); + break; + case KPIM::LdapServer::SSL: + mCfg->setSecSSL(); + break; + default: + mCfg->setSecNO(); + } + + switch ( mServer->auth() ) { + case KPIM::LdapServer::Simple: + mCfg->setAuthSimple(); + break; + case KPIM::LdapServer::SASL: + mCfg->setAuthSASL(); + break; + default: + mCfg->setAuthAnon(); + } + mCfg->setMech( mServer->mech() ); + + KAcceleratorManager::manage( this ); + +} + +AddHostDialog::~AddHostDialog() +{ +} + +void AddHostDialog::slotHostEditChanged( const QString &text ) +{ + enableButtonOK( !text.isEmpty() ); +} + +void AddHostDialog::slotOk() +{ + mServer->setHost( mCfg->host() ); + mServer->setPort( mCfg->port() ); + mServer->setBaseDN( mCfg->dn().stripWhiteSpace() ); + mServer->setUser( mCfg->user() ); + mServer->setBindDN( mCfg->bindDN() ); + mServer->setPwdBindDN( mCfg->password() ); + mServer->setTimeLimit( mCfg->timeLimit() ); + mServer->setSizeLimit( mCfg->sizeLimit() ); + mServer->setVersion( mCfg->ver() ); + mServer->setSecurity( KPIM::LdapServer::Sec_None ); + if ( mCfg->isSecTLS() ) mServer->setSecurity( KPIM::LdapServer::TLS ); + if ( mCfg->isSecSSL() ) mServer->setSecurity( KPIM::LdapServer::SSL ); + mServer->setAuth( KPIM::LdapServer::Anonymous ); + if ( mCfg->isAuthSimple() ) mServer->setAuth( KPIM::LdapServer::Simple ); + if ( mCfg->isAuthSASL() ) mServer->setAuth( KPIM::LdapServer::SASL ); + mServer->setMech( mCfg->mech() ); + KDialog::accept(); +} + +#include "addhostdialog.moc" diff --git a/kaddressbook/kcmconfigs/addhostdialog.h b/kaddressbook/kcmconfigs/addhostdialog.h new file mode 100644 index 000000000..84f5a0c9e --- /dev/null +++ b/kaddressbook/kcmconfigs/addhostdialog.h @@ -0,0 +1,54 @@ +/* + This file is part of KAddressBook. + Copyright (c) 2002 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 ADDHOSTDIALOG_H +#define ADDHOSTDIALOG_H + +#include <kdialogbase.h> +#include <kabc/ldapconfigwidget.h> +#include <libkdepim/ldapclient.h> + +class KLineEdit; +class QPushButton; +class QSpinBox; + +class AddHostDialog : public KDialogBase +{ + Q_OBJECT + + public: + AddHostDialog( KPIM::LdapServer* server, QWidget* parent = 0, const char* name = 0 ); + ~AddHostDialog(); + + signals: + void changed( bool ); + + private slots: + void slotHostEditChanged( const QString& ); + virtual void slotOk(); + private: + KABC::LdapConfigWidget *mCfg; + KPIM::LdapServer *mServer; +}; + +#endif // ADDHOSTDIALOG_H diff --git a/kaddressbook/kcmconfigs/addresseewidget.cpp b/kaddressbook/kcmconfigs/addresseewidget.cpp new file mode 100644 index 000000000..610b94b80 --- /dev/null +++ b/kaddressbook/kcmconfigs/addresseewidget.cpp @@ -0,0 +1,202 @@ +/* + 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 <qcstring.h> +#include <qgroupbox.h> +#include <qlabel.h> +#include <qlayout.h> +#include <qlistbox.h> +#include <qpushbutton.h> + +#include <dcopclient.h> + +#include <kbuttonbox.h> +#include <kcombobox.h> +#include <kconfig.h> +#include <kdialog.h> +#include <kinputdialog.h> +#include <klocale.h> +#include <klineedit.h> + +#include "addresseewidget.h" + +NamePartWidget::NamePartWidget( const QString &title, const QString &label, + QWidget *parent, const char *name ) + : QWidget( parent, name ), mTitle( title ), mLabel( label ) +{ + QHBoxLayout *layout = new QHBoxLayout( this ); + + QGroupBox *group = new QGroupBox( 0, Qt::Vertical, title, this ); + QGridLayout *groupLayout = new QGridLayout( group->layout(), 2, 2, + KDialog::spacingHint() ); + + mBox = new QListBox( group ); + connect( mBox, SIGNAL( selectionChanged( QListBoxItem* ) ), + SLOT( selectionChanged( QListBoxItem* ) ) ); + groupLayout->addWidget( mBox, 0, 0 ); + + KButtonBox *bbox = new KButtonBox( group, Qt::Vertical ); + mAddButton = bbox->addButton( i18n( "Add..." ), this, SLOT( add() ) ); + mEditButton = bbox->addButton( i18n( "Edit..." ), this, SLOT( edit() ) ); + mEditButton->setEnabled( false ); + mRemoveButton = bbox->addButton( i18n( "Remove" ), this, SLOT( remove() ) ); + mRemoveButton->setEnabled( false ); + bbox->layout(); + groupLayout->addWidget( bbox, 0, 1 ); + + layout->addWidget( group ); +} + +NamePartWidget::~NamePartWidget() +{ +} + +void NamePartWidget::setNameParts( const QStringList &list ) +{ + mBox->clear(); + mBox->insertStringList( list ); +} + +QStringList NamePartWidget::nameParts() const +{ + QStringList parts; + for ( uint i = 0; i < mBox->count(); ++i ) + parts.append( mBox->text( i ) ); + + return parts; +} + +void NamePartWidget::add() +{ + bool ok; + + QString namePart = KInputDialog::getText( i18n( "New" ), mLabel, + QString::null, &ok ); + if ( ok && !namePart.isEmpty() ) { + mBox->insertItem( namePart ); + emit modified(); + } +} + +void NamePartWidget::edit() +{ + bool ok; + + int index = mBox->currentItem(); + if ( index == -1 ) + return; + + QString namePart = KInputDialog::getText( i18n( "Edit" ), mLabel, + mBox->text( index ), &ok ); + if ( ok && !namePart.isEmpty() ) { + mBox->changeItem( namePart, index ); + emit modified(); + } +} + +void NamePartWidget::remove() +{ + mBox->removeItem( mBox->currentItem() ); + if ( mBox->count() == 0 ) + selectionChanged( 0 ); + + emit modified(); +} + +void NamePartWidget::selectionChanged( QListBoxItem *item ) +{ + mEditButton->setEnabled( item != 0 ); + mRemoveButton->setEnabled( item != 0 ); +} + + + +AddresseeWidget::AddresseeWidget( QWidget *parent, const char *name ) + : QWidget( parent, name ) +{ + QGridLayout *layout = new QGridLayout( this, 2, 3, KDialog::marginHint(), + KDialog::spacingHint() ); + + mPrefix = new NamePartWidget( i18n( "Prefixes"), i18n( "Enter prefix:" ), this ); + layout->addWidget( mPrefix, 0, 0 ); + + mInclusion = new NamePartWidget( i18n( "Inclusions"), i18n( "Enter inclusion:" ), this ); + layout->addWidget( mInclusion, 0, 1 ); + + mSuffix = new NamePartWidget( i18n( "Suffixes" ), i18n( "Enter suffix:" ), this ); + layout->addWidget( mSuffix, 0, 2 ); + + QLabel *label = new QLabel( i18n( "Default formatted name:" ), this ); + layout->addWidget( label, 1, 0 ); + + mFormattedNameCombo = new KComboBox( this ); + mFormattedNameCombo->insertItem( i18n( "Empty" ) ); + mFormattedNameCombo->insertItem( i18n( "Simple Name" ) ); + mFormattedNameCombo->insertItem( i18n( "Full Name" ) ); + mFormattedNameCombo->insertItem( i18n( "Reverse Name with Comma" ) ); + mFormattedNameCombo->insertItem( i18n( "Reverse Name" ) ); + layout->addMultiCellWidget( mFormattedNameCombo, 1, 1, 1, 2 ); + + connect( mPrefix, SIGNAL( modified() ), SIGNAL( modified() ) ); + connect( mInclusion, SIGNAL( modified() ), SIGNAL( modified() ) ); + connect( mSuffix, SIGNAL( modified() ), SIGNAL( modified() ) ); + connect( mFormattedNameCombo, SIGNAL( activated( int ) ), SIGNAL( modified() ) ); +} + +AddresseeWidget::~AddresseeWidget() +{ +} + +void AddresseeWidget::restoreSettings() +{ + KConfig config( "kabcrc" ); + config.setGroup( "General" ); + + mPrefix->setNameParts( config.readListEntry( "Prefixes" ) ); + mInclusion->setNameParts( config.readListEntry( "Inclusions" ) ); + mSuffix->setNameParts( config.readListEntry( "Suffixes" ) ); + + KConfig cfg( "kaddressbookrc" ); + cfg.setGroup( "General" ); + mFormattedNameCombo->setCurrentItem( cfg.readNumEntry( "FormattedNameType", 1 ) ); +} + +void AddresseeWidget::saveSettings() +{ + KConfig config( "kabcrc" ); + config.setGroup( "General" ); + + config.writeEntry( "Prefixes", mPrefix->nameParts() ); + config.writeEntry( "Inclusions", mInclusion->nameParts() ); + config.writeEntry( "Suffixes", mSuffix->nameParts() ); + + KConfig cfg( "kaddressbookrc" ); + cfg.setGroup( "General" ); + cfg.writeEntry( "FormattedNameType", mFormattedNameCombo->currentItem() ); + + DCOPClient *client = DCOPClient::mainClient(); + if ( client ) + client->emitDCOPSignal( "KABC::AddressBookConfig", "changed()", QByteArray() ); +} + +#include "addresseewidget.moc" diff --git a/kaddressbook/kcmconfigs/addresseewidget.h b/kaddressbook/kcmconfigs/addresseewidget.h new file mode 100644 index 000000000..c942ee42b --- /dev/null +++ b/kaddressbook/kcmconfigs/addresseewidget.h @@ -0,0 +1,89 @@ +/* + 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 ADDRESSEEWIDGET_H +#define ADDRESSEEWIDGET_H + +#include <qwidget.h> + +class KComboBox; +class KLineEdit; + +class QListBox; +class QListBoxItem; +class QPushButton; + +class NamePartWidget : public QWidget +{ + Q_OBJECT + + public: + NamePartWidget( const QString &title, const QString &label, QWidget *parent, + const char *name = 0 ); + ~NamePartWidget(); + + void setNameParts( const QStringList &list ); + QStringList nameParts() const; + + signals: + void modified(); + + private slots: + void add(); + void edit(); + void remove(); + + void selectionChanged( QListBoxItem* ); + + private: + QListBox *mBox; + QPushButton *mAddButton; + QPushButton *mEditButton; + QPushButton *mRemoveButton; + + QString mTitle; + QString mLabel; +}; + +class AddresseeWidget : public QWidget +{ + Q_OBJECT + + public: + AddresseeWidget( QWidget *parent, const char *name = 0 ); + ~AddresseeWidget(); + + void restoreSettings(); + void saveSettings(); + + signals: + void modified(); + + private: + KComboBox *mFormattedNameCombo; + NamePartWidget *mPrefix; + NamePartWidget *mInclusion; + NamePartWidget *mSuffix; +}; + +#endif diff --git a/kaddressbook/kcmconfigs/extensionconfigdialog.cpp b/kaddressbook/kcmconfigs/extensionconfigdialog.cpp new file mode 100644 index 000000000..70a8d1afc --- /dev/null +++ b/kaddressbook/kcmconfigs/extensionconfigdialog.cpp @@ -0,0 +1,57 @@ +/* + 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 <qlayout.h> + +#include <klocale.h> + +#include "configurewidget.h" +#include "extensionconfigdialog.h" +#include "extensionwidget.h" + +ExtensionConfigDialog::ExtensionConfigDialog( KAB::ExtensionFactory *factory, KConfig *config, + QWidget *parent, const char *name ) + : KDialogBase( Plain, i18n( "Extension Settings" ), Ok | Cancel, Ok, parent, + name, true, true ), mWidget( 0 ), mConfig( config ) +{ + QFrame *page = plainPage(); + QGridLayout *layout = new QGridLayout( page, 1, 1, marginHint(), spacingHint() ); + + mWidget = factory->configureWidget( page, "ExtensionConfigWidget" ); + layout->addWidget( mWidget, 0, 0 ); + + mWidget->restoreSettings( mConfig ); +} + +ExtensionConfigDialog::~ExtensionConfigDialog() +{ +} + +void ExtensionConfigDialog::slotOk() +{ + mWidget->saveSettings( mConfig ); + + KDialogBase::slotOk(); +} + +#include "extensionconfigdialog.moc" diff --git a/kaddressbook/kcmconfigs/extensionconfigdialog.h b/kaddressbook/kcmconfigs/extensionconfigdialog.h new file mode 100644 index 000000000..1547647a9 --- /dev/null +++ b/kaddressbook/kcmconfigs/extensionconfigdialog.h @@ -0,0 +1,52 @@ +/* + 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 EXTENSIONCONFIGDIALOG_H +#define EXTENSIONCONFIGDIALOG_H + +#include <kdialogbase.h> + +#include "extensionwidget.h" + +namespace KAB { +class ConfigureWidget; +} + +class ExtensionConfigDialog : public KDialogBase +{ + Q_OBJECT + + public: + ExtensionConfigDialog( KAB::ExtensionFactory *factory, KConfig *config, + QWidget *parent, const char *name = 0 ); + ~ExtensionConfigDialog(); + + protected slots: + void slotOk(); + + private: + KAB::ConfigureWidget *mWidget; + KConfig *mConfig; +}; + +#endif diff --git a/kaddressbook/kcmconfigs/kabconfig.desktop b/kaddressbook/kcmconfigs/kabconfig.desktop new file mode 100644 index 000000000..17a0b1b5a --- /dev/null +++ b/kaddressbook/kcmconfigs/kabconfig.desktop @@ -0,0 +1,180 @@ +[Desktop Entry] +Icon=kaddressbook +Type=Service +ServiceTypes=KCModule +DocPath=kaddressbook/preferences.html + +X-KDE-ModuleType=Library +X-KDE-Library=kabconfig +X-KDE-FactoryName=kabconfig +X-KDE-HasReadOnlyMode=false +X-KDE-ParentApp=kaddressbook +X-KDE-ParentComponents=kaddressbook,kontact_kaddressbookplugin +X-KDE-CfgDlgHierarchy=KAB + +Name=General +Name[af]=Algemeen +Name[ar]=عام +Name[bg]=Общи +Name[br]=Pennañ +Name[cs]=Obecné +Name[cy]=Cyffredinol +Name[da]=Generelt +Name[de]=Allgemein +Name[el]=Γενικά +Name[eo]=Ĝenerala +Name[et]=Üldine +Name[eu]=Orokorra +Name[fa]=عمومی +Name[fi]=Yleinen +Name[fr]=Général +Name[fy]=Algemien +Name[ga]=Ginearálta +Name[gl]=Xeral +Name[he]=כללי +Name[hu]=Általános +Name[is]=Almennt +Name[it]=Generale +Name[ja]=全般 +Name[ka]=ზოგადი +Name[kk]=Жалпы +Name[km]=ទូទៅ +Name[lt]=Bendras +Name[mk]=Општо +Name[ms]=Umum +Name[nb]=Generelt +Name[nds]=Allgemeen +Name[ne]=साधारण +Name[nl]=Algemeen +Name[nn]=Generelt +Name[pa]=ਸਧਾਰਨ +Name[pl]=Ogólne +Name[pt]=Geral +Name[pt_BR]=Geral +Name[ru]=Общие +Name[se]=Oppalaš +Name[sk]=Všeobecné +Name[sl]=Splošno +Name[sr]=Опште +Name[sr@Latn]=Opšte +Name[sv]=Allmänt +Name[ta]=பொதுவான +Name[th]=ทั่วไป +Name[tr]=Genel +Name[uk]=Загальні +Name[uz]=Umumiy +Name[uz@cyrillic]=Умумий +Name[zh_CN]=常规 +Comment=Configure the Address Book +Comment[af]=Stel die adres boek op +Comment[ar]=إعداد دفتر العناوين +Comment[be]=Настроіць адрасную кнігу +Comment[bg]=Настройки на адресника +Comment[br]=Kefluniañ ar c'harned chomlec'hioù +Comment[bs]=Podesite Adresar +Comment[ca]=Configura la Llibreta d'adreces +Comment[cs]=Nastavit knihu adres +Comment[cy]=Ffurfweddu'r Llyfr Cyfeiriadau +Comment[da]=Indstil adressebogen +Comment[de]=Adressbuch einrichten +Comment[el]=Ρύθμιση του Βιβλίου διευθύνσεων +Comment[eo]=Agordi la Adreslibron +Comment[es]=Configura la libreta de direcciones +Comment[et]=Aadressiraamatu seadistamine +Comment[eu]=Konfiguratu helbide-liburua +Comment[fa]=پیکربندی کتاب نشانی +Comment[fi]=Muokkaa osoitekirjan asetuksia +Comment[fr]=Configurer le carnet d'adresses +Comment[fy]=Hjir kinne jo, jo adresboek oanpasse +Comment[ga]=Cumraigh an Leabhar Seoltaí +Comment[gl]=Configurar o Caderno de Enderezos +Comment[he]=הגדרת הפנקס כתובת +Comment[hi]=पता पुस्तिका कॉन्फ़िगर करें +Comment[hu]=A címjegyzék beállítása +Comment[is]=Stilla vistfangaskrána +Comment[it]=Configura la rubrica indirizzi +Comment[ja]=アドレス帳設定 +Comment[ka]=წიგნაკის კონფიგურაცია +Comment[kk]=Адрестік кітапшаны баптау +Comment[km]=កំណត់រចនាសម្ព័ន្ធសៀវភៅអាសយដ្ឋាន +Comment[lt]=Konfigūruoti adresų knygelę +Comment[mk]=Конфигурирајте го адресарот +Comment[ms]=Konfigurkan Buku Alamat +Comment[nb]=Oppsett for adresseboka +Comment[nds]=Adressbook instellen +Comment[ne]=ठेगाना पुस्तिका कन्फिगर गर्नुहोस् +Comment[nl]=Hier kunt u uw adresboek aanpassen +Comment[nn]=Setja opp adressebok +Comment[pl]=Konfiguracja Książki adresowej +Comment[pt]=Configuração do Livro de Endereços +Comment[pt_BR]=Configurar o Livro de Endereços +Comment[ro]=Configurează cartea de adrese +Comment[ru]=Настройка адресной книги +Comment[se]=Heivet čujuhusgirjji +Comment[sk]=Nastavenie Adresára +Comment[sl]=Nastavi Adresar +Comment[sr]=Подешавање адресара +Comment[sr@Latn]=Podešavanje adresara +Comment[sv]=Anpassa adressboken +Comment[ta]=கேமுகவரிப்புத்தகத்தை கட்டமை +Comment[tg]=Танзимоти китоби адрес +Comment[tr]=Adres Defterini Yapılandır +Comment[uk]=Налаштування адресної книги +Comment[uz]=Manzillar daftarini moslash +Comment[uz@cyrillic]=Манзиллар дафтарини мослаш +Comment[zh_CN]=配置地址簿 +Comment[zh_TW]=設定通訊錄 +Keywords=kaddressbook, configure, settings +Keywords[af]=kaddressbook, configure,settings,adres +Keywords[be]=K Адрасная кніга, настроіць, настаўленні, kaddressbook, configure, settings +Keywords[bg]=адресни,адресна,книга,визитник,визитка,картичка,kaddressbook, configure, settings +Keywords[br]=kaddressbook, kefluniañ, dibarzhoù +Keywords[bs]=kaddressbook, configure, settings, podesi, podesite, postavke, konfiguracija +Keywords[ca]=llibreta d'adreces, configura, opcions +Keywords[cs]=kniha adres,nastavení +Keywords[cy]=kaddressbook, ffurfweddu,godosiadau +Keywords[da]=kaddressbook, indstil, opsætning +Keywords[de]=KAddressbook,Adressbuch +Keywords[el]=kaddressbook, ρύθμιση, ρυθμίσεις +Keywords[eo]=kaddressbook,adresaro,agordo +Keywords[es]=kaddressbook, configurar, opciones +Keywords[et]=kde aadressiraamat, seadistamine, seadistused +Keywords[eu]=kaddressbook, konfiguratu, ezarpenak +Keywords[fa]=kaddressbook، پیکربندی، تنظیمات +Keywords[fi]=kaddressbook, aseta, asetukset +Keywords[fr]=carnet d'adresses,adresses,kab,kaddressbook,configurer,paramètres,paramètre +Keywords[fy]=adresboek,KAB,kab,kaddressbook,ynstellings,configuratie +Keywords[ga]=kaddressbook, cumraigh, cumraíocht, socruithe +Keywords[gl]=kaddressbook, configurar, opcións +Keywords[hi]=केएड्रेसबुक, कॉन्फ़िगर, विन्यास +Keywords[hu]=kaddressbook, konfigurálás, beállítások +Keywords[is]=kaddressbook, stillingar, stilla +Keywords[it]=kaddressbook, configura, impostazioni +Keywords[ja]=kaddressbook 設定 +Keywords[ka]=kaddressbook,კონფიგურაცია, პარამეტრები +Keywords[km]=kaddressbook,កំណត់រចនាសម្ព័ន្ធ,ការកំណត់ +Keywords[lt]=kaddressbook, configure, settings, konfigūravimas, nustatymai +Keywords[mk]=kaddressbook, configure, settings, КАдресар, конфигурирање, конфигурација, поставување +Keywords[ms]=,selaraskan, tetapan, kaddressbook, configure, settings +Keywords[nb]=kaddressbook, sette opp, innstillinger +Keywords[nds]=KAddressbook,KAdressbook,Adressbook,instellen +Keywords[ne]=केडीई ठेगाना पुस्तिका, कन्फिगर, सेटिङ +Keywords[nl]=adresboek,KAB,kab,kaddressbook,instellingen,configuratie +Keywords[nn]=adressebok, oppsett, innstillingar +Keywords[pl]=kaddressbook, książka adresowa,adresy,konfiguracja,ustawienia,opcje +Keywords[pt]=kaddressbook, configurar, configuração +Keywords[pt_BR]=kaddressbook, configurar, configurações +Keywords[ro]=kaddressbook,configurare,setări +Keywords[ru]=kaddressbook,адресная книга,настройка +Keywords[se]=čujuhusgirji,heivehus,heivehusat +Keywords[sl]=kaddressbook, adresar, nastavi, nastavitve +Keywords[sr]=kaddressbook, configure, settings, подеси, поставке +Keywords[sr@Latn]=kaddressbook, configure, settings, podesi, postavke +Keywords[sv]=adressbok, anpassa, inställningar +Keywords[ta]=கேமுகவரிப்புத்தகம்,கட்டமைப்பு,அமைவுகள் +Keywords[tg]=kaddressbook,китоби адрес,танзимот +Keywords[tr]=kadresdefteri, yapılandırma, ayarlar +Keywords[uk]=kaddressbook, налаштування, параметри +Keywords[uz]=kaddressbook, moslash, moslamalar, manzillar daftari +Keywords[uz@cyrillic]=kaddressbook, мослаш, мосламалар, манзиллар дафтари +Keywords[zh_CN]=kaddressbook, configure, settings, 配置, 设置 diff --git a/kaddressbook/kcmconfigs/kabconfigwidget.cpp b/kaddressbook/kcmconfigs/kabconfigwidget.cpp new file mode 100644 index 000000000..7c57a926c --- /dev/null +++ b/kaddressbook/kcmconfigs/kabconfigwidget.cpp @@ -0,0 +1,223 @@ +/* + 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 <qframe.h> +#include <qgroupbox.h> +#include <qlabel.h> +#include <qlayout.h> +#include <qlineedit.h> +#include <qpushbutton.h> +#include <qtabwidget.h> +#include <qtooltip.h> +#include <qcombobox.h> + +#include <kconfig.h> +#include <kdebug.h> +#include <kdialog.h> +#include <klistview.h> +#include <klocale.h> +#include <kmessagebox.h> +#include <ktrader.h> + +#include "addresseewidget.h" +#include "kabprefs.h" + +#include "kabconfigwidget.h" + +KABConfigWidget::KABConfigWidget( QWidget *parent, const char *name ) + : QWidget( parent, name ) +{ + QVBoxLayout *topLayout = new QVBoxLayout( this, 0, + KDialog::spacingHint() ); + + QTabWidget *tabWidget = new QTabWidget( this ); + topLayout->addWidget( tabWidget ); + + // General page + QWidget *generalPage = new QWidget( this ); + QVBoxLayout *layout = new QVBoxLayout( generalPage, KDialog::marginHint(), + KDialog::spacingHint() ); + + QGroupBox *groupBox = new QGroupBox( 0, Qt::Vertical, i18n( "General" ), generalPage ); + QBoxLayout *boxLayout = new QVBoxLayout( groupBox->layout() ); + boxLayout->setAlignment( Qt::AlignTop ); + + mViewsSingleClickBox = new QCheckBox( i18n( "Honor KDE single click" ), groupBox, "msingle" ); + boxLayout->addWidget( mViewsSingleClickBox ); + + mNameParsing = new QCheckBox( i18n( "Automatic name parsing for new addressees" ), groupBox, "mparse" ); + boxLayout->addWidget( mNameParsing ); + + mTradeAsFamilyName = new QCheckBox( i18n( "Trade single name component as family name" ), groupBox, "mtrade" ); + boxLayout->addWidget( mTradeAsFamilyName ); +/** + TODO: show the checkbox when we can compile agains kdelibs from HEAD, atm it + doesn't work and would just confuse the users ;) +*/ + mTradeAsFamilyName->hide(); + + mLimitContactDisplay = new QCheckBox( i18n( "Limit unfiltered display to 100 contacts" ), groupBox, "mlimit" ); + boxLayout->addWidget( mLimitContactDisplay ); + + QBoxLayout *editorLayout = new QHBoxLayout( boxLayout, KDialog::spacingHint() ); + + QLabel *label = new QLabel( i18n( "Addressee editor type:" ), groupBox ); + editorLayout->addWidget( label ); + + mEditorCombo = new QComboBox( groupBox ); + mEditorCombo->insertItem( i18n( "Full Editor" ) ); + mEditorCombo->insertItem( i18n( "Simple Editor" ) ); + label->setBuddy( mEditorCombo ); + editorLayout->addWidget( mEditorCombo ); + + editorLayout->addStretch( 1 ); + + + layout->addWidget( groupBox ); + + groupBox = new QGroupBox( 0, Qt::Vertical, i18n( "Script-Hooks" ), generalPage ); + QGridLayout *grid = new QGridLayout( groupBox->layout(), 3, 2, + KDialog::spacingHint() ); + label = new QLabel( i18n( "Phone:" ), groupBox ); + grid->addWidget( label, 0, 0 ); + + mPhoneHook = new QLineEdit( groupBox ); + QToolTip::add( mPhoneHook, i18n( "<ul><li>%N: Phone Number</li></ul>" ) ); + grid->addWidget( mPhoneHook, 0, 1 ); + + label = new QLabel( i18n( "Fax:" ), groupBox ); + grid->addWidget( label, 1, 0 ); + + mFaxHook = new QLineEdit( groupBox ); + QToolTip::add( mFaxHook, i18n( "<ul><li>%N: Fax Number</li></ul>" ) ); + grid->addWidget( mFaxHook, 1, 1 ); + + + label = new QLabel( i18n( "SMS Text:" ), groupBox ); + grid->addWidget( label, 2, 0 ); + + mSMSHook = new QLineEdit( groupBox ); + QToolTip::add( mSMSHook, i18n( "<ul><li>%N: Phone Number</li><li>%F: File containing the text message(s)</li></ul>" ) ); + grid->addWidget( mSMSHook, 2, 1 ); + + + grid->setColStretch( 1, 1 ); + + layout->addWidget( groupBox ); + + groupBox = new QGroupBox( 0, Qt::Vertical, i18n( "Location Map" ), generalPage ); + boxLayout = new QVBoxLayout( groupBox->layout(), KDialog::spacingHint() ); + boxLayout->setAlignment( Qt::AlignTop ); + + mLocationMapURL = new QComboBox( true, groupBox ); + mLocationMapURL->setSizePolicy( QSizePolicy( QSizePolicy::Preferred, QSizePolicy::Fixed ) ); + QToolTip::add( mLocationMapURL, i18n( "<ul> <li>%s: Street</li>" + "<li>%r: Region</li>" + "<li>%l: Location</li>" + "<li>%z: Zip Code</li>" + "<li>%c: Country ISO Code</li> </ul>" ) ); + mLocationMapURL->insertStringList( KABPrefs::instance()->locationMapURLs() ); + boxLayout->addWidget( mLocationMapURL ); + layout->addWidget( groupBox ); + + connect( mNameParsing, SIGNAL( toggled( bool ) ), SLOT( modified() ) ); + connect( mViewsSingleClickBox, SIGNAL( toggled( bool ) ), SLOT( modified() ) ); + connect( mTradeAsFamilyName, SIGNAL( toggled( bool ) ), SLOT( modified() ) ); + connect( mLimitContactDisplay, SIGNAL( toggled( bool ) ), SLOT( modified() ) ); + connect( mPhoneHook, SIGNAL( textChanged( const QString& ) ), SLOT( modified() ) ); + connect( mSMSHook, SIGNAL( textChanged( const QString& ) ), SLOT( modified() ) ); + connect( mFaxHook, SIGNAL( textChanged( const QString& ) ), SLOT( modified() ) ); + connect( mLocationMapURL, SIGNAL( textChanged( const QString& ) ), SLOT( modified() ) ); + connect( mEditorCombo, SIGNAL( activated( int ) ), SLOT( modified() ) ); + + tabWidget->addTab( generalPage, i18n( "General" ) ); + + // Addressee page + mAddresseeWidget = new AddresseeWidget( this ); + tabWidget->addTab( mAddresseeWidget, i18n( "Contact" ) ); + connect( mAddresseeWidget, SIGNAL( modified() ), SLOT( modified() ) ); +} + +void KABConfigWidget::restoreSettings() +{ + bool blocked = signalsBlocked(); + blockSignals( true ); + + mNameParsing->setChecked( KABPrefs::instance()->automaticNameParsing() ); + mViewsSingleClickBox->setChecked( KABPrefs::instance()->honorSingleClick() ); + mPhoneHook->setText( KABPrefs::instance()->phoneHookApplication() ); + mSMSHook->setText( KABPrefs::instance()->sMSHookApplication() ); + mFaxHook->setText( KABPrefs::instance()->faxHookApplication() ); + mAddresseeWidget->restoreSettings(); + mEditorCombo->setCurrentItem( KABPrefs::instance()->editorType() ); + mLocationMapURL->setCurrentText( KABPrefs::instance()->locationMapURL().arg( KGlobal::locale()->country() ) ); + mLocationMapURL->lineEdit()->setCursorPosition( 0 ); + + KConfig config( "kabcrc", false, false ); + config.setGroup( "General" ); + mTradeAsFamilyName->setChecked( config.readBoolEntry( "TradeAsFamilyName", true ) ); + mLimitContactDisplay->setChecked( config.readBoolEntry( "LimitContactDisplay", true ) ); + + blockSignals( blocked ); + + emit changed( false ); +} + +void KABConfigWidget::saveSettings() +{ + KABPrefs::instance()->setAutomaticNameParsing( mNameParsing->isChecked() ); + KABPrefs::instance()->setHonorSingleClick( mViewsSingleClickBox->isChecked() ); + KABPrefs::instance()->setPhoneHookApplication( mPhoneHook->text() ); + KABPrefs::instance()->setSMSHookApplication( mSMSHook->text() ); + KABPrefs::instance()->setFaxHookApplication( mFaxHook->text() ); + KABPrefs::instance()->setEditorType( mEditorCombo->currentItem() ); + KABPrefs::instance()->setLocationMapURL( mLocationMapURL->currentText() ); + mAddresseeWidget->saveSettings(); + + KABPrefs::instance()->writeConfig(); + + KConfig config( "kabcrc", false, false ); + config.setGroup( "General" ); + config.writeEntry( "TradeAsFamilyName", mTradeAsFamilyName->isChecked() ); + config.writeEntry( "LimitContactDisplay", mLimitContactDisplay->isChecked() ); + + emit changed( false ); +} + +void KABConfigWidget::defaults() +{ + mNameParsing->setChecked( true ); + mViewsSingleClickBox->setChecked( false ); + mEditorCombo->setCurrentItem( 0 ); + mLimitContactDisplay->setChecked( true ); + + emit changed( true ); +} + +void KABConfigWidget::modified() +{ + emit changed( true ); +} + +#include "kabconfigwidget.moc" diff --git a/kaddressbook/kcmconfigs/kabconfigwidget.h b/kaddressbook/kcmconfigs/kabconfigwidget.h new file mode 100644 index 000000000..72b3e88f3 --- /dev/null +++ b/kaddressbook/kcmconfigs/kabconfigwidget.h @@ -0,0 +1,70 @@ +/* + 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 KABCONFIGWIDGET_H +#define KABCONFIGWIDGET_H + +#include <qwidget.h> + +class QCheckBox; +class QLineEdit; +class QListViewItem; +class QPushButton; +class QComboBox; + +class KListView; + +class AddresseeWidget; + +class KABConfigWidget : public QWidget +{ + Q_OBJECT + + public: + KABConfigWidget( QWidget *parent, const char *name = 0 ); + + void restoreSettings(); + void saveSettings(); + void defaults(); + + signals: + void changed( bool ); + + public slots: + void modified(); + + private: + QCheckBox *mNameParsing; + QCheckBox *mViewsSingleClickBox; + QCheckBox *mTradeAsFamilyName; + QComboBox *mEditorCombo; + QLineEdit *mPhoneHook; + QLineEdit *mFaxHook; + QLineEdit *mSMSHook; + QCheckBox *mLimitContactDisplay; + QComboBox *mLocationMapURL; + + AddresseeWidget *mAddresseeWidget; +}; + +#endif diff --git a/kaddressbook/kcmconfigs/kabcustomfields.desktop b/kaddressbook/kcmconfigs/kabcustomfields.desktop new file mode 100644 index 000000000..f0b7cf1ff --- /dev/null +++ b/kaddressbook/kcmconfigs/kabcustomfields.desktop @@ -0,0 +1,163 @@ +[Desktop Entry] +Icon=dlgedit +Type=Service +ServiceTypes=KCModule +DocPath=kaddressbook/preferences.html + +X-KDE-ModuleType=Library +X-KDE-Library=kabcustomfields +X-KDE-FactoryName=kabcustomfields +X-KDE-ParentApp=kaddressbook +X-KDE-ParentComponents=kaddressbook,kontact_kaddressbookplugin +X-KDE-CfgDlgHierarchy=KAB + +Name=Custom Pages +Name[af]=Pasmaak Blaaie +Name[ar]=الصفحات المعتادة +Name[bg]=Потребителски полета +Name[br]=Pajennoù dre ziouer +Name[bs]=Vlastite stranice +Name[ca]=Pàgines a mida +Name[cs]=Vlastní stránky +Name[da]=Brugervalgte sider +Name[de]=Benutzerdefinierte Seiten +Name[el]=Προσαρμοσμένες σελίδες +Name[eo]=Propraj Paĝoj +Name[es]=Páginas personalizadas +Name[et]=Omaloodud leheküljed +Name[eu]=Orri pertsonalizatuak +Name[fa]=صفحات سفارشی +Name[fi]=Omat sivut +Name[fr]=Pages personnalisées +Name[fy]=Oanpaste siden +Name[ga]=Leathanaigh Shaincheaptha +Name[gl]=Páxinas Personalizadas +Name[he]=דפים מותאמים אישית +Name[hu]=Egyéni lapok +Name[is]=Sérsniðnar síður +Name[it]=Pagine personalizzate +Name[ja]=カスタムページ +Name[ka]=სამომხმარებლო გვერდები +Name[kk]=Қосымша парақтар +Name[km]=ទំព័រផ្ទាល់ខ្លួន +Name[lt]=Pasirinkti puslapiai +Name[mk]=Сопствени страници +Name[ms]=Halaman Kebiasaan +Name[nb]=Tilpassede sider +Name[nds]=Egen Sieden +Name[ne]=अनुकूल पृष्ठ +Name[nl]=Aangepaste pagina's +Name[nn]=Tilpassa sider +Name[pl]=Własne strony +Name[pt]=Páginas Personalizadas +Name[pt_BR]=Páginas personalizadas +Name[ru]=Дополнительные поля +Name[se]=Iežat siiddut +Name[sk]=Vlastné stránky +Name[sl]=Prilagojene strani +Name[sr]=Посебне странице +Name[sr@Latn]=Posebne stranice +Name[sv]=Egna sidor +Name[ta]=தனிபயன் பக்கங்கள் +Name[tg]=Варақаҳои замимавии истифодашаванда +Name[tr]=Özel Sayfa +Name[uk]=Нетипові сторінки +Name[zh_CN]=定制页 +Comment=Configure the Custom Pages +Comment[af]=Stel die pasmaak blaaie op +Comment[ar]=إعداد الصفحات المعتادة +Comment[bg]=Настройки на потребителските полета +Comment[br]=Kefluniañ ar pajennoù diouzhoc'h +Comment[bs]=Podesite vlastite stranice +Comment[ca]=Configura les pàgines a mida +Comment[cs]=Nastavení vlastních stránek +Comment[da]=Indstil de selvvalgte sider +Comment[de]=Einstellungen für benutzerdefinierte Seiten +Comment[el]=Ρύθμιση των προσαρμοσμένων σελίδων +Comment[eo]=Agordi la proprajn paĝojn +Comment[es]=Configura las páginas personalizadas +Comment[et]=Omaloodud lehekülgede seadistamine +Comment[eu]=Konfiguratu orri pertsonalizatuak +Comment[fa]=پیکربندی صفحات سفارشی +Comment[fi]=Muokkaa omia sivuja +Comment[fr]=Configurer les pages personnalisées +Comment[fy]=Hjir kinne jo de oanpaste siden ynstelle +Comment[ga]=Cumraigh na Leathanaigh Shaincheaptha +Comment[gl]=Configurar as Páxinas Personalizadas +Comment[he]=הגדר את הדפים המותאמים אישית +Comment[hu]=Az egyéni lapok beállítása +Comment[is]=Stilla sérsniðnu síðurnar +Comment[it]=Configura le pagine personalizzate +Comment[ja]=カスタムページの設定 +Comment[ka]=სამომხმარებლო გვერდების კონფიგურაცია +Comment[kk]=Қосымша парақтарды баптау +Comment[km]=កំណត់រចនាសម្ព័ន្ធទំព័រផ្ទាល់ខ្លួន +Comment[lt]=Konfigūruoti darbastalių skaičių ir pavadinimus +Comment[mk]=Конфигурирајте ги сопствените страници +Comment[ms]=Konfigurkan Halaman Langganan +Comment[nb]=Stille inn de tilpassede sidene +Comment[nds]=Egen Sieden instellen +Comment[ne]=अनुकूल पृष्ठ कन्फिगर गर्नुहोस् +Comment[nl]=Hier kunt u de aangepaste pagina's instellen +Comment[nn]=Set opp dei tilpassa sidene +Comment[pl]=Konfiguracja własnych stron +Comment[pt]=Configurar as Páginas Personalizadas +Comment[pt_BR]=Configurar Páginas personalizadas +Comment[ru]=Настройка пользовательских вкладок +Comment[se]=Heivet iežat siidduid +Comment[sk]=Nastavenie vlastných stránok +Comment[sl]=Nastavi prilagojene strani +Comment[sr]=Подешавање посебних страница +Comment[sr@Latn]=Podešavanje posebnih stranica +Comment[sv]=Anpassa egna sidor +Comment[ta]=தனிபயன் பக்கங்களை கட்டமை +Comment[tg]=Танзимоти варақаҳои замимавии истифодашаванда +Comment[tr]=Özel Sayfaları Yapılandır +Comment[uk]=Налаштування нетипових сторінок +Comment[zh_CN]=配置定制页 +Comment[zh_TW]=設定 Custom Pages +Keywords=kaddressbook, configure, settings, custom fields +Keywords[bg]=адресник, потребителски, полета, настройки, настройване, kaddressbook, configure, settings, custom fields +Keywords[bs]=kaddressbook, configure, settings, custom fields, podesite, postavke, vlastite, vlastito +Keywords[ca]=llibreta d'adreces, configura, opcions, camps a mida +Keywords[cs]=kniha adres,nastavení,vlastní pole +Keywords[da]=kaddressbook, indstil, opsætning, brugervalgte felter +Keywords[de]=KAddressbook,Konfigurieren,Einstellungen,benutzerdefinierte Felder,Einrichten +Keywords[el]=kaddressbook, ρύθμιση, ρυθμίσεις, προσαρμοσμένα πεδία +Keywords[es]=kaddressbook, configurar, opciones, campos personalizados +Keywords[et]=kde aadressiraamat, seadistamine, seadistused, omaloodud väljad +Keywords[eu]=kaddressbook, konfiguratu, ezarpenak, eremu pertsonalizatuak +Keywords[fa]=kaddresAPsbook، پیکربندی، تنظیمات، حوزههای سفارشی +Keywords[fi]=osoitekirja, aseta, asetukset, omat kentät +Keywords[fr]=carnet d'adresses,adresses,kab,kaddressbook,configurer,paramètres,paramètre,champ,personnalisé +Keywords[fy]=adresboek,KAB,kab,kaddressbook,ynstellings,konfiguraasje,oanpaste fjilden +Keywords[ga]=kaddressbook, cumraith, cumraíocht, socruithe, réimsí saincheaptha +Keywords[gl]=kaddressbook, configurar, opcións, campos personalizados +Keywords[hu]=kaddressbook, beállítás, beállítások, egyéni mezők +Keywords[is]=kaddressbook, stillingar, stilla, sérsniðnir reitir +Keywords[it]=kaddressbook, configura, impostazioni, campi personalizzati +Keywords[ja]=kaddressbook、設定、設定,カスタムフィールド +Keywords[ka]=kaddressbook,კონფიგურაცია,პარამეტრები,სამომხმარებლო ველები +Keywords[km]=kaddressbook,កំណត់រចនាសម្ព័ន្ធ,ការកំណត់,វាលផ្ទាល់ខ្លួន +Keywords[lt]=kaddressbook, configure, settings, custom fields, pasirinkti laukai,konfigūruoti, nustatymai +Keywords[mk]=kaddressbook, configure, settings, custom fields, КАдресар, конфигурација, конфигурирање, сопствени полиња +Keywords[ms]=kaddressbook, konfigur, seting, medan kebiasaan +Keywords[nb]=kaddressbook, sette opp, innstillinger +Keywords[nds]=KAddressbook,KAdressbook,Adressbook,instellen,egen Feller +Keywords[ne]=केडीई ठेगाना पुस्तिका, कन्फिगर, सेटिङ, अनुकूल फिल्ड +Keywords[nl]=adresboek,KAB,kab,kaddressbook,instellingen,configuratie,aangepaste velden +Keywords[nn]=adressebok, oppsett, innstillingar, tilpassa felt +Keywords[pl]=kaddressbook,książka adresowa,konfiguracja,ustawienia, własne pola +Keywords[pt]=kaddressbook, configurar, configuração, campos personalizados +Keywords[pt_BR]=kaddressbook,configurar,configurações, campos personalizados +Keywords[ru]=kaddressbook,адресная книга,настройка +Keywords[sk]=kaddressbook,nastavenie,vlastné polia +Keywords[sl]=kaddressbook, adresar, nastavi, nastavitve, polja, prilagojena +Keywords[sr]=kaddressbook, подеси, поставке, посебна поља +Keywords[sr@Latn]=kaddressbook, podesi, postavke, posebna polja +Keywords[sv]=adressbok, anpassa, inställningar, egna fält +Keywords[ta]=கேமுகவரிப்புத்தகம்,கட்டமை, அமைவுகள், தனிபயன் புலங்கள் +Keywords[tg]=kaddressbook,китоби адрес,танзимот +Keywords[tr]=kaddressbook,adres defteri,yapılandır,yapılandırma,özel alanlar +Keywords[uk]=kaddressbook, налаштування, параметри, нетипові поля +Keywords[zh_CN]=kaddressbook, configure, settings, custom fields, 配置, 设置, 定制项 diff --git a/kaddressbook/kcmconfigs/kabldapconfig.desktop b/kaddressbook/kcmconfigs/kabldapconfig.desktop new file mode 100644 index 000000000..a13645a98 --- /dev/null +++ b/kaddressbook/kcmconfigs/kabldapconfig.desktop @@ -0,0 +1,171 @@ +[Desktop Entry] +Icon=find +Type=Service +ServiceTypes=KCModule +DocPath=kaddressbook/preferences.html#preferences-ldap-lookup + +X-KDE-ModuleType=Library +X-KDE-Library=kabldapconfig +X-KDE-FactoryName=kabldapconfig +X-KDE-ParentApp=kaddressbook +X-KDE-ParentComponents=kaddressbook,kontact_kaddressbookplugin +X-KDE-CfgDlgHierarchy=KAB + +Name=LDAP Lookup +Name[af]=LDAP Opkyk +Name[ar]=البحث في LDAP +Name[bg]=Търсене в LDAP +Name[br]=Klask LDAP +Name[bs]=LDAP pretraga +Name[ca]=Recerca LDAP +Name[cs]=LDAP vyhledávání +Name[cy]=Chwiliad LDAP +Name[da]=LDAP-Opslag +Name[de]=LDAP-Nachschlagefunktion +Name[el]=Αναζήτηση LDAP +Name[eo]=LDAP-Serĉo +Name[es]=Búsqueda LDAP +Name[et]=LDAP otsing +Name[eu]=LDAP bilaketa +Name[fa]=مراجعه به LDAP +Name[fi]=LDAP-haku +Name[fr]=Consultation LDAP +Name[fy]=LDAP-sykasksje +Name[ga]=Cuardach LDAP +Name[gl]=Procura LDAP +Name[hi]=एलडीएपी तलाश +Name[hu]=LDAP-lekérdezés +Name[is]=LDAP uppfletting +Name[it]=Ricerca LDAP +Name[ja]=LDAP 検索 +Name[ka]= ძებნა LDAP-ში +Name[kk]=LDAP іздеу +Name[km]=ស្វែងរក LDAP +Name[lt]=LDAP paieška +Name[mk]=Пребарување во LDAP +Name[nb]=LDAP oppslag +Name[nds]=LDAP-Naslaan +Name[ne]=एलडीएपी खोजी गर्नुहोस् +Name[nl]=LDAP-zoekactie +Name[nn]=LDAP oppslag +Name[pa]=LDAP ਖੋਜ +Name[pl]=Wyszukiwanie LDAP +Name[pt]=Pesquisa na LDAP +Name[pt_BR]=Procura LDAP +Name[ro]=Căutare LDAP +Name[ru]=Каталоги LDAP +Name[sk]=LDAP hľadanie +Name[sl]=Vpogled v LDAP +Name[sr]=LDAP потрага +Name[sr@Latn]=LDAP potraga +Name[sv]=LDAP-uppslagning +Name[ta]=LDAP லுக்கப் +Name[tg]=Ҷустуҷӯ дар каталогҳои LDAP +Name[tr]=LDAP Tarama +Name[uk]=Пошук через LDAP +Name[zh_CN]=LDAP 查询 +Comment=Configure the Address Book LDAP Settings +Comment[af]=Stel die adres boek se LDAP opstelling op. +Comment[bg]=Настройки на адресника за използване на сървър LDAP +Comment[bs]=Podesite LDAP postavke Adresara +Comment[ca]=Configura les opcions de la Llibreta d'adreces LDAP +Comment[cs]=Nastavit LDAP pro Knihu adres +Comment[cy]=Ffurfweddu gosodiadau LDAP y Llyfr Cyfeiriadau +Comment[da]=Indstil adressebogens LDAP-opsætning +Comment[de]=Adressbuch-Modul für LDAP-Einstellungen +Comment[el]=Αλλάξτε τις ρυθμίσεις LDAP του Βιβλίου διευθύνσεων +Comment[eo]=Agordo de tenejo +Comment[es]=Configura las opciones de búsqueda LDAP en la libreta de direcciones +Comment[et]=Aadressiraamatu LDAP seadistused +Comment[eu]=Konfiguratu Helbide-liburuaren LDAP ezarpenak +Comment[fa]=پیکربندی تنظیمات LDAP کتاب نشانی +Comment[fi]=Aseta osoitekirjan LDAP-asetuksia +Comment[fr]=Configurer les paramètres du carnet d'adresses LDAP +Comment[fy]=Hjir kinne jo de LDAP-ynstellings foar jo adresboek ynstelle +Comment[gl]=Configurar as opcións do Caderno de Enderezos de LDAP +Comment[he]=הגדר את פנקס הכתובות מבוסס LDAP +Comment[hi]=पता पुस्तिका एलडीएपी विन्यास कॉन्फ़िगर करें +Comment[hu]=A címjegyzék LDAP-beállításainak megváltoztatása +Comment[is]=Breyta LDAP stillingum vistfangaskráarinnar +Comment[it]=Configurare le impostazioni LDAP della rubrica indirizzi +Comment[ja]=アドレス帳 LDAP 設定 +Comment[ka]=LDAP წიგნაკის პარამეტრების კონფიგურაცია +Comment[kk]=Адрестік кітапшаның LDAP параметрлерін баптау +Comment[km]=កំណត់រចនាសម្ព័ន្ធការកំណត់ LDAP របស់សៀវភៅអាសយដ្ឋាន +Comment[lt]=Konfigūruoti adresų knygelės LDAP nustatymus +Comment[mk]=Конфигурирајте ги поставувањата за LDAP за адресарот +Comment[ms]=Konfigurkan Seting Buku Alamat LDAP +Comment[nb]=Sett opp LDAP-innstillinger for adresseboka +Comment[nds]=LDAP-Instellen för KAdressbook +Comment[ne]=ठेगाना पुस्तिका एलडीएपी सेटिङ कन्फिगर गर्नुहोस् +Comment[nl]=Hier kunt u de LDAP-instellingen voor uw adresboek instellen +Comment[nn]=Setja opp LDAP-innstillingar for adresseboka +Comment[pl]=Konfiguracja ustawień LDAP dla Książki adresowej +Comment[pt]=Configurar as opções de LDAP do Livro de Endereços +Comment[pt_BR]=Configurar as Definições para LDAP do Livro de Endereços +Comment[ru]=Настройка серверов LDAP адресной книги +Comment[sk]=Nastavenie LDAP volieb Adresára +Comment[sl]=Prilagodi nastavitve LDAP v Adresarju +Comment[sr]=Подешавање LDAP поставки адресара +Comment[sr@Latn]=Podešavanje LDAP postavki adresara +Comment[sv]=Anpassa adressbokens LDAP-inställningar +Comment[ta]=கேமுகவரிபுத்தகத்தை உருவமை LDAP அமைவுகள் +Comment[tg]=Танзимоти серверҳои LDAP-и китоби адрес +Comment[tr]=Adres Defteri LDAP Ayarlarını Yapılandır +Comment[uk]=Налаштування параметрів LDAP для адресної книги +Comment[uz]=LDAP manzillar daftarini moslash +Comment[uz@cyrillic]=LDAP манзиллар дафтарини мослаш +Comment[zh_CN]=配置地址簿 LDAP 设置 +Comment[zh_TW]=設定通訊錄 LDAP 設定 +Keywords=kaddressbook, configure, settings, LDAP +Keywords[be]=K Адрасная кніга, настроіць, настраўленні, kaddressbook, configure, settings, LDAP +Keywords[bg]=адресник,адрес,адресна,книга,сървър,всички,kaddressbook, configure, settings, LDAP +Keywords[br]=kaddressbook, kefluniañ, dibarzhoù, LDAP +Keywords[bs]=kaddressbook, configure, settings, LDAP, podesi, postavke, podesite, konfiguracija +Keywords[ca]=llibreta d'adreces, configura, opcions, LDAP +Keywords[cs]=kniha adres,nastavení,LDAP +Keywords[cy]=kaddressbook,ffurfweddu, gosodiadau,LDAP +Keywords[da]=kaddressbook, indstil, opsætning, LDAP +Keywords[de]=KAddressbook,LDAP,Einstellungen, Einrichten +Keywords[el]=kaddressbook, ρύθμιση, ρυθμίσεις, LDAP +Keywords[es]=kaddressbook, configurar, opciones, LDAP +Keywords[et]=kde aadressiraamat, seadistamine, seadistused, LDAP +Keywords[eu]=kaddressbook, konfiguratu,ezarpenak, LDAP +Keywords[fa]=kaddressbook، پیکربندی، تنظیمات، LDAP +Keywords[fi]=kaddressbook, aseta, asetukset, LDAP +Keywords[fr]=carnet d'adresses,adresses,kab,kaddressbook,configurer,paramètres,paramètre,LDAP +Keywords[fy]=adresboek,kaddressbook,LDAP +Keywords[ga]=kaddressbook, cumraigh, cumraíocht, socruithe, LDAP +Keywords[gl]=kaddressbook, configurar,opcións, LDAP +Keywords[hi]=केएड्रेसबुक, कॉन्फ़िगर, विन्यास,एलडीएपी +Keywords[hu]=kaddressbook, konfiguráció, beállítások, LDAP +Keywords[is]=kaddressbook, stillingar, stilla, LDAP +Keywords[it]=kaddressbook, configura, impostazioni, LDAP +Keywords[ja]=kaddressbook LDAP 設定 +Keywords[ka]=kaddressbook,კონფიგურაცია,პარამეტრები, LDAP +Keywords[km]=kaddressbook,កំណត់រចនាសម្ព័ន្ធ,ការកំណត់,LDAP +Keywords[lt]=kaddressbook, configure, settings, LDAP, nustatymai, konfigūruoti +Keywords[mk]=kaddressbook, configure, settings, LDAP, кадресар, конфигурација, конфигурирање, поставувања +Keywords[ms]=selaraskan, tetapan, kaddressbook, configure, settings, LDAP +Keywords[nb]=kaddressbook, sette opp, innstillinger, LDAP +Keywords[nds]=KAdressbook,Adressbook,LDAP,instellen +Keywords[ne]=केडीई ठेगाना पुस्तिका, कन्फिगर, सेटिङ, एलडीएपी +Keywords[nl]=adresboek,kaddressbook,LDAP +Keywords[nn]=adressebok, oppsett, innstillingar, LDAP +Keywords[pl]=kaddressbook, książka adresowa,konfiguracja,ustawienia,opcje, LDAP +Keywords[pt]=kaddressbook, configurar, configuração, LDAP +Keywords[pt_BR]=kaddressbook, configurar, configurações, LDAP +Keywords[ro]=kaddressbook,configurare,setări,LDAP +Keywords[ru]=kaddressbook, configure, settings, LDAP, адресная книга, настройки +Keywords[se]=čujuhusgirji,heivehus,heivehit,LDAP +Keywords[sl]=kaddressbook,adresar, nastavi, nastavitve, LDAP +Keywords[sr]=kaddressbook, configure, settings, подеси, поставке, LDAP +Keywords[sr@Latn]=kaddressbook, configure, settings, podesi, postavke, LDAP +Keywords[sv]=adressbok, anpassa, inställningar, LDAP +Keywords[ta]=கேமுகவரிபுத்தகம்,கட்டமைப்பு,அமைவுகள்,LDAP +Keywords[tg]=kaddressbook, configure, settings, LDAP, китоби адрес, танзимот +Keywords[tr]=adres defteri,yapılandırma,ayarlar,LDAP +Keywords[uk]=kaddressbook, налаштування, параметри, LDAP +Keywords[uz]=kaddressbook, moslash, moslamalar, manzillar daftari, LDAP +Keywords[uz@cyrillic]=kaddressbook, мослаш, мосламалар, манзиллар дафтари, LDAP +Keywords[zh_CN]=kaddressbook, configure, settings, LDAP, 配置, 设置 diff --git a/kaddressbook/kcmconfigs/kcmkabconfig.cpp b/kaddressbook/kcmconfigs/kcmkabconfig.cpp new file mode 100644 index 000000000..97fee4661 --- /dev/null +++ b/kaddressbook/kcmconfigs/kcmkabconfig.cpp @@ -0,0 +1,78 @@ +/* + 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 <qlayout.h> + +#include <kaboutdata.h> +#include <kdebug.h> +#include <klocale.h> + +#include "kabconfigwidget.h" + +#include "kcmkabconfig.h" + +#include <kdepimmacros.h> + +extern "C" +{ + KDE_EXPORT KCModule *create_kabconfig( QWidget *parent, const char * ) { + return new KCMKabConfig( parent, "kcmkabconfig" ); + } +} + +KCMKabConfig::KCMKabConfig( QWidget *parent, const char *name ) + : KCModule( parent, name ) +{ + QVBoxLayout *layout = new QVBoxLayout( this ); + mConfigWidget = new KABConfigWidget( this, "mConfigWidget" ); + layout->addWidget( mConfigWidget ); + + connect( mConfigWidget, SIGNAL( changed( bool ) ), SIGNAL( changed( bool ) ) ); + + load(); + + KAboutData *about = new KAboutData( I18N_NOOP( "kcmkabconfig" ), + I18N_NOOP( "KAddressBook Configure Dialog" ), + 0, 0, KAboutData::License_GPL, + I18N_NOOP( "(c), 2003 - 2004 Tobias Koenig" ) ); + + about->addAuthor( "Tobias Koenig", 0, "tokoe@kde.org" ); + setAboutData( about ); +} + +void KCMKabConfig::load() +{ + mConfigWidget->restoreSettings(); +} + +void KCMKabConfig::save() +{ + mConfigWidget->saveSettings(); +} + +void KCMKabConfig::defaults() +{ + mConfigWidget->defaults(); +} + +#include "kcmkabconfig.moc" diff --git a/kaddressbook/kcmconfigs/kcmkabconfig.h b/kaddressbook/kcmconfigs/kcmkabconfig.h new file mode 100644 index 000000000..a42dff08b --- /dev/null +++ b/kaddressbook/kcmconfigs/kcmkabconfig.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 KCMKABCONFIG_H +#define KCMKABCONFIG_H + +#include <kcmodule.h> + +class KABConfigWidget; + +class KCMKabConfig : public KCModule +{ + Q_OBJECT + + public: + KCMKabConfig( QWidget *parent = 0, const char *name = 0 ); + + virtual void load(); + virtual void save(); + virtual void defaults(); + + private: + KABConfigWidget *mConfigWidget; +}; + +#endif diff --git a/kaddressbook/kcmconfigs/kcmkabcustomfields.cpp b/kaddressbook/kcmconfigs/kcmkabcustomfields.cpp new file mode 100644 index 000000000..0c70b08bd --- /dev/null +++ b/kaddressbook/kcmconfigs/kcmkabcustomfields.cpp @@ -0,0 +1,77 @@ +/* + This file is part of KAddressbook. + Copyright (c) 2004 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 "kcmkabcustomfields.h" + +#include "kabprefs.h" + +#include <kstandarddirs.h> + +#include <qregexp.h> + +#include <kdepimmacros.h> + +extern "C" +{ + KDE_EXPORT KCModule *create_kabcustomfields( QWidget *parent, const char * ) { + return new KCMKabCustomFields( parent, "kcmkabcustomfields" ); + } +} + +KCMKabCustomFields::KCMKabCustomFields( QWidget *parent, const char *name ) + : KCMDesignerFields( parent, name ) +{ +} + +QString KCMKabCustomFields::localUiDir() +{ + return kabLocalDir() + "contacteditorpages/"; +} + +QString KCMKabCustomFields::uiPath() +{ + return "kaddressbook/contacteditorpages/"; +} + +void KCMKabCustomFields::writeActivePages( const QStringList &activePages ) +{ + KABPrefs::instance()->setAdvancedCustomFields( activePages ); + KABPrefs::instance()->writeConfig(); +} + +QStringList KCMKabCustomFields::readActivePages() +{ + return KABPrefs::instance()->advancedCustomFields(); +} + +QString KCMKabCustomFields::applicationName() +{ + return "KADDRESSBOOK"; +} + +QString KCMKabCustomFields::kabLocalDir() +{ + QStringList kabdirs = locateLocal("data", "kaddressbook/"); + return kabdirs.grep( QRegExp( "^"+KGlobal::dirs()->localkdedir() ) ).first(); +} + diff --git a/kaddressbook/kcmconfigs/kcmkabcustomfields.h b/kaddressbook/kcmconfigs/kcmkabcustomfields.h new file mode 100644 index 000000000..1501c42ed --- /dev/null +++ b/kaddressbook/kcmconfigs/kcmkabcustomfields.h @@ -0,0 +1,43 @@ +/* + This file is part of KAddressbook. + Copyright (c) 2004 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 KCMKABCUSTOMFIELDS_H +#define KCMKABCUSTOMFIELDS_H + +#include <libkdepim/kcmdesignerfields.h> + +class KCMKabCustomFields : public KPIM::KCMDesignerFields +{ + public: + KCMKabCustomFields( QWidget *parent = 0, const char *name = 0 ); + + protected: + QString localUiDir(); + QString uiPath(); + void writeActivePages( const QStringList & ); + QStringList readActivePages(); + QString applicationName(); + + QString kabLocalDir(); +}; + +#endif diff --git a/kaddressbook/kcmconfigs/kcmkabldapconfig.cpp b/kaddressbook/kcmconfigs/kcmkabldapconfig.cpp new file mode 100644 index 000000000..48c83a543 --- /dev/null +++ b/kaddressbook/kcmconfigs/kcmkabldapconfig.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 <qcheckbox.h> +#include <qframe.h> +#include <qlayout.h> + +#include <kaboutdata.h> +#include <klocale.h> + +#include "ldapoptionswidget.h" + +#include "kcmkabldapconfig.h" + +#include <kdepimmacros.h> + +extern "C" +{ + KDE_EXPORT KCModule *create_kabldapconfig( QWidget *parent, const char * ) { + return new KCMKabLdapConfig( parent, "kcmkabldapconfig" ); + } +} + +KCMKabLdapConfig::KCMKabLdapConfig( QWidget *parent, const char *name ) + : KCModule( parent, name ) +{ + QVBoxLayout *layout = new QVBoxLayout( this ); + mConfigWidget = new LDAPOptionsWidget( this ); + layout->addWidget( mConfigWidget ); + + connect( mConfigWidget, SIGNAL( changed( bool ) ), SIGNAL( changed( bool ) ) ); + + load(); + + KAboutData *about = new KAboutData( I18N_NOOP( "kcmkabldapconfig" ), + I18N_NOOP( "KAB LDAP Configure Dialog" ), + 0, 0, KAboutData::License_GPL, + I18N_NOOP( "(c), 2003 - 2004 Tobias Koenig" ) ); + + about->addAuthor( "Tobias Koenig", 0, "tokoe@kde.org" ); + setAboutData( about ); +} + +void KCMKabLdapConfig::load() +{ + mConfigWidget->restoreSettings(); +} + +void KCMKabLdapConfig::save() +{ + mConfigWidget->saveSettings(); +} + +void KCMKabLdapConfig::defaults() +{ + mConfigWidget->defaults(); +} + +#include "kcmkabldapconfig.moc" diff --git a/kaddressbook/kcmconfigs/kcmkabldapconfig.h b/kaddressbook/kcmconfigs/kcmkabldapconfig.h new file mode 100644 index 000000000..85e67053a --- /dev/null +++ b/kaddressbook/kcmconfigs/kcmkabldapconfig.h @@ -0,0 +1,48 @@ +/* + 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 KCMKABLDAPCONFIG_H +#define KCMKABLDAPCONFIG_H + +#include <kcmodule.h> + +#include <qwidget.h> + +class LDAPOptionsWidget; + +class KCMKabLdapConfig : public KCModule +{ + Q_OBJECT + + public: + KCMKabLdapConfig( QWidget *parent = 0, const char *name = 0 ); + + virtual void load(); + virtual void save(); + virtual void defaults(); + + private: + LDAPOptionsWidget *mConfigWidget; +}; + +#endif diff --git a/kaddressbook/kcmconfigs/ldapoptionswidget.cpp b/kaddressbook/kcmconfigs/ldapoptionswidget.cpp new file mode 100644 index 000000000..df80ad872 --- /dev/null +++ b/kaddressbook/kcmconfigs/ldapoptionswidget.cpp @@ -0,0 +1,303 @@ +/* + This file is part of KAddressBook. + Copyright (c) 2002 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 <qgroupbox.h> +#include <qheader.h> +#include <qlabel.h> +#include <qlayout.h> +#include <qpushbutton.h> +#include <qtoolbutton.h> +#include <qstring.h> + +#include <kapplication.h> +#include <kbuttonbox.h> +#include <kconfig.h> +#include <klistview.h> +#include <klocale.h> + +#include "addhostdialog.h" +#include "ldapoptionswidget.h" +#include <qvgroupbox.h> +#include <qhbox.h> +#include <qvbox.h> +#include <kiconloader.h> + +class LDAPItem : public QCheckListItem +{ + public: + LDAPItem( QListView *parent, const KPIM::LdapServer &server, bool isActive = false ) + : QCheckListItem( parent, parent->lastItem(), QString::null, QCheckListItem::CheckBox ), + mIsActive( isActive ) + { + setServer( server ); + } + + void setServer( const KPIM::LdapServer &server ) + { + mServer = server; + + setText( 0, mServer.host() ); + } + + const KPIM::LdapServer &server() const { return mServer; } + + void setIsActive( bool isActive ) { mIsActive = isActive; } + bool isActive() const { return mIsActive; } + + private: + KPIM::LdapServer mServer; + bool mIsActive; +}; + +LDAPOptionsWidget::LDAPOptionsWidget( QWidget* parent, const char* name ) + : QWidget( parent, name ) +{ + initGUI(); + + mHostListView->setSorting( -1 ); + mHostListView->setAllColumnsShowFocus( true ); + mHostListView->setFullWidth( true ); + mHostListView->addColumn( QString::null ); + mHostListView->header()->hide(); + + connect( mHostListView, SIGNAL( selectionChanged( QListViewItem* ) ), + SLOT( slotSelectionChanged( QListViewItem* ) ) ); + connect( mHostListView, SIGNAL(doubleClicked( QListViewItem *, const QPoint &, int )), this, SLOT(slotEditHost())); + connect( mHostListView, SIGNAL( clicked( QListViewItem* ) ), + SLOT( slotItemClicked( QListViewItem* ) ) ); + + connect( mUpButton, SIGNAL( clicked() ), this, SLOT( slotMoveUp() ) ); + connect( mDownButton, SIGNAL( clicked() ), this, SLOT( slotMoveDown() ) ); +} + +LDAPOptionsWidget::~LDAPOptionsWidget() +{ +} + +void LDAPOptionsWidget::slotSelectionChanged( QListViewItem *item ) +{ + bool state = ( item != 0 ); + mEditButton->setEnabled( state ); + mRemoveButton->setEnabled( state ); + mDownButton->setEnabled( item && item->itemBelow() ); + mUpButton->setEnabled( item && item->itemAbove() ); +} + +void LDAPOptionsWidget::slotItemClicked( QListViewItem *item ) +{ + LDAPItem *ldapItem = dynamic_cast<LDAPItem*>( item ); + if ( !ldapItem ) + return; + + if ( ldapItem->isOn() != ldapItem->isActive() ) { + emit changed( true ); + ldapItem->setIsActive( ldapItem->isOn() ); + } +} + +void LDAPOptionsWidget::slotAddHost() +{ + KPIM::LdapServer server; + AddHostDialog dlg( &server, this ); + + if ( dlg.exec() && !server.host().isEmpty() ) { + new LDAPItem( mHostListView, server ); + + emit changed( true ); + } +} + +void LDAPOptionsWidget::slotEditHost() +{ + LDAPItem *item = dynamic_cast<LDAPItem*>( mHostListView->currentItem() ); + if ( !item ) + return; + + KPIM::LdapServer server = item->server(); + AddHostDialog dlg( &server, this ); + dlg.setCaption( i18n( "Edit Host" ) ); + + if ( dlg.exec() && !server.host().isEmpty() ) { + item->setServer( server ); + + emit changed( true ); + } +} + +void LDAPOptionsWidget::slotRemoveHost() +{ + QListViewItem *item = mHostListView->currentItem(); + if ( !item ) + return; + + mHostListView->takeItem( item ); + delete item; + + slotSelectionChanged( mHostListView->currentItem() ); + + emit changed( true ); +} + +static void swapItems( LDAPItem *item, LDAPItem *other ) +{ + KPIM::LdapServer server = item->server(); + bool isActive = item->isActive(); + item->setServer( other->server() ); + item->setIsActive( other->isActive() ); + item->setOn( other->isActive() ); + other->setServer( server ); + other->setIsActive( isActive ); + other->setOn( isActive ); +} + +void LDAPOptionsWidget::slotMoveUp() +{ + LDAPItem *item = static_cast<LDAPItem *>( mHostListView->selectedItem() ); + if ( !item ) return; + LDAPItem *above = static_cast<LDAPItem *>( item->itemAbove() ); + if ( !above ) return; + swapItems( item, above ); + mHostListView->setCurrentItem( above ); + mHostListView->setSelected( above, true ); + emit changed( true ); +} + +void LDAPOptionsWidget::slotMoveDown() +{ + LDAPItem *item = static_cast<LDAPItem *>( mHostListView->selectedItem() ); + if ( !item ) return; + LDAPItem *below = static_cast<LDAPItem *>( item->itemBelow() ); + if ( !below ) return; + swapItems( item, below ); + mHostListView->setCurrentItem( below ); + mHostListView->setSelected( below, true ); + emit changed( true ); +} + +void LDAPOptionsWidget::restoreSettings() +{ + mHostListView->clear(); + KConfig *config = KPIM::LdapSearch::config(); + KConfigGroupSaver saver( config, "LDAP" ); + + QString host; + + uint count = config->readUnsignedNumEntry( "NumSelectedHosts"); + for ( uint i = 0; i < count; ++i ) { + KPIM::LdapServer server; + KPIM::LdapSearch::readConfig( server, config, i, true ); + LDAPItem *item = new LDAPItem( mHostListView, server, true ); + item->setOn( true ); + } + + count = config->readUnsignedNumEntry( "NumHosts" ); + for ( uint i = 0; i < count; ++i ) { + KPIM::LdapServer server; + KPIM::LdapSearch::readConfig( server, config, i, false ); + new LDAPItem( mHostListView, server ); + } + + emit changed( false ); +} + +void LDAPOptionsWidget::saveSettings() +{ + KConfig *config = KPIM::LdapSearch::config(); + config->deleteGroup( "LDAP" ); + + KConfigGroupSaver saver( config, "LDAP" ); + + uint selected = 0; uint unselected = 0; + QListViewItemIterator it( mHostListView ); + for ( ; it.current(); ++it ) { + LDAPItem *item = dynamic_cast<LDAPItem*>( it.current() ); + if ( !item ) + continue; + + KPIM::LdapServer server = item->server(); + if ( item->isOn() ) { + KPIM::LdapSearch::writeConfig( server, config, selected, true ); + selected++; + } else { + KPIM::LdapSearch::writeConfig( server, config, unselected, false ); + unselected++; + } + } + + config->writeEntry( "NumSelectedHosts", selected ); + config->writeEntry( "NumHosts", unselected ); + config->sync(); + + emit changed( false ); +} + +void LDAPOptionsWidget::defaults() +{ + // add default configuration here +} + +void LDAPOptionsWidget::initGUI() +{ + QVBoxLayout *layout = new QVBoxLayout( this, 0, KDialog::spacingHint() ); + + QVGroupBox *groupBox = new QVGroupBox( i18n( "LDAP Servers" ), this ); + groupBox->setInsideSpacing( KDialog::spacingHint() ); + groupBox->setInsideMargin( KDialog::marginHint() ); + + // Contents of the QVGroupBox: label and hbox + /*QLabel *label =*/ new QLabel( i18n( "Check all servers that should be used:" ), groupBox ); + + QHBox* hBox = new QHBox( groupBox ); + hBox->setSpacing( 6 ); + // Contents of the hbox: listview and up/down buttons on the right (vbox) + mHostListView = new KListView( hBox ); + + QVBox* upDownBox = new QVBox( hBox ); + upDownBox->setSpacing( 6 ); + mUpButton = new QToolButton( upDownBox, "mUpButton" ); + mUpButton->setIconSet( BarIconSet( "up", KIcon::SizeSmall ) ); + mUpButton->setEnabled( false ); // b/c no item is selected yet + + mDownButton = new QToolButton( upDownBox, "mDownButton" ); + mDownButton->setIconSet( BarIconSet( "down", KIcon::SizeSmall ) ); + mDownButton->setEnabled( false ); // b/c no item is selected yet + + QWidget* spacer = new QWidget( upDownBox ); + upDownBox->setStretchFactor( spacer, 100 ); + + layout->addWidget( groupBox ); + + KButtonBox *buttons = new KButtonBox( this ); + buttons->addButton( i18n( "&Add Host..." ), this, SLOT( slotAddHost() ) ); + mEditButton = buttons->addButton( i18n( "&Edit Host..." ), this, SLOT( slotEditHost() ) ); + mEditButton->setEnabled( false ); + mRemoveButton = buttons->addButton( i18n( "&Remove Host" ), this, SLOT( slotRemoveHost() ) ); + mRemoveButton->setEnabled( false ); + buttons->layout(); + + layout->addWidget( buttons ); + + resize( QSize( 460, 300 ).expandedTo( sizeHint() ) ); +} + +#include "ldapoptionswidget.moc" diff --git a/kaddressbook/kcmconfigs/ldapoptionswidget.h b/kaddressbook/kcmconfigs/ldapoptionswidget.h new file mode 100644 index 000000000..c63b96dd7 --- /dev/null +++ b/kaddressbook/kcmconfigs/ldapoptionswidget.h @@ -0,0 +1,71 @@ +/* + 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 LDAPOPTIONSWIDGET_H +#define LDAPOPTIONSWIDGET_H + +#include <qwidget.h> + +class QToolButton; +class KListView; +class QListViewItem; +class QPushButton; + +class LDAPOptionsWidget : public QWidget +{ + Q_OBJECT + + public: + LDAPOptionsWidget( QWidget* parent = 0, const char* name = 0 ); + ~LDAPOptionsWidget(); + + void restoreSettings(); + void saveSettings(); + void defaults(); + + signals: + void changed( bool ); + + private slots: + void slotAddHost(); + void slotEditHost(); + void slotRemoveHost(); + void slotSelectionChanged( QListViewItem* ); + void slotItemClicked( QListViewItem* ); + void slotMoveUp(); + void slotMoveDown(); + + private: + void initGUI(); + + KListView* mHostListView; + + QPushButton* mAddButton; + QPushButton* mEditButton; + QPushButton* mRemoveButton; + + QToolButton* mUpButton; + QToolButton* mDownButton; +}; + +#endif diff --git a/kaddressbook/keywidget.cpp b/kaddressbook/keywidget.cpp new file mode 100644 index 000000000..ab0f8fa7f --- /dev/null +++ b/kaddressbook/keywidget.cpp @@ -0,0 +1,201 @@ +/* + 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 <qlabel.h> +#include <qlayout.h> +#include <qpushbutton.h> + +#include <kapplication.h> +#include <kcombobox.h> +#include <kdialog.h> +#include <kfiledialog.h> +#include <kio/netaccess.h> +#include <kinputdialog.h> +#include <klocale.h> +#include <kmessagebox.h> +#include <ktempfile.h> + +#include "keywidget.h" + +KeyWidget::KeyWidget( QWidget *parent, const char *name ) + : QWidget( parent, name ) +{ + QGridLayout *layout = new QGridLayout( this, 4, 2, KDialog::marginHint(), + KDialog::spacingHint() ); + + QLabel *label = new QLabel( i18n( "Keys:" ), this ); + layout->addWidget( label, 0, 0 ); + + mKeyCombo = new KComboBox( this ); + layout->addWidget( mKeyCombo, 0, 1 ); + + mAddButton = new QPushButton( i18n( "Add..." ), this ); + layout->addMultiCellWidget( mAddButton, 1, 1, 0, 1 ); + + mRemoveButton = new QPushButton( i18n( "Remove" ), this ); + mRemoveButton->setEnabled( false ); + layout->addMultiCellWidget( mRemoveButton, 2, 2, 0, 1 ); + + mExportButton = new QPushButton( i18n( "Export..." ), this ); + mExportButton->setEnabled( false ); + layout->addMultiCellWidget( mExportButton, 3, 3, 0, 1 ); + + connect( mAddButton, SIGNAL( clicked() ), SLOT( addKey() ) ); + connect( mRemoveButton, SIGNAL( clicked() ), SLOT( removeKey() ) ); + connect( mExportButton, SIGNAL( clicked() ), SLOT( exportKey() ) ); +} + +KeyWidget::~KeyWidget() +{ +} + +void KeyWidget::setKeys( const KABC::Key::List &list ) +{ + mKeyList = list; + + updateKeyCombo(); +} + +KABC::Key::List KeyWidget::keys() const +{ + return mKeyList; +} + +void KeyWidget::addKey() +{ + QMap<QString, int> keyMap; + QStringList keyTypeNames; + QStringList existingKeyTypes; + + KABC::Key::List::ConstIterator listIt; + for ( listIt = mKeyList.begin(); listIt != mKeyList.end(); ++listIt ) { + if ( (*listIt).type() != KABC::Key::Custom ) + existingKeyTypes.append( KABC::Key::typeLabel( (*listIt).type() ) ); + } + + KABC::Key::TypeList typeList = KABC::Key::typeList(); + KABC::Key::TypeList::ConstIterator it; + for ( it = typeList.begin(); it != typeList.end(); ++it ) { + if ( (*it) != KABC::Key::Custom && + !existingKeyTypes.contains( KABC::Key::typeLabel( *it ) ) ) { + keyMap.insert( KABC::Key::typeLabel( *it ), *it ); + keyTypeNames.append( KABC::Key::typeLabel( *it ) ); + } + } + + bool ok; + QString name = KInputDialog::getItem( i18n( "Key Type" ), i18n( "Select the key type:" ), keyTypeNames, 0, true, &ok ); + if ( !ok || name.isEmpty() ) + return; + + int type = keyMap[ name ]; + if ( !keyTypeNames.contains( name ) ) + type = KABC::Key::Custom; + + KURL url = KFileDialog::getOpenURL(); + if ( url.isEmpty() ) + return; + + QString tmpFile; + if ( KIO::NetAccess::download( url, tmpFile, this ) ) { + QFile file( tmpFile ); + if ( !file.open( IO_ReadOnly ) ) { + QString text( i18n( "<qt>Unable to open file <b>%1</b>.</qt>" ) ); + KMessageBox::error( this, text.arg( url.url() ) ); + return; + } + + QTextStream s( &file ); + QString data; + + s.setEncoding( QTextStream::UnicodeUTF8 ); + s >> data; + file.close(); + + KABC::Key key( data, type ); + if ( type == KABC::Key::Custom ) + key.setCustomTypeString( name ); + mKeyList.append( key ); + + emit changed(); + + KIO::NetAccess::removeTempFile( tmpFile ); + } + + updateKeyCombo(); +} + +void KeyWidget::removeKey() +{ + int pos = mKeyCombo->currentItem(); + if ( pos == -1 ) + return; + + QString type = mKeyCombo->currentText(); + QString text = i18n( "<qt>Do you really want to remove the key <b>%1</b>?</qt>" ); + if ( KMessageBox::warningContinueCancel( this, text.arg( type ), "", KGuiItem( i18n("&Delete"), "editdelete") ) == KMessageBox::Cancel ) + return; + + mKeyList.remove( mKeyList.at( pos ) ); + emit changed(); + + updateKeyCombo(); +} + +void KeyWidget::exportKey() +{ + KABC::Key key = (*mKeyList.at( mKeyCombo->currentItem() ) ); + + KURL url = KFileDialog::getSaveURL(); + + KTempFile tempFile; + QTextStream *s = tempFile.textStream(); + s->setEncoding( QTextStream::UnicodeUTF8 ); + (*s) << key.textData(); + tempFile.close(); + + KIO::NetAccess::upload( tempFile.name(), url, kapp->mainWidget() ); +} + +void KeyWidget::updateKeyCombo() +{ + int pos = mKeyCombo->currentItem(); + mKeyCombo->clear(); + + KABC::Key::List::ConstIterator it; + for ( it = mKeyList.begin(); it != mKeyList.end(); ++it ) { + if ( (*it).type() == KABC::Key::Custom ) + mKeyCombo->insertItem( (*it).customTypeString() ); + else + mKeyCombo->insertItem( KABC::Key::typeLabel( (*it).type() ) ); + } + + mKeyCombo->setCurrentItem( pos ); + + bool state = ( mKeyList.count() != 0 ); + mRemoveButton->setEnabled( state ); + mExportButton->setEnabled( state ); +} + +#include "keywidget.moc" diff --git a/kaddressbook/keywidget.h b/kaddressbook/keywidget.h new file mode 100644 index 000000000..712c26c00 --- /dev/null +++ b/kaddressbook/keywidget.h @@ -0,0 +1,65 @@ +/* + 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 KEYWIDGET_H +#define KEYWIDGET_H + +#include <qwidget.h> +#include <kabc/key.h> + +class KComboBox; + +class QPushButton; + +class KeyWidget : public QWidget +{ + Q_OBJECT + + public: + KeyWidget( QWidget *parent, const char *name = 0 ); + ~KeyWidget(); + + void setKeys( const KABC::Key::List &list ); + KABC::Key::List keys() const; + + signals: + void changed(); + + private slots: + void addKey(); + void removeKey(); + void exportKey(); + + private: + void updateKeyCombo(); + + KComboBox *mKeyCombo; + + QPushButton *mAddButton; + QPushButton *mRemoveButton; + QPushButton *mExportButton; + + KABC::Key::List mKeyList; +}; + +#endif diff --git a/kaddressbook/ldapsearchdialog.cpp b/kaddressbook/ldapsearchdialog.cpp new file mode 100644 index 000000000..706b982ff --- /dev/null +++ b/kaddressbook/ldapsearchdialog.cpp @@ -0,0 +1,634 @@ +/* ldapsearchdialogimpl.cpp - LDAP access + * Copyright (C) 2002 Klar�vdalens Datakonsult AB + * + * Author: Steffen Hansen <hansen@kde.org> + * + * This file 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 file 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 + */ + +#include "config.h" + +#include <qcheckbox.h> +#include <qgroupbox.h> +#include <qheader.h> +#include <qlabel.h> +#include <qlayout.h> +#include <qlistview.h> +#include <qmap.h> +#include <qpushbutton.h> + +#include <addresseelineedit.h> +#include <kapplication.h> +#include <kbuttonbox.h> +#include <kcombobox.h> +#include <kconfig.h> +#include <klineedit.h> +#include <klocale.h> +#include <kmessagebox.h> + +#include "kabcore.h" +#include "ldapsearchdialog.h" +#include "kablock.h" + +#ifdef KDEPIM_NEW_DISTRLISTS +#include "distributionlistpicker.h" +#endif + +static QString asUtf8( const QByteArray &val ) +{ + if ( val.isEmpty() ) + return QString::null; + + const char *data = val.data(); + + //QString::fromUtf8() bug workaround + if ( data[ val.size() - 1 ] == '\0' ) + return QString::fromUtf8( data, val.size() - 1 ); + else + return QString::fromUtf8( data, val.size() ); +} + +static QString join( const KPIM::LdapAttrValue& lst, const QString& sep ) +{ + QString res; + bool alredy = false; + for ( KPIM::LdapAttrValue::ConstIterator it = lst.begin(); it != lst.end(); ++it ) { + if ( alredy ) + res += sep; + alredy = true; + res += asUtf8( *it ); + } + return res; +} + +static QMap<QString, QString>& adrbookattr2ldap() +{ + static QMap<QString, QString> keys; + + if ( keys.isEmpty() ) { + keys[ i18n( "Title" ) ] = "title"; + keys[ i18n( "Full Name" ) ] = "cn"; + keys[ i18n( "Email" ) ] = "mail"; + keys[ i18n( "Home Number" ) ] = "homePhone"; + keys[ i18n( "Work Number" ) ] = "telephoneNumber"; + keys[ i18n( "Mobile Number" ) ] = "mobile"; + keys[ i18n( "Fax Number" ) ] = "facsimileTelephoneNumber"; + keys[ i18n( "Pager" ) ] = "pager"; + keys[ i18n( "Street") ] = "street"; + keys[ i18n( "State" ) ] = "st"; + keys[ i18n( "Country" ) ] = "co"; + keys[ i18n( "City" ) ] = "l"; + keys[ i18n( "Organization" ) ] = "o"; + keys[ i18n( "Company" ) ] = "Company"; + keys[ i18n( "Department" ) ] = "department"; + keys[ i18n( "Zip Code" ) ] = "postalCode"; + keys[ i18n( "Postal Address" ) ] = "postalAddress"; + keys[ i18n( "Description" ) ] = "description"; + keys[ i18n( "User ID" ) ] = "uid"; + } + return keys; +} + +class ContactListItem : public QListViewItem +{ + public: + ContactListItem( QListView* parent, const KPIM::LdapAttrMap& attrs ) + : QListViewItem( parent ), mAttrs( attrs ) + { } + + KPIM::LdapAttrMap mAttrs; + + virtual QString text( int col ) const + { + // Look up a suitable attribute for column col + const QString colName = listView()->columnText( col ); + const QString ldapAttrName = adrbookattr2ldap()[ colName ]; + return join( mAttrs[ ldapAttrName ], ", " ); + } +}; + +class LDAPSearchDialog::Private +{ + public: + static QValueList<ContactListItem*> selectedItems( QListView* ); + QMap<const ContactListItem*, QString> itemToServer; +}; + +QValueList<ContactListItem*> LDAPSearchDialog::Private::selectedItems( QListView* view ) +{ + QValueList<ContactListItem*> selected; + ContactListItem* cli = static_cast<ContactListItem*>( view->firstChild() ); + while ( cli ) { + if ( cli->isSelected() ) + selected.append( cli ); + cli = static_cast<ContactListItem*>( cli->nextSibling() ); + } + return selected; +} + +LDAPSearchDialog::LDAPSearchDialog( KABC::AddressBook *ab, KABCore *core, + QWidget* parent, const char* name ) + : KDialogBase( Plain, i18n( "Search for Addresses in Directory" ), Help | User1 | User2 | + Cancel, Default, parent, name, false, true ), + mAddressBook( ab ), mCore( core ), d( new Private ) +{ + setButtonCancel( KStdGuiItem::close() ); + QFrame *page = plainPage(); + QVBoxLayout *topLayout = new QVBoxLayout( page, marginHint(), spacingHint() ); + + QGroupBox *groupBox = new QGroupBox( i18n( "Search for Addresses in Directory" ), + page ); + groupBox->setFrameShape( QGroupBox::Box ); + groupBox->setFrameShadow( QGroupBox::Sunken ); + groupBox->setColumnLayout( 0, Qt::Vertical ); + QGridLayout *boxLayout = new QGridLayout( groupBox->layout(), 2, + 5, spacingHint() ); + boxLayout->setColStretch( 1, 1 ); + + QLabel *label = new QLabel( i18n( "Search for:" ), groupBox ); + boxLayout->addWidget( label, 0, 0 ); + + mSearchEdit = new KLineEdit( groupBox ); + boxLayout->addWidget( mSearchEdit, 0, 1 ); + label->setBuddy( mSearchEdit ); + + label = new QLabel( i18n( "In LDAP attribute", "in" ), groupBox ); + boxLayout->addWidget( label, 0, 2 ); + + mFilterCombo = new KComboBox( groupBox ); + mFilterCombo->insertItem( i18n( "Name" ) ); + mFilterCombo->insertItem( i18n( "Email" ) ); + mFilterCombo->insertItem( i18n( "Home Number" ) ); + mFilterCombo->insertItem( i18n( "Work Number" ) ); + boxLayout->addWidget( mFilterCombo, 0, 3 ); + + QSize buttonSize; + mSearchButton = new QPushButton( i18n( "Stop" ), groupBox ); + buttonSize = mSearchButton->sizeHint(); + mSearchButton->setText( i18n( "&Search" ) ); + if ( buttonSize.width() < mSearchButton->sizeHint().width() ) + buttonSize = mSearchButton->sizeHint(); + mSearchButton->setFixedWidth( buttonSize.width() ); + + mSearchButton->setDefault( true ); + boxLayout->addWidget( mSearchButton, 0, 4 ); + + mRecursiveCheckbox = new QCheckBox( i18n( "Recursive search" ), groupBox ); + mRecursiveCheckbox->setChecked( true ); + boxLayout->addMultiCellWidget( mRecursiveCheckbox, 1, 1, 0, 4 ); + + mSearchType = new KComboBox( groupBox ); + mSearchType->insertItem( i18n( "Contains" ) ); + mSearchType->insertItem( i18n( "Starts With" ) ); + boxLayout->addMultiCellWidget( mSearchType, 1, 1, 3, 4 ); + + topLayout->addWidget( groupBox ); + + mResultListView = new QListView( page ); + mResultListView->setSelectionMode( QListView::Multi ); + mResultListView->setAllColumnsShowFocus( true ); + mResultListView->setShowSortIndicator( true ); + topLayout->addWidget( mResultListView ); + + KButtonBox *buttons = new KButtonBox( page, Qt::Horizontal ); + buttons->addButton( i18n( "Select All" ), this, SLOT( slotSelectAll() ) ); + buttons->addButton( i18n( "Unselect All" ), this, SLOT( slotUnselectAll() ) ); + + topLayout->addWidget( buttons ); + + resize( QSize( 600, 400).expandedTo( minimumSizeHint() ) ); + + setButtonText( User1, i18n( "Add Selected" ) ); + + showButton( User2, false ); + +#ifdef KDEPIM_NEW_DISTRLISTS + showButton( User2, true ); + setButtonText( User2, i18n( "Add to Distribution List..." ) ); +#endif + + mNumHosts = 0; + mIsOK = false; + + connect( mRecursiveCheckbox, SIGNAL( toggled( bool ) ), + this, SLOT( slotSetScope( bool ) ) ); + connect( mSearchButton, SIGNAL( clicked() ), + this, SLOT( slotStartSearch() ) ); + + setTabOrder(mSearchEdit, mFilterCombo); + setTabOrder(mFilterCombo, mSearchButton); + mSearchEdit->setFocus(); + + restoreSettings(); +} + +LDAPSearchDialog::~LDAPSearchDialog() +{ + saveSettings(); + delete d; +} + +void LDAPSearchDialog::restoreSettings() +{ + // Create one KPIM::LdapClient per selected server and configure it. + + // First clean the list to make sure it is empty at + // the beginning of the process + mLdapClientList.setAutoDelete( true ); + mLdapClientList.clear(); + + KConfig kabConfig( "kaddressbookrc" ); + kabConfig.setGroup( "LDAPSearch" ); + mSearchType->setCurrentItem( kabConfig.readNumEntry( "SearchType", 0 ) ); + + // then read the config file and register all selected + // server in the list + KConfig* config = KPIM::LdapSearch::config(); + KConfigGroupSaver saver( config, "LDAP" ); + mNumHosts = config->readUnsignedNumEntry( "NumSelectedHosts" ); + if ( !mNumHosts ) { + KMessageBox::error( this, i18n( "You must select a LDAP server before searching.\nYou can do this from the menu Settings/Configure KAddressBook." ) ); + mIsOK = false; + } else { + mIsOK = true; + for ( int j = 0; j < mNumHosts; ++j ) { + KPIM::LdapClient* ldapClient = new KPIM::LdapClient( 0, this, "ldapclient" ); + KPIM::LdapServer ldapServer; + KPIM::LdapSearch::readConfig( ldapServer, config, j, true ); + ldapClient->setServer( ldapServer ); + QStringList attrs; + + for ( QMap<QString,QString>::ConstIterator it = adrbookattr2ldap().begin(); it != adrbookattr2ldap().end(); ++it ) + attrs << *it; + + ldapClient->setAttrs( attrs ); + + connect( ldapClient, SIGNAL( result( const KPIM::LdapObject& ) ), + this, SLOT( slotAddResult( const KPIM::LdapObject& ) ) ); + connect( ldapClient, SIGNAL( done() ), + this, SLOT( slotSearchDone() ) ); + connect( ldapClient, SIGNAL( error( const QString& ) ), + this, SLOT( slotError( const QString& ) ) ); + + mLdapClientList.append( ldapClient ); + } + +/** CHECKIT*/ + while ( mResultListView->header()->count() > 0 ) { + mResultListView->removeColumn(0); + } + + mResultListView->addColumn( i18n( "Full Name" ) ); + mResultListView->addColumn( i18n( "Email" ) ); + mResultListView->addColumn( i18n( "Home Number" ) ); + mResultListView->addColumn( i18n( "Work Number" ) ); + mResultListView->addColumn( i18n( "Mobile Number" ) ); + mResultListView->addColumn( i18n( "Fax Number" ) ); + mResultListView->addColumn( i18n( "Company" ) ); + mResultListView->addColumn( i18n( "Organization" ) ); + mResultListView->addColumn( i18n( "Street" ) ); + mResultListView->addColumn( i18n( "State" ) ); + mResultListView->addColumn( i18n( "Country" ) ); + mResultListView->addColumn( i18n( "Zip Code" ) ); + mResultListView->addColumn( i18n( "Postal Address" ) ); + mResultListView->addColumn( i18n( "City" ) ); + mResultListView->addColumn( i18n( "Department" ) ); + mResultListView->addColumn( i18n( "Description" ) ); + mResultListView->addColumn( i18n( "User ID" ) ); + mResultListView->addColumn( i18n( "Title" ) ); + + mResultListView->clear(); + d->itemToServer.clear(); + } +} + +void LDAPSearchDialog::saveSettings() +{ + KConfig config( "kaddressbookrc" ); + config.setGroup( "LDAPSearch" ); + config.writeEntry( "SearchType", mSearchType->currentItem() ); + config.sync(); +} + +void LDAPSearchDialog::cancelQuery() +{ + for ( KPIM::LdapClient* client = mLdapClientList.first(); client; client = mLdapClientList.next() ) { + client->cancelQuery(); + } +} + +void LDAPSearchDialog::slotAddResult( const KPIM::LdapObject& obj ) +{ + ContactListItem* item = new ContactListItem( mResultListView, obj.attrs ); + d->itemToServer[item] = obj.client->server().host(); +} + +void LDAPSearchDialog::slotSetScope( bool rec ) +{ + for ( KPIM::LdapClient* client = mLdapClientList.first(); client; client = mLdapClientList.next() ) { + if ( rec ) + client->setScope( "sub" ); + else + client->setScope( "one" ); + } +} + +QString LDAPSearchDialog::makeFilter( const QString& query, const QString& attr, + bool startsWith ) +{ + /* The reasoning behind this filter is: + * If it's a person, or a distlist, show it, even if it doesn't have an email address. + * If it's not a person, or a distlist, only show it if it has an email attribute. + * This allows both resource accounts with an email address which are not a person and + * person entries without an email address to show up, while still not showing things + * like structural entries in the ldap tree. */ + QString result( "&(|(objectclass=person)(objectclass=groupofnames)(mail=*))(" ); + if( query.isEmpty() ) + // Return a filter that matches everything + return result + "|(cn=*)(sn=*)" + ")"; + + if ( attr == i18n( "Name" ) ) { + result += startsWith ? "|(cn=%1*)(sn=%2*)" : "|(cn=*%1*)(sn=*%2*)"; + result = result.arg( query ).arg( query ); + } else { + result += (startsWith ? "%1=%2*" : "%1=*%2*"); + if ( attr == i18n( "Email" ) ) { + result = result.arg( "mail" ).arg( query ); + } else if ( attr == i18n( "Home Number" ) ) { + result = result.arg( "homePhone" ).arg( query ); + } else if ( attr == i18n( "Work Number" ) ) { + result = result.arg( "telephoneNumber" ).arg( query ); + } else { + // Error? + result = QString::null; + return result; + } + } + result += ")"; + return result; +} + +void LDAPSearchDialog::slotStartSearch() +{ + cancelQuery(); + + QApplication::setOverrideCursor( Qt::waitCursor ); + mSearchButton->setText( i18n( "Stop" ) ); + + disconnect( mSearchButton, SIGNAL( clicked() ), + this, SLOT( slotStartSearch() ) ); + connect( mSearchButton, SIGNAL( clicked() ), + this, SLOT( slotStopSearch() ) ); + + bool startsWith = (mSearchType->currentItem() == 1); + + QString filter = makeFilter( mSearchEdit->text().stripWhiteSpace(), mFilterCombo->currentText(), startsWith ); + + // loop in the list and run the KPIM::LdapClients + mResultListView->clear(); + d->itemToServer.clear(); + for ( KPIM::LdapClient* client = mLdapClientList.first(); client; client = mLdapClientList.next() ) + client->startQuery( filter ); + + saveSettings(); +} + +void LDAPSearchDialog::slotStopSearch() +{ + cancelQuery(); + slotSearchDone(); +} + +void LDAPSearchDialog::slotSearchDone() +{ + // If there are no more active clients, we are done. + for ( KPIM::LdapClient* client = mLdapClientList.first(); client; client = mLdapClientList.next() ) { + if ( client->isActive() ) + return; + } + + disconnect( mSearchButton, SIGNAL( clicked() ), + this, SLOT( slotStopSearch() ) ); + connect( mSearchButton, SIGNAL( clicked() ), + this, SLOT( slotStartSearch() ) ); + + mSearchButton->setText( i18n( "&Search" ) ); + QApplication::restoreOverrideCursor(); +} + +void LDAPSearchDialog::slotError( const QString& error ) +{ + QApplication::restoreOverrideCursor(); + KMessageBox::error( this, error ); +} + +void LDAPSearchDialog::closeEvent( QCloseEvent* e ) +{ + slotStopSearch(); + e->accept(); +} + +/*! + * Returns a ", " separated list of email addresses that were + * checked by the user + */ +QString LDAPSearchDialog::selectedEMails() const +{ + QStringList result; + ContactListItem* cli = static_cast<ContactListItem*>( mResultListView->firstChild() ); + while ( cli ) { + if ( cli->isSelected() ) { + QString email = asUtf8( cli->mAttrs[ "mail" ].first() ).stripWhiteSpace(); + if ( !email.isEmpty() ) { + QString name = asUtf8( cli->mAttrs[ "cn" ].first() ).stripWhiteSpace(); + if ( name.isEmpty() ) { + result << email; + } else { + result << name + " <" + email + ">"; + } + } + } + cli = static_cast<ContactListItem*>( cli->nextSibling() ); + } + + return result.join( ", " ); +} + +void LDAPSearchDialog::slotHelp() +{ + kapp->invokeHelp( "ldap-queries" ); +} + +void LDAPSearchDialog::slotUnselectAll() +{ + mResultListView->selectAll( false ); +} + +void LDAPSearchDialog::slotSelectAll() +{ + mResultListView->selectAll( true ); +} + +KABC::Addressee LDAPSearchDialog::convertLdapAttributesToAddressee( const KPIM::LdapAttrMap& attrs ) +{ + KABC::Addressee addr; + + // name + addr.setNameFromString( asUtf8( attrs["cn"].first() ) ); + + // email + KPIM::LdapAttrValue lst = attrs["mail"]; + KPIM::LdapAttrValue::ConstIterator it = lst.begin(); + bool pref = true; + if ( it != lst.end() ) { + addr.insertEmail( asUtf8( *it ), pref ); + pref = false; + ++it; + } + + addr.setOrganization( asUtf8( attrs[ "o" ].first() ) ); + if ( addr.organization().isEmpty() ) + addr.setOrganization( asUtf8( attrs[ "Company" ].first() ) ); + +#if KDE_IS_VERSION(3,5,8) + addr.setDepartment( asUtf8( attrs[ "department" ].first() ) ); +#else + addr.insertCustom( "KADDRESSBOOK", "X-Department", asUtf8( attrs[ "department" ].first() ) ); +#endif + + // Address + KABC::Address workAddr( KABC::Address::Work ); + + workAddr.setStreet( asUtf8( attrs[ "street" ].first()) ); + workAddr.setLocality( asUtf8( attrs[ "l" ].first()) ); + workAddr.setRegion( asUtf8( attrs[ "st" ].first())); + workAddr.setPostalCode( asUtf8( attrs[ "postalCode" ].first()) ); + workAddr.setCountry( asUtf8( attrs[ "co" ].first()) ); + + if ( !workAddr.isEmpty() ) + addr.insertAddress( workAddr ); + + // phone + KABC::PhoneNumber homeNr = asUtf8( attrs[ "homePhone" ].first() ); + homeNr.setType( KABC::PhoneNumber::Home ); + addr.insertPhoneNumber( homeNr ); + + KABC::PhoneNumber workNr = asUtf8( attrs[ "telephoneNumber" ].first() ); + workNr.setType( KABC::PhoneNumber::Work ); + addr.insertPhoneNumber( workNr ); + + KABC::PhoneNumber faxNr = asUtf8( attrs[ "facsimileTelephoneNumber" ].first() ); + faxNr.setType( KABC::PhoneNumber::Fax ); + addr.insertPhoneNumber( faxNr ); + + KABC::PhoneNumber cellNr = asUtf8( attrs[ "mobile" ].first() ); + cellNr.setType( KABC::PhoneNumber::Cell ); + addr.insertPhoneNumber( cellNr ); + + KABC::PhoneNumber pagerNr = asUtf8( attrs[ "pager" ].first() ); + pagerNr.setType( KABC::PhoneNumber::Pager ); + addr.insertPhoneNumber( pagerNr ); + return addr; +} + +#ifdef KDEPIM_NEW_DISTRLISTS +KPIM::DistributionList LDAPSearchDialog::selectDistributionList() +{ + QGuardedPtr<KPIM::DistributionListPickerDialog> picker = new KPIM::DistributionListPickerDialog( mCore->addressBook(), this ); + picker->setLabelText( i18n( "Select a distribution list to add the selected contacts to." ) ); + picker->setCaption( i18n( "Select Distribution List" ) ); + picker->exec(); + const KPIM::DistributionList list = KPIM::DistributionList::findByName( mCore->addressBook(), picker +? picker->selectedDistributionList() : QString() ); + delete picker; + return list; +} +#endif + +KABC::Addressee::List LDAPSearchDialog::importContactsUnlessTheyExist( const QValueList<ContactListItem*>& selectedItems, + KABC::Resource * const resource ) +{ + const QDateTime now = QDateTime::currentDateTime(); + QStringList importedAddrs; + KABC::Addressee::List localAddrs; + + KABLock::self( mCore->addressBook() )->lock( resource ); + + for ( QValueList<ContactListItem*>::ConstIterator it = selectedItems.begin(); it != selectedItems.end(); ++it ) { + const ContactListItem * const cli = *it; + KABC::Addressee addr = convertLdapAttributesToAddressee( cli->mAttrs ); + const KABC::Addressee::List existing = mCore->addressBook()->findByEmail( addr.preferredEmail() ); + + if ( existing.isEmpty() ) { + addr.setUid( KApplication::randomString( 10 ) ); + addr.setNote( i18n( "arguments are host name, datetime", "Imported from LDAP directory %1 on %2" ).arg( d->itemToServer[cli], KGlobal::locale()->formatDateTime( now ) ) ); + addr.setResource( resource ); + mCore->addressBook()->insertAddressee( addr ); + importedAddrs.append( addr.fullEmail() ); + localAddrs.append( addr ); + } else { + localAddrs.append( existing.first() ); + } + } + KABLock::self( mCore->addressBook() )->unlock( resource ); + if ( !importedAddrs.isEmpty() ) { + KMessageBox::informationList( this, i18n( "The following contact was imported into your address book:", + "The following %n contacts were imported into your address book:", importedAddrs.count() ), + importedAddrs ); + emit addresseesAdded(); + } + return localAddrs; +} + +void LDAPSearchDialog::slotUser2() +{ +#ifdef KDEPIM_NEW_DISTRLISTS + KABC::Resource *resource = mCore->requestResource( this ); + if ( !resource ) return; + + const QValueList<ContactListItem*> selectedItems = d->selectedItems( mResultListView ); + if ( selectedItems.isEmpty() ) { + KMessageBox::information( this, i18n( "Please select the contacts you want to add to the distribution list." ), i18n( "No Contacts Selected" ) ); + return; + } + KPIM::DistributionList dist = selectDistributionList(); + if ( dist.isEmpty() ) + return; + + + KABC::Addressee::List localAddrs = importContactsUnlessTheyExist( selectedItems, resource ); + + if ( localAddrs.isEmpty() ) + return; + + for ( KABC::Addressee::List::ConstIterator it = localAddrs.begin(); it != localAddrs.end(); ++it ) { + dist.insertEntry( *it, QString() ); + } + KABLock::self( mCore->addressBook() )->lock( resource ); + mCore->addressBook()->insertAddressee( dist ); + KABLock::self( mCore->addressBook() )->unlock( resource ); + emit addresseesAdded(); +#endif +} + +void LDAPSearchDialog::slotUser1() +{ + KABC::Resource *resource = mCore->requestResource( this ); + if ( !resource ) return; + const QValueList<ContactListItem*> selectedItems = d->selectedItems( mResultListView ); + importContactsUnlessTheyExist( selectedItems, resource ); +} + +#include "ldapsearchdialog.moc" diff --git a/kaddressbook/ldapsearchdialog.h b/kaddressbook/ldapsearchdialog.h new file mode 100644 index 000000000..dba41fc54 --- /dev/null +++ b/kaddressbook/ldapsearchdialog.h @@ -0,0 +1,117 @@ +/* ldapsearchdialogimpl.h - LDAP access + * Copyright (C) 2002 Klar�lvdalens Datakonsult AB + * + * Author: Steffen Hansen <hansen@kde.org> + * + * This file 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 file 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 + */ + +#ifndef LDAPSEARCHDIALOG_H +#define LDAPSEARCHDIALOG_H + +#include "config.h" + +#include <qptrlist.h> + +#include <kabc/addressbook.h> +#include <ldapclient.h> +#include <kdialogbase.h> + +#ifdef KDEPIM_NEW_DISTRLISTS +#include <libkdepim/distributionlist.h> +#endif + +class KAddressBookTableView; +class KComboBox; +class KLineEdit; + +class QCheckBox; +class QListView; +class QPushButton; +class KABCore; +class ContactListItem; + +namespace KABC { + class Resource; +} + +class LDAPSearchDialog : public KDialogBase +{ + Q_OBJECT + + public: + LDAPSearchDialog( KABC::AddressBook *ab, KABCore *core, QWidget* parent, const char* name = 0 ); + ~LDAPSearchDialog(); + + bool isOK() const { return mIsOK; } + + void restoreSettings(); + + signals: + void addresseesAdded(); + + protected slots: + void slotAddResult( const KPIM::LdapObject& obj ); + void slotSetScope( bool rec ); + void slotStartSearch(); + void slotStopSearch(); + void slotSearchDone(); + void slotError( const QString& ); + virtual void slotHelp(); + virtual void slotUser1(); + virtual void slotUser2(); + void slotSelectAll(); + void slotUnselectAll(); + /** + * Traverses the given items and adds them to the given resource, + * unless they already exist. Returns the list of both the added + * and the existing contacts. + */ + KABC::Addressee::List importContactsUnlessTheyExist( const QValueList<ContactListItem*>& items, KABC::Resource * const resource ); + + protected: + QString selectedEMails() const; + + virtual void closeEvent( QCloseEvent* ); + + private: + void saveSettings(); + static KABC::Addressee convertLdapAttributesToAddressee( const KPIM::LdapAttrMap& attrs ); +#ifdef KDEPIM_NEW_DISTRLISTS + KPIM::DistributionList selectDistributionList(); +#endif + + QString makeFilter( const QString& query, const QString& attr, bool startsWith ); + + void cancelQuery(); + + int mNumHosts; + QPtrList<KPIM::LdapClient> mLdapClientList; + bool mIsOK; + KABC::AddressBook *mAddressBook; + KABCore *mCore; + + KComboBox* mFilterCombo; + KComboBox* mSearchType; + KLineEdit* mSearchEdit; + + QCheckBox* mRecursiveCheckbox; + QListView* mResultListView; + QPushButton* mSearchButton; + class Private; + Private* const d; +}; + +#endif diff --git a/kaddressbook/main.cpp b/kaddressbook/main.cpp new file mode 100644 index 000000000..bfb5f8159 --- /dev/null +++ b/kaddressbook/main.cpp @@ -0,0 +1,130 @@ +/* + This file is part of KAddressBook. + Copyright (C) 1999 Don Sanders <sanders@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 <stdlib.h> +#include <unistd.h> + +#include <qstring.h> + +#include <kabc/stdaddressbook.h> +#include <kaboutdata.h> +#include <kcmdlineargs.h> +#include <kcrash.h> +#include <kdebug.h> +#include <klocale.h> +#include <kstartupinfo.h> +#include <kuniqueapplication.h> +#include <kwin.h> + +#include "kaddressbookmain.h" +#include "kaddressbook_options.h" +#include "kabcore.h" + +class KAddressBookApp : public KUniqueApplication { + public: + KAddressBookApp() : mMainWin( 0 ), mDefaultIsOpen( false ) {} + ~KAddressBookApp() {} + + int newInstance(); + + private: + KAddressBookMain *mMainWin; + bool mDefaultIsOpen; +}; + +int KAddressBookApp::newInstance() +{ + if ( isRestored() ) { + // There can only be one main window + if ( KMainWindow::canBeRestored( 1 ) ) { + mMainWin = new KAddressBookMain; + setMainWidget( mMainWin ); + mMainWin->show(); + mMainWin->restore( 1 ); + } + } else { + KCmdLineArgs *args = KCmdLineArgs::parsedArgs(); + + if ( args->isSet( "editor-only" ) ) { + if ( !mMainWin ) { + mMainWin = new KAddressBookMain; + setMainWidget( mMainWin ); + mMainWin->hide(); + } + // otherwise, leave the window like it is (hidden or shown) + KStartupInfo::appStarted(); + } else { + QString file; + if ( args->isSet( "document" ) ) { + file = args->getOption( "document" ); + } + if ( !( file.isEmpty() && mDefaultIsOpen ) ) { + if ( !mMainWin ) { + mMainWin = new KAddressBookMain( file ); + setMainWidget( mMainWin ); + mMainWin->show(); + } else { + KAddressBookMain *m = new KAddressBookMain( file ); + m->show(); + } + if ( file.isEmpty() ) mDefaultIsOpen = true; + } + } + + mMainWin->handleCommandLine(); + } + + // Handle startup notification and window activation + // We do it ourselves instead of calling KUniqueApplication::newInstance + // to avoid the show() call there. +#if defined Q_WS_X11 && ! defined K_WS_QTONLY + static bool firstInstance = true; + + if ( !firstInstance ) + KStartupInfo::setNewStartupId( mMainWin, kapp->startupId() ); + + firstInstance = false; +#endif + + return 0; +} + +int main( int argc, char *argv[] ) +{ + KLocale::setMainCatalogue( "kaddressbook" ); + + KCmdLineArgs::init( argc, argv, KABCore::createAboutData() ); + KCmdLineArgs::addCmdLineOptions( kaddressbook_options ); + KUniqueApplication::addCmdLineOptions(); + + if ( !KAddressBookApp::start() ) + return 0; + + KAddressBookApp app; + KGlobal::locale()->insertCatalogue( "libkdepim" ); + + bool ret = app.exec(); + while (KMainWindow::memberList->first()) + delete KMainWindow::memberList->first(); + return ret; +} diff --git a/kaddressbook/nameeditdialog.cpp b/kaddressbook/nameeditdialog.cpp new file mode 100644 index 000000000..fc29eda8d --- /dev/null +++ b/kaddressbook/nameeditdialog.cpp @@ -0,0 +1,321 @@ +/* + This file is part of KAddressBook. + Copyright (c) 2002 Mike Pilone <mpilone@slac.com> + + 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 <qlayout.h> +#include <qlabel.h> +#include <qlistbox.h> +#include <qlistview.h> +#include <qtooltip.h> +#include <qpushbutton.h> +#include <qcheckbox.h> +#include <qstring.h> +#include <qwhatsthis.h> + +#include <kaccelmanager.h> +#include <kapplication.h> +#include <kbuttonbox.h> +#include <kconfig.h> +#include <klineedit.h> +#include <klistview.h> +#include <kcombobox.h> +#include <klocale.h> +#include <kdebug.h> +#include <kiconloader.h> +#include <kmessagebox.h> + +#include "nameeditdialog.h" + +NameEditDialog::NameEditDialog( const KABC::Addressee &addr, int type, + bool readOnly, QWidget *parent, const char *name ) + : KDialogBase( Plain, i18n( "Edit Contact Name" ), Help | Ok | Cancel, + Ok, parent, name, true ), mAddressee( addr ) +{ + QWidget *page = plainPage(); + QGridLayout *layout = new QGridLayout( page ); + layout->setSpacing( spacingHint() ); + layout->addColSpacing( 2, 100 ); + QLabel *label; + + label = new QLabel( i18n( "Honorific prefixes:" ), page ); + layout->addWidget( label, 0, 0 ); + mPrefixCombo = new KComboBox( page ); + mPrefixCombo->setDuplicatesEnabled( false ); + mPrefixCombo->setEditable( true ); + mPrefixCombo->setEnabled( !readOnly ); + label->setBuddy( mPrefixCombo ); + layout->addMultiCellWidget( mPrefixCombo, 0, 0, 1, 2 ); + + QWhatsThis::add( mPrefixCombo, i18n( "The predefined honorific prefixes can be extended in the settings dialog." ) ); + + label = new QLabel( i18n( "Given name:" ), page ); + layout->addWidget( label, 1, 0 ); + mGivenNameEdit = new KLineEdit( page ); + mGivenNameEdit->setReadOnly( readOnly ); + label->setBuddy( mGivenNameEdit ); + layout->addMultiCellWidget( mGivenNameEdit, 1, 1, 1, 2 ); + + label = new QLabel( i18n( "Additional names:" ), page ); + layout->addWidget( label, 2, 0 ); + mAdditionalNameEdit = new KLineEdit( page ); + mAdditionalNameEdit->setReadOnly( readOnly ); + label->setBuddy( mAdditionalNameEdit ); + layout->addMultiCellWidget( mAdditionalNameEdit, 2, 2, 1, 2 ); + + label = new QLabel( i18n( "Family names:" ), page ); + layout->addWidget( label, 3, 0 ); + mFamilyNameEdit = new KLineEdit( page ); + mFamilyNameEdit->setReadOnly( readOnly ); + label->setBuddy( mFamilyNameEdit ); + layout->addMultiCellWidget( mFamilyNameEdit, 3, 3, 1, 2 ); + + label = new QLabel( i18n( "Honorific suffixes:" ), page ); + layout->addWidget( label, 4, 0 ); + mSuffixCombo = new KComboBox( page ); + mSuffixCombo->setDuplicatesEnabled( false ); + mSuffixCombo->setEditable( true ); + mSuffixCombo->setEnabled( !readOnly ); + label->setBuddy( mSuffixCombo ); + layout->addMultiCellWidget( mSuffixCombo, 4, 4, 1, 2 ); + + QWhatsThis::add( mSuffixCombo, i18n( "The predefined honorific suffixes can be extended in the settings dialog." ) ); + + label = new QLabel( i18n( "Formatted name:" ), page ); + layout->addWidget( label, 5, 0 ); + + mFormattedNameCombo = new KComboBox( page ); + mFormattedNameCombo->setEnabled( !readOnly ); + layout->addWidget( mFormattedNameCombo, 5, 1 ); + connect( mFormattedNameCombo, SIGNAL( activated( int ) ), SLOT( typeChanged( int ) ) ); + + mFormattedNameEdit = new KLineEdit( page ); + mFormattedNameEdit->setEnabled( type == CustomName && !readOnly ); + layout->addWidget( mFormattedNameEdit, 5, 2 ); + + mParseBox = new QCheckBox( i18n( "Parse name automatically" ), page ); + mParseBox->setEnabled( !readOnly ); + connect( mParseBox, SIGNAL( toggled(bool) ), SLOT( parseBoxChanged(bool) ) ); + connect( mParseBox, SIGNAL( toggled(bool) ), SLOT( modified() ) ); + layout->addMultiCellWidget( mParseBox, 6, 6, 0, 1 ); + + // Fill in the values + mFamilyNameEdit->setText( addr.familyName() ); + mGivenNameEdit->setText( addr.givenName() ); + mAdditionalNameEdit->setText( addr.additionalName() ); + mFormattedNameEdit->setText( addr.formattedName() ); + + // Prefix and suffix combos + KConfig config( "kabcrc" ); + config.setGroup( "General" ); + + QStringList sTitle; + sTitle += ""; + sTitle += i18n( "Dr." ); + sTitle += i18n( "Miss" ); + sTitle += i18n( "Mr." ); + sTitle += i18n( "Mrs." ); + sTitle += i18n( "Ms." ); + sTitle += i18n( "Prof." ); + sTitle += config.readListEntry( "Prefixes" ); + sTitle.sort(); + + QStringList sSuffix; + sSuffix += ""; + sSuffix += i18n( "I" ); + sSuffix += i18n( "II" ); + sSuffix += i18n( "III" ); + sSuffix += i18n( "Jr." ); + sSuffix += i18n( "Sr." ); + sSuffix += config.readListEntry( "Suffixes" ); + sSuffix.sort(); + + mPrefixCombo->insertStringList( sTitle ); + mSuffixCombo->insertStringList( sSuffix ); + + mPrefixCombo->setCurrentText( addr.prefix() ); + mSuffixCombo->setCurrentText( addr.suffix() ); + + mAddresseeConfig.setAddressee( addr ); + mParseBox->setChecked( mAddresseeConfig.automaticNameParsing() ); + + KAcceleratorManager::manage( this ); + + connect( mPrefixCombo, SIGNAL( textChanged( const QString& ) ), + this, SLOT( modified() ) ); + connect( mGivenNameEdit, SIGNAL( textChanged( const QString& ) ), + this, SLOT( modified() ) ); + connect( mAdditionalNameEdit, SIGNAL( textChanged( const QString& ) ), + this, SLOT( modified() ) ); + connect( mFamilyNameEdit, SIGNAL( textChanged( const QString& ) ), + this, SLOT( modified() ) ); + connect( mSuffixCombo, SIGNAL( textChanged( const QString& ) ), + this, SLOT( modified() ) ); + connect( mFormattedNameCombo, SIGNAL( activated( int ) ), + this, SLOT( modified() ) ); + connect( mFormattedNameCombo, SIGNAL( activated( int ) ), + this, SLOT( formattedNameTypeChanged() ) ); + connect( mFormattedNameEdit, SIGNAL( textChanged( const QString& ) ), + this, SLOT( modified() ) ); + connect( mFormattedNameEdit, SIGNAL( textChanged( const QString& ) ), + this, SLOT( formattedNameChanged( const QString& ) ) ); + + initTypeCombo(); + mFormattedNameCombo->setCurrentItem( type ); + mPrefixCombo->lineEdit()->setFocus(); + mChanged = false; +} + +NameEditDialog::~NameEditDialog() +{ +} + +QString NameEditDialog::familyName() const +{ + return mFamilyNameEdit->text(); +} + +QString NameEditDialog::givenName() const +{ + return mGivenNameEdit->text(); +} + +QString NameEditDialog::prefix() const +{ + return mPrefixCombo->currentText(); +} + +QString NameEditDialog::suffix() const +{ + return mSuffixCombo->currentText(); +} + +QString NameEditDialog::additionalName() const +{ + return mAdditionalNameEdit->text(); +} + +QString NameEditDialog::customFormattedName() const +{ + return mFormattedNameEdit->text(); +} + +int NameEditDialog::formattedNameType() const +{ + return mFormattedNameCombo->currentItem(); +} + +bool NameEditDialog::changed() const +{ + return mChanged; +} + +void NameEditDialog::formattedNameTypeChanged() +{ + QString name; + + if ( formattedNameType() == CustomName ) + name = mCustomFormattedName; + else { + KABC::Addressee addr; + addr.setPrefix( prefix() ); + addr.setFamilyName( familyName() ); + addr.setAdditionalName( additionalName() ); + addr.setGivenName( givenName() ); + addr.setSuffix( suffix() ); + addr.setOrganization( mAddressee.organization() ); + + name = formattedName( addr, formattedNameType() ); + } + + mFormattedNameEdit->setText( name ); +} + +QString NameEditDialog::formattedName( const KABC::Addressee &addr, int type ) +{ + QString name; + + switch ( type ) { + case SimpleName: + name = addr.givenName() + " " + addr.familyName(); + break; + case FullName: + name = addr.assembledName(); + break; + case ReverseNameWithComma: + name = addr.familyName() + ", " + addr.givenName(); + break; + case ReverseName: + name = addr.familyName() + " " + addr.givenName(); + break; + case Organization: + name = addr.organization(); + break; + default: + name = ""; + break; + } + + return name.simplifyWhiteSpace(); +} + +void NameEditDialog::parseBoxChanged( bool value ) +{ + mAddresseeConfig.setAutomaticNameParsing( value ); +} + +void NameEditDialog::typeChanged( int pos ) +{ + mFormattedNameEdit->setEnabled( pos == 0 ); +} + +void NameEditDialog::formattedNameChanged( const QString &name ) +{ + if ( formattedNameType() == CustomName ) + mCustomFormattedName = name; +} + +void NameEditDialog::modified() +{ + mChanged = true; +} + +void NameEditDialog::initTypeCombo() +{ + int pos = mFormattedNameCombo->currentItem(); + + mFormattedNameCombo->clear(); + mFormattedNameCombo->insertItem( i18n( "Custom" ) ); + mFormattedNameCombo->insertItem( i18n( "Simple Name" ) ); + mFormattedNameCombo->insertItem( i18n( "Full Name" ) ); + mFormattedNameCombo->insertItem( i18n( "Reverse Name with Comma" ) ); + mFormattedNameCombo->insertItem( i18n( "Reverse Name" ) ); + mFormattedNameCombo->insertItem( i18n( "Organization" ) ); + + mFormattedNameCombo->setCurrentItem( pos ); +} + +void NameEditDialog::slotHelp() +{ + kapp->invokeHelp( "managing-contacts-automatic-nameparsing" ); +} + +#include "nameeditdialog.moc" diff --git a/kaddressbook/nameeditdialog.h b/kaddressbook/nameeditdialog.h new file mode 100644 index 000000000..6581eccac --- /dev/null +++ b/kaddressbook/nameeditdialog.h @@ -0,0 +1,98 @@ +/* + This file is part of KAddressBook. + Copyright (c) 2002 Mike Pilone <mpilone@slac.com> + + 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 NAMEEDITDIALOG_H +#define NAMEEDITDIALOG_H + +#include <kdialogbase.h> +#include <kabc/addressee.h> + +#include "addresseeconfig.h" + +class QCheckBox; + +class KLineEdit; +class KComboBox; + +/** + Editor dialog for name details, like given name, family name etc. +*/ +class NameEditDialog : public KDialogBase +{ + Q_OBJECT + + public: + enum FormattedNameType + { + CustomName, // returned by @ref customFormattedName() + SimpleName, // form: givenName familyName + FullName, // form: prefix givenName additionalName familyName suffix + ReverseNameWithComma, // form: familyName, givenName + ReverseName, // form: familyName givenName + Organization // the organization name + }; + + NameEditDialog( const KABC::Addressee &addr, int type, + bool readOnly, QWidget *parent, const char *name = 0 ); + ~NameEditDialog(); + + QString familyName() const; + QString givenName() const; + QString prefix() const; + QString suffix() const; + QString additionalName() const; + QString customFormattedName() const; + int formattedNameType() const; + + bool changed() const; + + static QString formattedName( const KABC::Addressee &addr, int type ); + + protected slots: + void slotHelp(); + + private slots: + void parseBoxChanged( bool ); + void formattedNameTypeChanged(); + void formattedNameChanged( const QString& ); + void typeChanged( int ); + void initTypeCombo(); + void modified(); + + private: + KComboBox *mSuffixCombo; + KComboBox *mPrefixCombo; + KComboBox *mFormattedNameCombo; + KLineEdit *mFamilyNameEdit; + KLineEdit *mGivenNameEdit; + KLineEdit *mAdditionalNameEdit; + KLineEdit *mFormattedNameEdit; + QCheckBox *mParseBox; + + AddresseeConfig mAddresseeConfig; + KABC::Addressee mAddressee; + QString mCustomFormattedName; + bool mChanged; +}; + +#endif diff --git a/kaddressbook/phoneeditwidget.cpp b/kaddressbook/phoneeditwidget.cpp new file mode 100644 index 000000000..6b696dc93 --- /dev/null +++ b/kaddressbook/phoneeditwidget.cpp @@ -0,0 +1,344 @@ +/* + This file is part of KAddressBook. + Copyright (c) 2002 Mike Pilone <mpilone@slac.com> + + 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 <qbuttongroup.h> +#include <qcheckbox.h> +#include <qlabel.h> +#include <qlayout.h> +#include <qlistbox.h> +#include <qlistview.h> +#include <qpushbutton.h> +#include <qsignalmapper.h> +#include <qstring.h> +#include <qtooltip.h> + +#include <kapplication.h> +#include <kbuttonbox.h> +#include <kcombobox.h> +#include <kconfig.h> +#include <kdebug.h> +#include <kiconloader.h> +#include <klineedit.h> +#include <klistview.h> +#include <klocale.h> + +#include <kabc/phonenumber.h> + +#include "phoneeditwidget.h" + +PhoneTypeCombo::PhoneTypeCombo( QWidget *parent ) + : KComboBox( parent, "TypeCombo" ), + mType( KABC::PhoneNumber::Home ), + mLastSelected( 0 ), + mTypeList( KABC::PhoneNumber::typeList() ) +{ + mTypeList.append( -1 ); // Others... + + update(); + + connect( this, SIGNAL( activated( int ) ), + this, SLOT( selected( int ) ) ); + connect( this, SIGNAL( activated( int ) ), + this, SIGNAL( modified() ) ); +} + +PhoneTypeCombo::~PhoneTypeCombo() +{ +} + +void PhoneTypeCombo::setType( int type ) +{ + if ( !mTypeList.contains( type ) ) + mTypeList.insert( mTypeList.at( mTypeList.count() - 1 ), type ); + + mType = type; + update(); +} + +int PhoneTypeCombo::type() const +{ + return mType; +} + +void PhoneTypeCombo::update() +{ + bool blocked = signalsBlocked(); + blockSignals( true ); + + clear(); + QValueList<int>::ConstIterator it; + for ( it = mTypeList.begin(); it != mTypeList.end(); ++it ) { + if ( *it == -1 ) { // "Other..." entry + insertItem( i18n( "Other..." ) ); + } else { + KABC::PhoneNumber number; + number.setType( *it ); + insertItem( number.typeLabel() ); + } + } + + setCurrentItem( mLastSelected = mTypeList.findIndex( mType ) ); + + blockSignals( blocked ); +} + +void PhoneTypeCombo::selected( int pos ) +{ + if ( mTypeList[ pos ] == -1 ) + otherSelected(); + else { + mType = mTypeList[ pos ]; + mLastSelected = pos; + } +} + +void PhoneTypeCombo::otherSelected() +{ + PhoneTypeDialog dlg( mType, this ); + if ( dlg.exec() ) { + mType = dlg.type(); + if ( !mTypeList.contains( mType ) ) + mTypeList.insert( mTypeList.at( mTypeList.count() - 1 ), mType ); + } else { + setType( mTypeList[ mLastSelected ] ); + } + + update(); +} + +PhoneNumberWidget::PhoneNumberWidget( QWidget *parent ) + : QWidget( parent ) +{ + QHBoxLayout *layout = new QHBoxLayout( this, 6, 11 ); + + mTypeCombo = new PhoneTypeCombo( this ); + mNumberEdit = new KLineEdit( this ); + + layout->addWidget( mTypeCombo ); + layout->addWidget( mNumberEdit ); + + connect( mTypeCombo, SIGNAL( modified() ), SIGNAL( modified() ) ); + connect( mNumberEdit, SIGNAL( textChanged( const QString& ) ), SIGNAL( modified() ) ); +} + +void PhoneNumberWidget::setNumber( const KABC::PhoneNumber &number ) +{ + mNumber = number; + + mTypeCombo->setType( number.type() ); + mNumberEdit->setText( number.number() ); +} + +KABC::PhoneNumber PhoneNumberWidget::number() const +{ + KABC::PhoneNumber number( mNumber ); + + number.setType( mTypeCombo->type() ); + number.setNumber( mNumberEdit->text() ); + + return number; +} + +void PhoneNumberWidget::setReadOnly( bool readOnly ) +{ + mTypeCombo->setEnabled( !readOnly ); + mNumberEdit->setReadOnly( readOnly ); +} + + +PhoneEditWidget::PhoneEditWidget( QWidget *parent, const char *name ) + : QWidget( parent, name ), mReadOnly( false ) +{ + QGridLayout *layout = new QGridLayout( this, 2, 2 ); + layout->setSpacing( KDialog::spacingHint() ); + + mWidgetLayout = new QVBoxLayout( layout ); + layout->addMultiCellLayout( mWidgetLayout, 0, 0, 0, 1 ); + + mAddButton = new QPushButton( i18n( "Add" ), this ); + mAddButton->setMaximumSize( mAddButton->sizeHint() ); + layout->addWidget( mAddButton, 1, 0, Qt::AlignRight ); + + mRemoveButton = new QPushButton( i18n( "Remove" ), this ); + mRemoveButton->setMaximumSize( mRemoveButton->sizeHint() ); + layout->addWidget( mRemoveButton, 1, 1 ); + + mMapper = new QSignalMapper( this ); + connect( mMapper, SIGNAL( mapped( int ) ), SLOT( changed( int ) ) ); + + connect( mAddButton, SIGNAL( clicked() ), SLOT( add() ) ); + connect( mRemoveButton, SIGNAL( clicked() ), SLOT( remove() ) ); +} + +PhoneEditWidget::~PhoneEditWidget() +{ +} + +void PhoneEditWidget::setReadOnly( bool readOnly ) +{ + mReadOnly = readOnly; + mAddButton->setEnabled( !readOnly ); + mRemoveButton->setEnabled( !readOnly && mPhoneNumberList.count() > 3 ); + + QPtrListIterator<PhoneNumberWidget> it( mWidgets ); + while ( it.current() ) { + it.current()->setReadOnly( readOnly ); + ++it; + } +} + +void PhoneEditWidget::setPhoneNumbers( const KABC::PhoneNumber::List &list ) +{ + mPhoneNumberList = list; + + KABC::PhoneNumber::TypeList types; + types << KABC::PhoneNumber::Home; + types << KABC::PhoneNumber::Work; + types << KABC::PhoneNumber::Cell; + + // add an empty entry per default + if ( mPhoneNumberList.count() < 3 ) + for ( int i = mPhoneNumberList.count(); i < 3; ++i ) + mPhoneNumberList.append( KABC::PhoneNumber( "", types[ i ] ) ); + + recreateNumberWidgets(); +} + +KABC::PhoneNumber::List PhoneEditWidget::phoneNumbers() const +{ + KABC::PhoneNumber::List list; + + KABC::PhoneNumber::List::ConstIterator it; + for ( it = mPhoneNumberList.begin(); it != mPhoneNumberList.end(); ++it ) + if ( !(*it).number().isEmpty() ) + list.append( *it ); + + return list; +} + +void PhoneEditWidget::changed() +{ + if ( !mReadOnly ) + emit modified(); +} + +void PhoneEditWidget::add() +{ + mPhoneNumberList.append( KABC::PhoneNumber() ); + + recreateNumberWidgets(); +} + +void PhoneEditWidget::remove() +{ + mPhoneNumberList.remove( mPhoneNumberList.last() ); + changed(); + + recreateNumberWidgets(); +} + +void PhoneEditWidget::recreateNumberWidgets() +{ + for ( QWidget *w = mWidgets.first(); w; w = mWidgets.next() ) { + mWidgetLayout->remove( w ); + w->deleteLater(); + } + mWidgets.clear(); + + KABC::PhoneNumber::List::ConstIterator it; + int counter = 0; + for ( it = mPhoneNumberList.begin(); it != mPhoneNumberList.end(); ++it ) { + PhoneNumberWidget *wdg = new PhoneNumberWidget( this ); + wdg->setNumber( *it ); + + mMapper->setMapping( wdg, counter ); + connect( wdg, SIGNAL( modified() ), mMapper, SLOT( map() ) ); + + mWidgetLayout->addWidget( wdg ); + mWidgets.append( wdg ); + wdg->show(); + + ++counter; + } + setReadOnly(mReadOnly); +} + +void PhoneEditWidget::changed( int pos ) +{ + mPhoneNumberList[ pos ] = mWidgets.at( pos )->number(); + changed(); +} + +/////////////////////////////////////////// +// PhoneTypeDialog +PhoneTypeDialog::PhoneTypeDialog( int type, QWidget *parent ) + : KDialogBase( Plain, i18n( "Edit Phone Number" ), Ok | Cancel, Ok, + parent, "PhoneTypeDialog", true ), + mType( type ) +{ + QWidget *page = plainPage(); + + QVBoxLayout *layout = new QVBoxLayout( page, spacingHint() ); + + mPreferredBox = new QCheckBox( i18n( "This is the preferred phone number" ), page ); + layout->addWidget( mPreferredBox ); + + mGroup = new QButtonGroup( 2, Horizontal, i18n( "Types" ), page ); + layout->addWidget( mGroup ); + + // fill widgets + mTypeList = KABC::PhoneNumber::typeList(); + mTypeList.remove( KABC::PhoneNumber::Pref ); + + KABC::PhoneNumber::TypeList::ConstIterator it; + for ( it = mTypeList.begin(); it != mTypeList.end(); ++it ) + new QCheckBox( KABC::PhoneNumber::typeLabel( *it ), mGroup ); + + for ( int i = 0; i < mGroup->count(); ++i ) { + QCheckBox *box = (QCheckBox*)mGroup->find( i ); + box->setChecked( mType & mTypeList[ i ] ); + } + + mPreferredBox->setChecked( mType & KABC::PhoneNumber::Pref ); +} + +int PhoneTypeDialog::type() const +{ + int type = 0; + + for ( int i = 0; i < mGroup->count(); ++i ) { + QCheckBox *box = (QCheckBox*)mGroup->find( i ); + if ( box->isChecked() ) + type += mTypeList[ i ]; + } + + if ( mPreferredBox->isChecked() ) + type = type | KABC::PhoneNumber::Pref; + else + type = type & ~KABC::PhoneNumber::Pref; + + return type; +} + + +#include "phoneeditwidget.moc" diff --git a/kaddressbook/phoneeditwidget.h b/kaddressbook/phoneeditwidget.h new file mode 100644 index 000000000..e123f68a0 --- /dev/null +++ b/kaddressbook/phoneeditwidget.h @@ -0,0 +1,144 @@ +/* + This file is part of KAddressBook. + Copyright (c) 2002 Mike Pilone <mpilone@slac.com> + + 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 PHONEEDITWIDGET_H +#define PHONEEDITWIDGET_H + +#include <kcombobox.h> +#include <kdialogbase.h> + +#include "addresseeconfig.h" + +class QButtonGroup; +class QCheckBox; +class QSignalMapper; + +class KLineEdit; +class KComboBox; + +class PhoneTypeCombo : public KComboBox +{ + Q_OBJECT + + public: + PhoneTypeCombo( QWidget *parent ); + ~PhoneTypeCombo(); + + void setType( int type ); + int type() const; + + signals: + void modified(); + + protected slots: + void selected( int ); + void otherSelected(); + + private: + void update(); + + int mType; + int mLastSelected; + QValueList<int> mTypeList; +}; + +class PhoneNumberWidget : public QWidget +{ + Q_OBJECT + + public: + PhoneNumberWidget( QWidget *parent ); + + void setNumber( const KABC::PhoneNumber &number ); + KABC::PhoneNumber number() const; + + void setReadOnly( bool readOnly ); + + signals: + void modified(); + + private: + PhoneTypeCombo *mTypeCombo; + KLineEdit *mNumberEdit; + KABC::PhoneNumber mNumber; +}; + +/** + Widget for editing phone numbers. +*/ +class PhoneEditWidget : public QWidget +{ + Q_OBJECT + + public: + PhoneEditWidget( QWidget *parent, const char *name = 0 ); + ~PhoneEditWidget(); + + void setPhoneNumbers( const KABC::PhoneNumber::List &list ); + KABC::PhoneNumber::List phoneNumbers() const; + + void setReadOnly( bool readOnly ); + + signals: + void modified(); + + protected slots: + void add(); + void remove(); + void changed(); + void changed( int pos ); + + private: + void recreateNumberWidgets(); + + KABC::PhoneNumber::List mPhoneNumberList; + QPtrList<PhoneNumberWidget> mWidgets; + + QPushButton *mAddButton; + QPushButton *mRemoveButton; + QVBoxLayout *mWidgetLayout; + + bool mReadOnly; + QSignalMapper *mMapper; +}; + +/** + Dialog for editing phone number types. + */ +class PhoneTypeDialog : public KDialogBase +{ + Q_OBJECT + public: + PhoneTypeDialog( int type, QWidget *parent ); + + int type() const; + + private: + int mType; + KABC::PhoneNumber::TypeList mTypeList; + + QButtonGroup *mGroup; + QCheckBox *mPreferredBox; +}; + +#endif diff --git a/kaddressbook/pics/Makefile.am b/kaddressbook/pics/Makefile.am new file mode 100644 index 000000000..4d15288d4 --- /dev/null +++ b/kaddressbook/pics/Makefile.am @@ -0,0 +1,5 @@ +kaddressbookicondir = $(kde_datadir)/kaddressbook/icons +kaddressbookicon_ICON = AUTO + +kabpics_DATA = world.jpg +kabpicsdir = $(kde_datadir)/kaddressbook/pics diff --git a/kaddressbook/pics/README b/kaddressbook/pics/README new file mode 100644 index 000000000..ddf0e05f8 --- /dev/null +++ b/kaddressbook/pics/README @@ -0,0 +1,6 @@ +Some the icons in this directory have been taken from: + +Slick Icon Pack (now part of KDE) + Copyright Robert Cosgrove + +KDE Hicolor & Locolor Themes diff --git a/kaddressbook/pics/cr16-action-ldap_lookup.png b/kaddressbook/pics/cr16-action-ldap_lookup.png Binary files differnew file mode 100644 index 000000000..8e21ddd4d --- /dev/null +++ b/kaddressbook/pics/cr16-action-ldap_lookup.png diff --git a/kaddressbook/pics/cr16-action-smallcal.png b/kaddressbook/pics/cr16-action-smallcal.png Binary files differnew file mode 100644 index 000000000..0e4acba52 --- /dev/null +++ b/kaddressbook/pics/cr16-action-smallcal.png diff --git a/kaddressbook/pics/cr32-action-homepage.png b/kaddressbook/pics/cr32-action-homepage.png Binary files differnew file mode 100644 index 000000000..145a6f47a --- /dev/null +++ b/kaddressbook/pics/cr32-action-homepage.png diff --git a/kaddressbook/pics/lo16-action-contact.png b/kaddressbook/pics/lo16-action-contact.png Binary files differnew file mode 100644 index 000000000..da0a9b658 --- /dev/null +++ b/kaddressbook/pics/lo16-action-contact.png diff --git a/kaddressbook/pics/lo16-action-down.png b/kaddressbook/pics/lo16-action-down.png Binary files differnew file mode 100644 index 000000000..5b968317b --- /dev/null +++ b/kaddressbook/pics/lo16-action-down.png diff --git a/kaddressbook/pics/lo16-action-group.png b/kaddressbook/pics/lo16-action-group.png Binary files differnew file mode 100644 index 000000000..1de096928 --- /dev/null +++ b/kaddressbook/pics/lo16-action-group.png diff --git a/kaddressbook/pics/lo16-action-up.png b/kaddressbook/pics/lo16-action-up.png Binary files differnew file mode 100644 index 000000000..dfaea128f --- /dev/null +++ b/kaddressbook/pics/lo16-action-up.png diff --git a/kaddressbook/pics/lo22-action-page.png b/kaddressbook/pics/lo22-action-page.png Binary files differnew file mode 100644 index 000000000..5fe6455ae --- /dev/null +++ b/kaddressbook/pics/lo22-action-page.png diff --git a/kaddressbook/pics/world.jpg b/kaddressbook/pics/world.jpg Binary files differnew file mode 100644 index 000000000..1447b3d9c --- /dev/null +++ b/kaddressbook/pics/world.jpg diff --git a/kaddressbook/printing/Makefile.am b/kaddressbook/printing/Makefile.am new file mode 100644 index 000000000..86e7d2793 --- /dev/null +++ b/kaddressbook/printing/Makefile.am @@ -0,0 +1,32 @@ +INCLUDES = -I$(top_srcdir) -I$(top_builddir)/kaddressbook -I$(top_srcdir)/kaddressbook \ + -I$(top_srcdir)/kaddressbook/details -I$(top_srcdir)/kaddressbook/common \ + -I$(top_builddir)/kaddressbook/common $(all_includes) + +noinst_LTLIBRARIES = libprinter.la + +libprinter_la_SOURCES = \ + detailledstyle.cpp \ + ds_appearance.ui \ + kabentrypainter.cpp \ + mikesstyle.cpp \ + printingwizard.cpp \ + printprogress.cpp \ + printstyle.cpp \ + selectionpage.cpp \ + stylepage.cpp \ + printsortmode.cpp +libprinter_la_COMPILE_FIRST = $(top_builddir)/kaddressbook/common/kabprefs_base.h + +EXTRA_DIST = \ + detailledstyle.cpp detailledstyle.h kabentrypainter.h \ + mikesstyle.cpp mikesstyle.h \ + printingwizard.cpp printingwizard.h \ + printprogress.cpp printprogress.h \ + printstyle.cpp printstyle.h rbs_appearance.ui.h \ + selectionpage.cpp selectionpage.h \ + stylepage.cpp stylepage.h + +libprinter_la_METASOURCES = AUTO + +previewdir = $(kde_datadir)/kaddressbook/printing +preview_DATA = detailed-style.png mike-style.png diff --git a/kaddressbook/printing/README b/kaddressbook/printing/README new file mode 100644 index 000000000..0c8951e18 --- /dev/null +++ b/kaddressbook/printing/README @@ -0,0 +1,15 @@ +This subdircetory implements the printing wizard that handles the +different styles of printing provided by kaddressbook. To see how +printing is handled, see printingwizard.h. See kaddressbookprinting.h +in the kaddressbook main directory, too. + +Have a look at printstyle.h if you want to create your own print +style. + +Files starting with ds_ are part of the detailed print style +implementation. + +----- +Feel free to add you comments here. + +--Mirko Boehm. diff --git a/kaddressbook/printing/detailed-style.png b/kaddressbook/printing/detailed-style.png Binary files differnew file mode 100644 index 000000000..c93602d4e --- /dev/null +++ b/kaddressbook/printing/detailed-style.png diff --git a/kaddressbook/printing/detailledstyle.cpp b/kaddressbook/printing/detailledstyle.cpp new file mode 100644 index 000000000..78283a080 --- /dev/null +++ b/kaddressbook/printing/detailledstyle.cpp @@ -0,0 +1,291 @@ +/* + This file is part of KAddressBook. + Copyright (c) 1996-2002 Mirko Boehm <mirko@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 <kapplication.h> +#include <qcheckbox.h> +#include <kcolorbutton.h> +#include <kconfig.h> +#include <kdebug.h> +#include <kdialog.h> +#include <kfontcombo.h> +#include <kglobalsettings.h> +#include <qlayout.h> +#include <klocale.h> +#include <knuminput.h> +#include <qpaintdevicemetrics.h> +#include <qpainter.h> +#include <kprinter.h> +#include <kstandarddirs.h> + +#include "ds_appearance.h" +#include "printingwizard.h" +#include "printprogress.h" +#include "printstyle.h" + +#include "detailledstyle.h" + +using namespace KABPrinting; + +const char *ConfigSectionName = "DetailedPrintStyle"; +const char *UseKDEFonts = "UseKDEFonts"; +const char *HeaderFont = "HeaderFont"; +const char *HeaderFontSize = "HeaderFontSize"; +const char *HeadlinesFont = "HeadlineFont"; +const char *HeadlinesFontSize = "HeadlineFontSize"; +const char *BodyFont = "BodyFont"; +const char *BodyFontSize = "BodyFontSize"; +const char *DetailsFont = "DetailsFont"; +const char *DetailsFontSize = "DetailsFontSize"; +const char *FixedFont = "FixedFont"; +const char *FixedFontSize = "FixedFontSize"; +const char *ColoredContactHeaders = "UseColoredContactHeaders"; +const char *ContactHeaderForeColor = "ContactHeaderForeColor"; +const char *ContactHeaderBGColor = "ContactHeaderBGColor"; + + +DetailledPrintStyle::DetailledPrintStyle( PrintingWizard *parent, const char *name ) + : PrintStyle( parent, name ), + mPageAppearance( new AppearancePage( parent, "AppearancePage" ) ), + mPainter( 0 ), + mPrintProgress( 0 ) +{ + KConfig *config; + QFont font; + bool kdeFonts; + QFont standard = KGlobalSettings::generalFont(); + QFont fixed = KGlobalSettings::fixedFont(); + + setPreview( "detailed-style.png" ); + + addPage( mPageAppearance, i18n( "Detailed Print Style - Appearance" ) ); + + config = kapp->config(); + config->setGroup( ConfigSectionName ); + + kdeFonts = config->readBoolEntry( UseKDEFonts, true ); + mPageAppearance->cbStandardFonts->setChecked( kdeFonts ); + + font = config->readFontEntry( HeaderFont, &standard ); + mPageAppearance->kfcHeaderFont->setCurrentFont( font.family() ); + mPageAppearance->kisbHeaderFontSize->setValue( font.pointSize() ); + + font = config->readFontEntry( HeadlinesFont, &standard ); + mPageAppearance->kfcHeadlineFont->setCurrentFont( font.family() ); + mPageAppearance->kisbHeadlineFontSize->setValue( font.pointSize() ); + + font = config->readFontEntry( BodyFont, &standard ); + mPageAppearance->kfcBodyFont->setCurrentFont( font.family() ); + mPageAppearance->kisbBodyFontSize->setValue( font.pointSize() ); + + font = config->readFontEntry( DetailsFont, &standard ); + mPageAppearance->kfcDetailsFont->setCurrentFont( font.family() ); + mPageAppearance->kisbDetailsFontSize->setValue( font.pointSize() ); + + font = config->readFontEntry( FixedFont, &fixed ); + mPageAppearance->kfcFixedFont->setCurrentFont( font.family() ); + mPageAppearance->kisbFixedFontSize->setValue( font.pointSize() ); + + mPageAppearance->cbBackgroundColor->setChecked( + config->readBoolEntry( ColoredContactHeaders, true ) ); + mPageAppearance->kcbHeaderBGColor->setColor( + config->readColorEntry( ContactHeaderBGColor, &Qt::black ) ); + mPageAppearance->kcbHeaderTextColor->setColor( + config->readColorEntry( ContactHeaderForeColor, &Qt::white ) ); + + mPageAppearance->layout()->setMargin( KDialog::marginHint() ); + mPageAppearance->layout()->setSpacing( KDialog::spacingHint() ); +} + +DetailledPrintStyle::~DetailledPrintStyle() +{ + delete mPainter; + mPainter = 0; +} + +void DetailledPrintStyle::print( const KABC::Addressee::List &contacts, PrintProgress *progress ) +{ + mPrintProgress = progress; + + progress->addMessage( i18n( "Setting up fonts and colors" ) ); + progress->setProgress( 0 ); + + bool useKDEFonts; + QFont font; + QColor foreColor = Qt::black; + QColor headerColor = Qt::white; + bool useHeaderColor = true; + QColor backColor = Qt::black; + bool useBGColor; + + // save, always available defaults: + QFont header = QFont("Helvetica", 12, QFont::Normal); + QFont headlines = QFont("Helvetica", 12, QFont::Normal, true); + QFont body = QFont("Helvetica", 12, QFont::Normal); + QFont fixed = QFont("Courier", 12, QFont::Normal); + QFont comment = QFont("Helvetica", 10, QFont::Normal); + + // store the configuration settings: + KConfig *config = kapp->config(); + config->setGroup( ConfigSectionName ); + useKDEFonts = mPageAppearance->cbStandardFonts->isChecked(); + config->writeEntry( UseKDEFonts, useKDEFonts ); + + // read the font and color selections from the wizard pages: + useBGColor=mPageAppearance->cbBackgroundColor->isChecked(); + config->writeEntry( ColoredContactHeaders, useBGColor ); + + // use colored contact headers, otherwise use plain black and white): + if ( useBGColor ) { + headerColor = mPageAppearance->kcbHeaderTextColor->color(); + backColor = mPageAppearance->kcbHeaderBGColor->color(); + config->writeEntry( ContactHeaderForeColor, headerColor ); + config->writeEntry( ContactHeaderBGColor, backColor ); + } + + if ( mPageAppearance->cbStandardFonts->isChecked() ) { + QFont standard = KGlobalSettings::generalFont(); + header = standard; + headlines = standard; + body = standard; + fixed = KGlobalSettings::fixedFont(); + comment = standard; + } else { + header.setFamily( mPageAppearance->kfcHeaderFont->currentText() ); + header.setPointSize( mPageAppearance->kisbHeaderFontSize->value() ); + config->writeEntry( HeaderFont, header ); + + // headlines: + headlines.setFamily( mPageAppearance->kfcHeadlineFont->currentText() ); + headlines.setPointSize( mPageAppearance->kisbHeadlineFontSize->value() ); + config->writeEntry( HeadlinesFont, headlines ); + + // body: + body.setFamily( mPageAppearance->kfcBodyFont->currentText() ); + body.setPointSize( mPageAppearance->kisbBodyFontSize->value() ); + config->writeEntry( BodyFont, body ); + + // details: + comment.setFamily( mPageAppearance->kfcDetailsFont->currentText() ); + comment.setPointSize( mPageAppearance->kisbDetailsFontSize->value() ); + config->writeEntry( DetailsFont, comment ); + + // fixed: + fixed.setFamily( mPageAppearance->kfcFixedFont->currentText() ); + fixed.setPointSize( mPageAppearance->kisbFixedFontSize->value() ); + config->writeEntry( FixedFont, fixed ); + } + + mPainter = new KABEntryPainter; + mPainter->setForegroundColor( foreColor ); + mPainter->setHeaderColor( headerColor ); + mPainter->setBackgroundColor( backColor ); + mPainter->setUseHeaderColor( useHeaderColor ); + mPainter->setHeaderFont( header ); + mPainter->setHeadLineFont( headlines ); + mPainter->setBodyFont( body ); + mPainter->setFixedFont( fixed ); + mPainter->setCommentFont( comment ); + + KPrinter *printer = wizard()->printer(); + + QPainter painter; + progress->addMessage( i18n( "Setting up margins and spacing" ) ); + int marginTop = 0, + marginLeft = 64, // to allow stapling, need refinement with two-side prints + marginRight = 0, + marginBottom = 0; + + register int left, top, width, height; + + painter.begin( printer ); + printer->setFullPage( true ); // use whole page + + QPaintDeviceMetrics metrics( printer ); + + left = QMAX( printer->margins().width(), marginLeft ); + top = QMAX( printer->margins().height(), marginTop ); + width = metrics.width() - left - QMAX( printer->margins().width(), marginRight ); + height = metrics.height() - top - QMAX( printer->margins().height(), marginBottom ); + + painter.setViewport( left, top, width, height ); + progress->addMessage( i18n( "Printing" ) ); + + printEntries( contacts, printer, &painter, + QRect( 0, 0, metrics.width(), metrics.height() ) ); + + progress->addMessage( i18n( "Done" ) ); + painter.end(); + + config->sync(); +} + +bool DetailledPrintStyle::printEntries( const KABC::Addressee::List &contacts, + KPrinter *printer, + QPainter *painter, + const QRect &window) +{ + QRect brect; + int ypos = 0, count = 0; + + KABC::Addressee::List::ConstIterator it; + for ( it = contacts.begin(); it != contacts.end(); ++it ) { + if ( !(*it).isEmpty() ) { + // do a faked print to get the bounding rect: + if ( !mPainter->printAddressee( *it, window, painter, ypos, true, &brect) ) { + // it does not fit on the page beginning at ypos: + printer->newPage(); + + // WORK_TO_DO: this assumes the entry fits on the whole page + // (dunno how to fix this without being illogical) + ypos = 0; + } + + mPainter->printAddressee( *it, window, painter, ypos, false, &brect ); + ypos += brect.height(); + } + + mPrintProgress->setProgress( (count++ * 100) / contacts.count() ); + } + + mPrintProgress->setProgress( 100 ); + + return true; +} + +DetailledPrintStyleFactory::DetailledPrintStyleFactory( PrintingWizard *parent, + const char *name ) + : PrintStyleFactory( parent, name ) +{ +} + +PrintStyle *DetailledPrintStyleFactory::create() const +{ + return new DetailledPrintStyle( mParent, mName ); +} + +QString DetailledPrintStyleFactory::description() const +{ + return i18n( "Detailed Style" ); +} + +#include "detailledstyle.moc" diff --git a/kaddressbook/printing/detailledstyle.h b/kaddressbook/printing/detailledstyle.h new file mode 100644 index 000000000..91c6dfe19 --- /dev/null +++ b/kaddressbook/printing/detailledstyle.h @@ -0,0 +1,68 @@ +/* + This file is part of KAddressBook. + Copyright (c) 1996-2002 Mirko Boehm <mirko@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 DETAILLEDSTYLE_H +#define DETAILLEDSTYLE_H + +#include <kabc/addressee.h> + +#include "printstyle.h" +#include "kabentrypainter.h" + +class AppearancePage; + +namespace KABPrinting { + +class DetailledPrintStyle : public PrintStyle +{ + Q_OBJECT + + public: + DetailledPrintStyle( PrintingWizard *parent, const char *name = 0 ); + ~DetailledPrintStyle(); + + void print( const KABC::Addressee::List &contacts, PrintProgress* ); + + protected: + bool printEntries( const KABC::Addressee::List &contacts, KPrinter *printer, + QPainter *painter, const QRect &window ); + bool printEntry( const KABC::Addressee &contact, const QRect &window, + QPainter *painter, int top, bool fake, QRect *brect ); + private: + AppearancePage *mPageAppearance; + KABEntryPainter *mPainter; + PrintProgress *mPrintProgress; +}; + +class DetailledPrintStyleFactory : public PrintStyleFactory +{ + public: + DetailledPrintStyleFactory( PrintingWizard *parent, const char *name = 0 ); + + PrintStyle *create() const; + QString description() const; +}; + +} + +#endif diff --git a/kaddressbook/printing/ds_appearance.ui b/kaddressbook/printing/ds_appearance.ui new file mode 100644 index 000000000..2fe5ce208 --- /dev/null +++ b/kaddressbook/printing/ds_appearance.ui @@ -0,0 +1,479 @@ +<!DOCTYPE UI><UI version="3.0" stdsetdef="1"> +<class>AppearancePage</class> +<widget class="QWidget"> + <property name="name"> + <cstring>AppearancePage</cstring> + </property> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>597</width> + <height>437</height> + </rect> + </property> + <property name="caption"> + <string>Appearance Page</string> + </property> + <vbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <property name="margin"> + <number>11</number> + </property> + <property name="spacing"> + <number>6</number> + </property> + <widget class="QLabel"> + <property name="name"> + <cstring>labelHeader</cstring> + </property> + <property name="sizePolicy"> + <sizepolicy> + <hsizetype>1</hsizetype> + <vsizetype>1</vsizetype> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="paletteForegroundColor"> + <color> + <red>0</red> + <green>0</green> + <blue>90</blue> + </color> + </property> + <property name="paletteBackgroundColor"> + <color> + <red>255</red> + <green>170</green> + <blue>127</blue> + </color> + </property> + <property name="font"> + <font> + <bold>1</bold> + </font> + </property> + <property name="frameShape"> + <enum>Panel</enum> + </property> + <property name="frameShadow"> + <enum>Sunken</enum> + </property> + <property name="text"> + <string>Detailed Print Style - Appearance</string> + </property> + <property name="scaledContents"> + <bool>false</bool> + </property> + <property name="alignment"> + <set>AlignVCenter|AlignLeft</set> + </property> + </widget> + <widget class="QGroupBox"> + <property name="name"> + <cstring>gbFont</cstring> + </property> + <property name="sizePolicy"> + <sizepolicy> + <hsizetype>7</hsizetype> + <vsizetype>3</vsizetype> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="title"> + <string>Font Settings</string> + </property> + <vbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <property name="margin"> + <number>11</number> + </property> + <property name="spacing"> + <number>6</number> + </property> + <widget class="QCheckBox"> + <property name="name"> + <cstring>cbStandardFonts</cstring> + </property> + <property name="text"> + <string>Use standard KDE fonts</string> + </property> + <property name="checked"> + <bool>true</bool> + </property> + </widget> + <widget class="QFrame"> + <property name="name"> + <cstring>frameFonts</cstring> + </property> + <property name="enabled"> + <bool>false</bool> + </property> + <property name="frameShape"> + <enum>NoFrame</enum> + </property> + <property name="frameShadow"> + <enum>Plain</enum> + </property> + <grid> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <property name="margin"> + <number>11</number> + </property> + <property name="spacing"> + <number>6</number> + </property> + <widget class="QLabel" row="3" column="0"> + <property name="name"> + <cstring>labelDetailsFont</cstring> + </property> + <property name="text"> + <string>Details font:</string> + </property> + <property name="alignment"> + <set>AlignVCenter|AlignRight</set> + </property> + </widget> + <widget class="QLabel" row="3" column="2"> + <property name="name"> + <cstring>labelDetailsFontSize</cstring> + </property> + <property name="text"> + <string>Size:</string> + </property> + <property name="alignment"> + <set>AlignVCenter|AlignRight</set> + </property> + </widget> + <widget class="QLabel" row="2" column="0"> + <property name="name"> + <cstring>labelBodyFont</cstring> + </property> + <property name="text"> + <string>Body font:</string> + </property> + <property name="alignment"> + <set>AlignVCenter|AlignRight</set> + </property> + </widget> + <widget class="QLabel" row="4" column="2"> + <property name="name"> + <cstring>labelFixedFontSize</cstring> + </property> + <property name="text"> + <string>Size:</string> + </property> + <property name="alignment"> + <set>AlignVCenter|AlignRight</set> + </property> + </widget> + <widget class="QLabel" row="4" column="0"> + <property name="name"> + <cstring>labelFixed</cstring> + </property> + <property name="text"> + <string>Fixed font:</string> + </property> + <property name="alignment"> + <set>AlignVCenter|AlignRight</set> + </property> + </widget> + <widget class="KIntSpinBox" row="3" column="3"> + <property name="name"> + <cstring>kisbDetailsFontSize</cstring> + </property> + </widget> + <widget class="KIntSpinBox" row="4" column="3"> + <property name="name"> + <cstring>kisbFixedFontSize</cstring> + </property> + </widget> + <widget class="QLabel" row="2" column="2"> + <property name="name"> + <cstring>labelBodyFontSize</cstring> + </property> + <property name="text"> + <string>Size:</string> + </property> + <property name="alignment"> + <set>AlignVCenter|AlignRight</set> + </property> + </widget> + <widget class="KFontCombo" row="2" column="1"> + <property name="name"> + <cstring>kfcBodyFont</cstring> + </property> + <property name="sizePolicy"> + <sizepolicy> + <hsizetype>7</hsizetype> + <vsizetype>0</vsizetype> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + </widget> + <widget class="KFontCombo" row="3" column="1"> + <property name="name"> + <cstring>kfcDetailsFont</cstring> + </property> + <property name="sizePolicy"> + <sizepolicy> + <hsizetype>7</hsizetype> + <vsizetype>0</vsizetype> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + </widget> + <widget class="KFontCombo" row="4" column="1"> + <property name="name"> + <cstring>kfcFixedFont</cstring> + </property> + </widget> + <widget class="QLabel" row="0" column="0"> + <property name="name"> + <cstring>labelHeaderFont</cstring> + </property> + <property name="text"> + <string>Contact header font:</string> + </property> + <property name="alignment"> + <set>AlignVCenter|AlignRight</set> + </property> + </widget> + <widget class="KFontCombo" row="0" column="1"> + <property name="name"> + <cstring>kfcHeaderFont</cstring> + </property> + <property name="sizePolicy"> + <sizepolicy> + <hsizetype>7</hsizetype> + <vsizetype>0</vsizetype> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + </widget> + <widget class="KFontCombo" row="1" column="1"> + <property name="name"> + <cstring>kfcHeadlineFont</cstring> + </property> + </widget> + <widget class="QLabel" row="0" column="2"> + <property name="name"> + <cstring>labelHeaderFontSize</cstring> + </property> + <property name="text"> + <string>Size:</string> + </property> + <property name="alignment"> + <set>AlignVCenter|AlignRight</set> + </property> + </widget> + <widget class="QLabel" row="1" column="2"> + <property name="name"> + <cstring>labelHeaderFontSize_2</cstring> + </property> + <property name="text"> + <string>Size:</string> + </property> + <property name="alignment"> + <set>AlignVCenter|AlignRight</set> + </property> + </widget> + <widget class="KIntSpinBox" row="2" column="3"> + <property name="name"> + <cstring>kisbBodyFontSize</cstring> + </property> + </widget> + <widget class="QLabel" row="1" column="0"> + <property name="name"> + <cstring>labelHeadlines</cstring> + </property> + <property name="text"> + <string>Headlines:</string> + </property> + <property name="alignment"> + <set>AlignVCenter|AlignRight</set> + </property> + </widget> + <widget class="KIntSpinBox" row="0" column="3"> + <property name="name"> + <cstring>kisbHeaderFontSize</cstring> + </property> + </widget> + <widget class="KIntSpinBox" row="1" column="3"> + <property name="name"> + <cstring>kisbHeadlineFontSize</cstring> + </property> + </widget> + </grid> + </widget> + </vbox> + </widget> + <widget class="QGroupBox"> + <property name="name"> + <cstring>gbHeadline</cstring> + </property> + <property name="sizePolicy"> + <sizepolicy> + <hsizetype>3</hsizetype> + <vsizetype>5</vsizetype> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="title"> + <string>Contact Headers</string> + </property> + <vbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <property name="margin"> + <number>11</number> + </property> + <property name="spacing"> + <number>6</number> + </property> + <widget class="QCheckBox"> + <property name="name"> + <cstring>cbBackgroundColor</cstring> + </property> + <property name="text"> + <string>Use colored contact headers</string> + </property> + <property name="checked"> + <bool>true</bool> + </property> + </widget> + <widget class="QFrame"> + <property name="name"> + <cstring>frameBGColor</cstring> + </property> + <property name="frameShape"> + <enum>NoFrame</enum> + </property> + <property name="frameShadow"> + <enum>Plain</enum> + </property> + <grid> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <property name="margin"> + <number>11</number> + </property> + <property name="spacing"> + <number>6</number> + </property> + <widget class="KColorButton" row="0" column="1"> + <property name="name"> + <cstring>kcbHeaderBGColor</cstring> + </property> + <property name="enabled"> + <bool>true</bool> + </property> + <property name="text"> + <string></string> + </property> + <property name="color"> + <color> + <red>0</red> + <green>0</green> + <blue>0</blue> + </color> + </property> + </widget> + <widget class="QLabel" row="0" column="0"> + <property name="name"> + <cstring>tlBackgroundColor</cstring> + </property> + <property name="text"> + <string>Headline background color:</string> + </property> + <property name="alignment"> + <set>AlignVCenter|AlignRight</set> + </property> + </widget> + <widget class="QLabel" row="1" column="0"> + <property name="name"> + <cstring>tlHeaderColor</cstring> + </property> + <property name="text"> + <string>Headline text color:</string> + </property> + <property name="alignment"> + <set>AlignVCenter|AlignRight</set> + </property> + </widget> + <widget class="KColorButton" row="1" column="1"> + <property name="name"> + <cstring>kcbHeaderTextColor</cstring> + </property> + <property name="enabled"> + <bool>true</bool> + </property> + <property name="text"> + <string></string> + </property> + <property name="color"> + <color> + <red>255</red> + <green>255</green> + <blue>255</blue> + </color> + </property> + </widget> + <spacer row="0" column="2"> + <property name="name"> + <cstring>Spacer3</cstring> + </property> + <property name="orientation"> + <enum>Horizontal</enum> + </property> + <property name="sizeType"> + <enum>Expanding</enum> + </property> + </spacer> + </grid> + </widget> + </vbox> + </widget> + <spacer> + <property name="name"> + <cstring>Spacer4</cstring> + </property> + <property name="orientation"> + <enum>Vertical</enum> + </property> + <property name="sizeType"> + <enum>Expanding</enum> + </property> + </spacer> + </vbox> +</widget> +<connections> + <connection> + <sender>cbBackgroundColor</sender> + <signal>toggled(bool)</signal> + <receiver>frameBGColor</receiver> + <slot>setEnabled(bool)</slot> + </connection> + <connection> + <sender>cbStandardFonts</sender> + <signal>toggled(bool)</signal> + <receiver>frameFonts</receiver> + <slot>setDisabled(bool)</slot> + </connection> +</connections> +<layoutdefaults spacing="6" margin="11"/> +</UI> diff --git a/kaddressbook/printing/kabentrypainter.cpp b/kaddressbook/printing/kabentrypainter.cpp new file mode 100644 index 000000000..6ae163de8 --- /dev/null +++ b/kaddressbook/printing/kabentrypainter.cpp @@ -0,0 +1,521 @@ +/* + This file is part of KAddressBook. + Copyright (c) 1996-2002 Mirko Boehm <mirko@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 <qpaintdevicemetrics.h> +#include <qpainter.h> + +#include <kdebug.h> +#include <kglobal.h> +#include <klocale.h> +#include <knotifyclient.h> +#include <kprinter.h> +#include <kurl.h> + +#include "kabentrypainter.h" + +KABEntryPainter::KABEntryPainter() + : mShowAddresses( true ), mShowEmails( true ), mShowPhones( true ), + mShowURLs( true ) +{ +} + +KABEntryPainter::~KABEntryPainter() +{ + mEmailRects.clear(); + mPhoneRects.clear(); + mURLRects.clear(); + mTalkRects.clear(); +} + +void KABEntryPainter::setForegroundColor( const QColor &color ) +{ + mForegroundColor = color; +} + +void KABEntryPainter::setBackgroundColor( const QColor &color ) +{ + mBackgroundColor = color; +} + +void KABEntryPainter::setHeaderColor( const QColor &color ) +{ + mHeaderColor = color; +} + +void KABEntryPainter::setHeaderFont( const QFont &font ) +{ + mHeaderFont = font; +} + +void KABEntryPainter::setHeadLineFont( const QFont &font ) +{ + mHeadLineFont = font; +} + +void KABEntryPainter::setBodyFont( const QFont &font ) +{ + mBodyFont = font; +} + +void KABEntryPainter::setFixedFont( const QFont &font ) +{ + mFixedFont = font; +} + +void KABEntryPainter::setCommentFont( const QFont &font ) +{ + mCommentFont = font; +} + +void KABEntryPainter::setUseHeaderColor( bool value ) +{ + mUseHeaderColor = value; +} + +void KABEntryPainter::setShowAddresses( bool value ) +{ + mShowAddresses = value; +} + +void KABEntryPainter::setShowEmails( bool value ) +{ + mShowEmails = value; +} + +void KABEntryPainter::setShowPhones( bool value ) +{ + mShowPhones = value; +} + +void KABEntryPainter::setShowURLs( bool value ) +{ + mShowURLs = value; +} + +int KABEntryPainter::hitsEmail( const QPoint &p ) +{ + return hits( mEmailRects, p ); +} + +int KABEntryPainter::hitsURL( const QPoint &p ) +{ + return hits( mURLRects, p ); +} + +int KABEntryPainter::hitsPhone( const QPoint &p ) +{ + return hits( mPhoneRects, p ); +} + +int KABEntryPainter::hitsTalk( const QPoint &p ) +{ + return hits( mTalkRects, p ); +} + +int KABEntryPainter::hits( const QRectList& list, const QPoint &p ) +{ + QRectList::const_iterator pos; + int count = 0; + + for ( pos = list.begin(); pos != list.end(); ++pos ) { + if ( (*pos).contains( p ) ) + return count; + + ++count; + } + + return -1; +} + +bool KABEntryPainter::printAddressee( const KABC::Addressee &addr, + const QRect &window, QPainter *painter, + int top, bool fake, QRect *brect ) +{ + // TODO: custom fields, custom (?) for Entry + const int Width = window.width(); + const int Height = window.height(); + const int Ruler1 = Width/32; + const int Ruler2 = 2 * Ruler1; + const int Ruler3 = 3 * Ruler1; + QString text, line1, line2, line3, line4; + QRect rect; + + // settings derived from the options: + QFontMetrics fmHeader( mHeaderFont ); + QFontMetrics fmHeadLine( mHeadLineFont ); + QFontMetrics fmBody( mBodyFont ); + QFontMetrics fmFixed( mFixedFont ); + QFontMetrics fmComment( mCommentFont ); + + int y = top; + KABC::Address address; + + // this is used to prepare some fields for printing and decide about + // the layout later: + QValueList<QStringList> parts; + QValueList<QRectList*> contents; + + mEmailRects.clear(); + mPhoneRects.clear(); + mURLRects.clear(); + + // set window the painter works on: + painter->setWindow( window ); + + // first draw a black rectangle on top, containing the entries name, centered: + painter->setFont( mHeaderFont ); + painter->setBrush( QBrush( mBackgroundColor ) ); + painter->setPen( mBackgroundColor ); + text = addr.realName(); + + // replacement for: api->addressbook()->literalName(entry, text); + rect = painter->boundingRect( Ruler1, y, Width, Height, + Qt::AlignVCenter | Qt::AlignLeft, text ); + rect.setHeight( (int)( 1.25 * rect.height() ) ); + + if ( !fake && mUseHeaderColor ) + painter->drawRect( 0, y, Width, rect.height() ); + + painter->setPen( mUseHeaderColor ? mHeaderColor : mForegroundColor ); + if ( !fake ) { + // create a little (1/8) space on top of the letters: + float ypos = y + ( (float)rect.height() ) * 0.125; + painter->drawText( Ruler1, (int)ypos, Width, rect.height(), + Qt::AlignVCenter | Qt::AlignLeft, text ); + } + + // paint the birthday to the right: + QDateTime dt = addr.birthday(); + if ( dt.isValid() ) { + line1 = KGlobal::locale()->formatDate( dt.date(), true ); + if ( !fake ) { + // create a little (1/8) space on top of the letters: + float ypos = y + ( (float)rect.height() ) * 0.125; + painter->drawText( 0, (int)ypos, Width-Ruler1, rect.height(), + Qt::AlignVCenter | Qt::AlignRight, line1 ); + } + } + + y += rect.height(); + + // now draw the data according to the person: + painter->setFont( mBodyFont ); + y += fmBody.lineSpacing() / 2; + + painter->setPen( mForegroundColor ); + if ( !addr.prefix().isEmpty() ) { + line1 = addr.prefix().stripWhiteSpace(); + + if ( fake ) { + rect = painter->boundingRect( Ruler1, y, Width-Ruler1, Height, + Qt::AlignTop | Qt::AlignLeft, line1 ); + } else { + painter->drawText( Ruler1, y, Width-Ruler1, Height, Qt::AlignTop | Qt::AlignLeft, + line1, -1, &rect ); + } + + y += rect.height(); + } + + if ( !( addr.prefix().isEmpty() ) ) + y += fmBody.lineSpacing() / 2; + + // fill the parts stringlist, it contains "parts" (printable areas) + // that will be combined to fill the page as effectively as possible: + // Email addresses: + if ( !addr.emails().isEmpty() && mShowEmails ) { + contents.push_back( &mEmailRects ); + QStringList list; + + list.append( addr.emails().count() == 1 ? i18n( "Email address:" ) + : i18n( "Email addresses:" ) ); + list += addr.emails(); + parts.push_back( list ); + } + + // Telephones: + const KABC::PhoneNumber::List phoneNumbers( addr.phoneNumbers() ); + if ( !phoneNumbers.isEmpty() && mShowPhones ) { + contents.push_back( &mPhoneRects ); + QStringList list; + QString line; + + list.append( phoneNumbers.count() == 1 ? i18n( "Telephone:" ) + : i18n( "Telephones:" ) ); + + KABC::PhoneNumber::List::ConstIterator it; + for ( it = phoneNumbers.begin(); it != phoneNumbers.end(); ++it ) { + line = (*it).typeLabel(); + line += ": " + (*it).number(); + list.append( line.stripWhiteSpace() ); + } + + parts.push_back( list ); + } + + // Web pages/URLs: + if ( !addr.url().isEmpty() && addr.url().isValid() && mShowURLs ) { + contents.push_back( &mURLRects ); + QStringList list; + + list.append( i18n( "Web page:" ) ); + list += addr.url().prettyURL(); + parts.push_back( list ); + } + + /* + // Talk addresses: + if ( !addr.talk.isEmpty() ) { + contents.push_back( &mTalkRects ); + QStringList list; + + list.append( addr.talk.count() == 1 ? i18n( "Talk address:" ) + : i18n( "Talk addresses:" ) ); + list += addr.talk; + parts.push_back( list ); + } + */ + + QRect limits[] = { QRect( 0, y, Width / 2, Height ), + QRect( Width / 2, y, Width / 2, Height ), + QRect( 0, y, Width / 2, Height ), + QRect( Width / 2, y, Width / 2, Height ) }; + int heights[ 4 ]= { 0, 0, 0, 0 }; + + QValueList<QStringList>::iterator pos = parts.begin(); + QValueList<QRectList*>::iterator rpos = contents.begin(); + + for ( uint counter = 0; counter < parts.count(); ++counter ) { + const int Offset = counter > 1 ? QMAX( heights[ 0 ], heights[ 1 ] ) : 0; + QStringList list = *pos; + + painter->setFont( mHeadLineFont ); + if ( fake ) { + rect = painter->boundingRect( limits[ counter ].left(), + limits[ counter ].top() + heights[counter] + + Offset, limits[ counter ].width(), + limits[ counter ].height(), + Qt::AlignTop | Qt::AlignLeft, *list.at( 0 ) ); + } else { + painter->drawText( limits[ counter ].left(), limits[ counter ].top() + + heights[ counter ] + Offset, limits[ counter ].width(), + limits[ counter ].height(), Qt::AlignTop | Qt::AlignLeft, + *list.at( 0 ), -1, &rect ); + } + + heights[ counter ] += rect.height(); + + // paint the other elements at Ruler1: + painter->setFont( mFixedFont ); + for ( uint c2 = 1; c2 < list.count(); ++c2 ) { + // TODO: implement proper line breaking! + if ( fake ) { + rect = painter->boundingRect ( limits[ counter ].left() + Ruler1, + limits[ counter ].top() + heights[ counter ] + + Offset, limits[ counter ].width() - Ruler1, + limits[ counter ].height(), Qt::AlignTop | Qt::AlignLeft, + *list.at( c2 ) ); + } else { + painter->drawText( limits[ counter ].left() + Ruler1, limits[ counter ].top() + + heights[ counter ] + Offset, limits[ counter ].width() + - Ruler1, limits[ counter ].height(), Qt::AlignTop | Qt::AlignLeft, + *list.at( c2 ), -1, &rect ); + } + (*rpos)->push_back( rect ); + heights[ counter ] += rect.height(); + } + + ++pos; + ++rpos; + } + + y = y + QMAX( heights[ 0 ], heights[ 1 ] ) + QMAX( heights[ 2 ], heights[ 3 ] ); + // ^^^^^ done with emails, telephone, URLs and talk addresses + + // now print the addresses: + KABC::Address::List addresses = addr.addresses(); + if ( addresses.count() > 0 && mShowAddresses ) { + y += fmBody.lineSpacing() / 2; + painter->setFont( mHeadLineFont ); + if ( fake ) { + rect = painter->boundingRect( 0, y, Width, Height, Qt::AlignTop | Qt::AlignLeft, + addresses.count() == 1 ? i18n( "Address:" ) + : i18n( "Addresses:" ) ); + } else { + painter->drawText( 0, y, Width, Height, Qt::AlignTop | Qt::AlignLeft, + addresses.count() == 1 ? i18n( "Address:" ) + : i18n( "Addresses:" ), -1, &rect ); + } + + y += rect.height(); + y += fmBody.lineSpacing() / 4; + painter->setFont( mBodyFont ); + + KABC::Address::List::ConstIterator it; + for ( it = addresses.begin(); it != addresses.end(); ++it ) { + address = *it; + switch ( address.type() ) { + case KABC::Address::Dom: + line1 = i18n( "Domestic Address" ); + break; + case KABC::Address::Intl: + line1 = i18n( "International Address" ); + break; + case KABC::Address::Postal: + line1 = i18n( "Postal Address" ); + break; + case KABC::Address::Parcel: + line1 = i18n( "Parcel Address" ); + break; + case KABC::Address::Home: + line1 = i18n( "Home Address" ); + break; + case KABC::Address::Work: + line1 = i18n( "Work Address" ); + break; + case KABC::Address::Pref: + default: + line1 = i18n( "Preferred Address" ); + } + + line1 += QString::fromLatin1( ":" ); + text = QString::null; + + if ( !address.extended().isEmpty() ) + text = address.extended().stripWhiteSpace(); + + if ( !text.isEmpty() ) { + line1 = line1 + QString::fromLatin1( " (" ) + text + + QString::fromLatin1( ")" ); + } + + line1 = line1.stripWhiteSpace(); + line2 = address.street(); + if ( !address.postOfficeBox().isEmpty() ) + line2 += QString::fromLatin1( " - " ) + address.postOfficeBox(); + + // print address in american style, this will need localisation: + line3 = address.locality() + ( address.region().isEmpty() ? + QString::fromLatin1( "" ) : QString::fromLatin1( ", " ) + + address.region() ) + ( address.postalCode().isEmpty() + ? QString::fromLatin1( "" ) : QString::fromLatin1( " " ) + + address.postalCode() ); + line4 = address.country(); + + if ( fake ) { + rect = painter->boundingRect( Ruler1, y, Width - Ruler1, Height, + Qt::AlignTop | Qt::AlignLeft, line1 ); + } else { + painter->drawText( Ruler1, y, Width - Ruler1, Height, + Qt::AlignTop | Qt::AlignLeft, line1, -1, &rect ); + } + + y += rect.height(); + if ( !line2.isEmpty() ) { + if ( fake ) { + rect = painter->boundingRect( Ruler2, y, Width - Ruler2, Height, + Qt::AlignTop | Qt::AlignLeft, line2 ); + } else { + painter->drawText( Ruler2, y, Width - Ruler2, Height, + Qt::AlignTop | Qt::AlignLeft, line2, -1, &rect ); + } + y += rect.height(); + } + + if ( !line3.isEmpty() ) { + if ( fake ) { + rect = painter->boundingRect( Ruler2, y, Width - Ruler2, Height, + Qt::AlignTop | Qt::AlignLeft, line3 ); + } else { + painter->drawText( Ruler2, y, Width - Ruler2, Height, + Qt::AlignTop | Qt::AlignLeft, line3, -1, &rect ); + } + y += rect.height(); + } + + if ( !line4.isEmpty() ) { + if ( fake ) { + rect = painter->boundingRect( Ruler2, y, Width - Ruler2, Height, + Qt::AlignTop | Qt::AlignLeft, line4 ); + } else { + painter->drawText( Ruler2, y, Width - Ruler2, Height, + Qt::AlignTop | Qt::AlignLeft, line4, -1, &rect ); + } + y += rect.height(); + } + + y += fmBody.lineSpacing() / 4; + if ( !address.label().isEmpty() ) { + if ( fake ) { + rect = painter->boundingRect( Ruler2, y, Width - Ruler2, Height, + Qt::AlignTop | Qt::AlignLeft, + i18n( "(Deliver to:)" ) ); + } else { + painter->drawText( Ruler2, y, Width - Ruler2, Height, + Qt::AlignTop | Qt::AlignLeft, + i18n( "(Deliver to:)" ), -1, &rect ); + } + + y += rect.height(); + y += fmBody.lineSpacing() / 4; + if ( fake ) { + rect = painter->boundingRect( Ruler3, y, Width - Ruler3, Height, + Qt::AlignTop | Qt::AlignLeft, address.label() ); + } else { + painter->drawText( Ruler3, y, Width - Ruler3, Height, + Qt::AlignTop | Qt::AlignLeft, address.label(), -1, &rect ); + } + + y += rect.height(); + y += fmBody.lineSpacing() / 2; + } + } + } + + if ( !addr.note().isEmpty() ) { + painter->setFont( mCommentFont ); + y += fmBody.lineSpacing() / 2; + if ( fake ) { + rect = painter->boundingRect( 0, y, Width, Height, + Qt::AlignTop | Qt::AlignLeft | Qt::WordBreak, + addr.note() ); + } else { + painter->drawText( 0, y, Width, Height, + Qt::AlignTop | Qt::AlignLeft | Qt::WordBreak, + addr.note(), -1, &rect ); + } + + y += rect.height(); + } + + y += fmBody.lineSpacing() / 2; + + if ( brect != 0 ) + *brect = QRect( 0, top, Width, y - top ); + + if ( y < Height ) + return true; + else + return false; +} diff --git a/kaddressbook/printing/kabentrypainter.h b/kaddressbook/printing/kabentrypainter.h new file mode 100644 index 000000000..6c5b8dca9 --- /dev/null +++ b/kaddressbook/printing/kabentrypainter.h @@ -0,0 +1,133 @@ +/* + This file is part of KAddressBook. + Copyright (c) 1996-2002 Mirko Boehm <mirko@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 KABENTRYPAINTER_H +#define KABENTRYPAINTER_H + +#include <kabc/addressbook.h> + +#include <qcolor.h> +#include <qfont.h> +#include <qrect.h> +#include <qvaluelist.h> + +typedef QValueList<QRect> QRectList; + +class KABEntryPainter +{ + public: + KABEntryPainter(); + ~KABEntryPainter(); + + /** + Paint one entry using the given painter. May not only be used on + printer objects but on any suitable QPaintDevice. + The function does not paint a background, just the contents of the + addressee. + + @param addr The addressee that should be printed. + @param window The rectangle where the addressee should be printed to. + @param p A painter object to print it. + @param top The starting pixel in vertical direction (coordinate + system origin in the upper left corner), it is zero by + default, but may be larger than this to place another + addressee below an already printed one. + @param fake If this is true, the addressee is not really printed, + it only calculates the space needed to draw this entry + onto the given window. + + @returns false if some error happens, otherwise true. + */ + bool printAddressee( const KABC::Addressee &addr, const QRect &window, + QPainter *p, int top = 0, bool fake = false, + QRect *rect = 0 ); + + void setForegroundColor( const QColor &color = Qt::black ); + void setBackgroundColor( const QColor &color = Qt::black ); + void setHeaderColor( const QColor &color = Qt::white ); + + void setHeaderFont( const QFont &font = QFont( "Helvetica", 12, QFont::Normal, true ) ); + void setHeadLineFont( const QFont &font = QFont( "Helvetica", 12, QFont::Normal, true ) ); + void setBodyFont( const QFont &font = QFont( "Helvetica", 12, QFont::Normal, true ) ); + void setFixedFont( const QFont &font = QFont( "Courier", 12, QFont::Normal, true ) ); + void setCommentFont( const QFont &font = QFont( "Helvetica", 10, QFont::Normal, true ) ); + + void setUseHeaderColor( bool value = true ); + + void setShowAddresses( bool value = true ); + void setShowEmails( bool value = true ); + void setShowPhones( bool value = true ); + void setShowURLs( bool value = true ); + + /** + Returns the index of the rectangle if the point p is inside of + one of the email addresses. The index is the position of the + email address in the emails list. If it does not point at one of + the email addresses, -1 is returned. + */ + int hitsEmail( const QPoint &p ); + + /** + Returns the index of the rectangle if the point p is inside of + one of the telephone numbers. See hitsEmail + */ + int hitsPhone( const QPoint &p ); + + /** + Returns the index of the rectangle if the point p is inside of + one of the telephone numbers. See hitsEmail + */ + int hitsTalk( const QPoint &p ); + + /** + Returns the index of the rectangle if the point p is inside of + one of the telephone numbers. See hitsEmail + */ + int hitsURL( const QPoint &p ); + + private: + int hits( const QRectList& rects, const QPoint &p ); + + QColor mForegroundColor; + QColor mBackgroundColor; + QColor mHeaderColor; + + QFont mHeaderFont; + QFont mHeadLineFont; + QFont mBodyFont; + QFont mFixedFont; + QFont mCommentFont; + + bool mUseHeaderColor; + bool mShowAddresses; + bool mShowEmails; + bool mShowPhones; + bool mShowURLs; + + QRectList mEmailRects; + QRectList mPhoneRects; + QRectList mURLRects; + QRectList mTalkRects; +}; + +#endif diff --git a/kaddressbook/printing/mike-style.png b/kaddressbook/printing/mike-style.png Binary files differnew file mode 100644 index 000000000..7d3fd2e3b --- /dev/null +++ b/kaddressbook/printing/mike-style.png diff --git a/kaddressbook/printing/mikesstyle.cpp b/kaddressbook/printing/mikesstyle.cpp new file mode 100644 index 000000000..1eae4281c --- /dev/null +++ b/kaddressbook/printing/mikesstyle.cpp @@ -0,0 +1,262 @@ +/* + This file is part of KAddressBook. + Copyright (c) 1996-2002 Mirko Boehm <mirko@kde.org> + 2002 Mike Pilone <mpilone@slac.com> + + 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 <qpaintdevicemetrics.h> +#include <qpainter.h> + +#include <kabc/addressee.h> +#include <kapplication.h> +#include <kdebug.h> +#include <kglobal.h> +#include <klocale.h> +#include <kprinter.h> +#include <kprogress.h> + +#include "printingwizard.h" +#include "printprogress.h" +#include "printstyle.h" + +#include "mikesstyle.h" + +using namespace KABPrinting; + +const int mFieldSpacingHint = 2; + +MikesStyle::MikesStyle( PrintingWizard *parent, const char *name ) + : PrintStyle( parent, name ) +{ + setPreview( "mike-style.png" ); +} + +MikesStyle::~MikesStyle() +{ +} + +void MikesStyle::print( const KABC::Addressee::List &contacts, PrintProgress *progress ) +{ + QFont mFont; + QFont mBoldFont; + QPainter p; + + p.begin( wizard()->printer() ); + int yPos = 0, count = 0; + int spacingHint = 10; + + // Now do the actual printing + mFont = p.font(); + mBoldFont = p.font(); + mBoldFont.setBold( true ); + QFontMetrics fm( mFont ); + QPaintDeviceMetrics metrics( p.device() ); + + int height = 0; + KABC::Addressee::List::ConstIterator it; + + progress->addMessage( i18n( "Preparing" ) ); + progress->addMessage( i18n( "Printing" ) ); + + for ( it = contacts.begin(); it != contacts.end(); ++it ) { + progress->setProgress( (count++ * 100) / contacts.count() ); + kapp->processEvents(); + + // Get the total height so we know if it will fit on the current page + height = calcHeight( *it, mFont, mBoldFont ); + if ( (yPos + spacingHint + height) > (metrics.height() - fm.height() - 5) ) { + p.save(); + p.translate( 0, metrics.height() - fm.height() - 5 ); + paintTagLine( p, mFont ); + p.restore(); + + wizard()->printer()->newPage(); + yPos = 0; + } + + // Move the painter to the proper position and then paint the addressee + yPos += spacingHint; + p.save(); + p.translate( 0, yPos ); + doPaint( p, *it, height, mFont, mBoldFont ); + p.restore(); + + yPos += height; + } + + progress->addMessage( i18n( "Done" ) ); + + // print the tag line on the last page + p.save(); + p.translate( 0, metrics.height() - fm.height() - 5 ); + paintTagLine( p, mFont ); + p.restore(); + + // send to the printer + p.end(); +} + +QString MikesStyle::trimString( const QString &text, int width, QFontMetrics &fm ) +{ + if ( fm.width( text ) <= width ) + return text; + + QString dots = "..."; + int dotWidth = fm.width( dots ); + QString trimmed; + int charNum = 0; + + while ( fm.width( trimmed ) + dotWidth < width ) { + trimmed += text[ charNum ]; + charNum++; + } + + // Now trim the last char, since it put the width over the top + trimmed = trimmed.left( trimmed.length() - 1 ); + trimmed += dots; + + return trimmed; +} + +void MikesStyle::doPaint( QPainter &painter, const KABC::Addressee &addr, + int maxHeight, const QFont &font, const QFont &bFont ) +{ + QFontMetrics fm( font ); + QFontMetrics bfm( bFont ); + QPaintDeviceMetrics metrics( painter.device() ); + int margin = 10; + int width = metrics.width() - 10; + int xPos = 5; + int yPos = 0; + QBrush brush( Qt::lightGray ); + + painter.setPen( Qt::black ); + painter.drawRect( xPos, yPos, width, maxHeight ); + + // The header + painter.fillRect( xPos + 1, yPos + 1, width - 2, + bfm.height() + 2 * mFieldSpacingHint - 2, brush ); + painter.setFont( bFont ); + xPos += mFieldSpacingHint; + painter.drawText( xPos, yPos + bfm.height(), addr.formattedName() ); + + yPos += bfm.height() + 2 * mFieldSpacingHint; + xPos = margin; + + // now the fields, in two halves + painter.setFont( font ); + + KABC::Field::List fields = wizard()->addressBook()->fields(); + int numFields = fields.count(); + QString label; + QString value; + + for ( int i = 0; i < numFields / 2; i++ ) { + label = fields[ i ]->label(); + value = trimString( fields[ i ]->value( addr ), (width - 10) / 4, fm ); + + yPos += fm.height(); + painter.drawText( xPos, yPos, label + ":" ); + + xPos += (width - (2 * margin)) / 4; + painter.drawText( xPos, yPos, value ); + + yPos += mFieldSpacingHint; + xPos = margin; + } + + yPos = bfm.height() + 2 * mFieldSpacingHint; + xPos = margin + width / 2; + for ( int i = numFields / 2; i < numFields; i++ ) { + label = fields[ i ]->label(); + value = value = trimString( fields[ i ]->value( addr ), (width - 10) / 4, fm ); + + yPos += fm.height(); + painter.drawText( xPos, yPos, label + ":" ); + + xPos += (width - (2 * margin)) / 4; + painter.drawText( xPos, yPos, value ); + + yPos += mFieldSpacingHint; + xPos = margin + width / 2; + } +} + +void MikesStyle::paintTagLine( QPainter &p, const QFont &font ) +{ + QFontMetrics fm( font ); + + QString text = i18n( "Printed on %1 by KAddressBook (http://www.kde.org)" ) + .arg( KGlobal::locale()->formatDateTime( QDateTime::currentDateTime() ) ); + + p.setPen( Qt::black ); + p.drawText( 0, fm.height(), text ); +} + +int MikesStyle::calcHeight( const KABC::Addressee &addr, + const QFont &font, const QFont &bFont ) +{ + QFontMetrics fm( font ); + QFontMetrics bfm( bFont ); + + int height = 0; + + // get the fields + KABC::Field::List fieldList = wizard()->addressBook()->fields(); + int numFields = fieldList.count(); + int halfHeight = 0; + + // Determine which half of the fields is higher + for ( int i = 0; i < numFields / 2; i++ ) + halfHeight += fm.height() * (fieldList[ i ]->value( addr ).contains( '\n' ) + 1); + + height = halfHeight; + + // now the second half + halfHeight = 0; + for ( int i = numFields / 2; i < numFields; i++ ) + halfHeight += fm.height() * (fieldList[ i ]->value( addr ).contains( '\n' ) + 1); + + height = QMAX( height, halfHeight ); + + // Add the title and the spacing + height += bfm.height() + ((numFields / 2 + 3) * mFieldSpacingHint); + + return height; +} + + +MikesStyleFactory::MikesStyleFactory( PrintingWizard *parent, const char *name ) + : PrintStyleFactory( parent, name ) +{ +} + +PrintStyle *MikesStyleFactory::create() const +{ + return new MikesStyle( mParent, mName ); +} + +QString MikesStyleFactory::description() const +{ + return i18n( "Mike's Printing Style" ); +} + +#include "mikesstyle.moc" diff --git a/kaddressbook/printing/mikesstyle.h b/kaddressbook/printing/mikesstyle.h new file mode 100644 index 000000000..52278d390 --- /dev/null +++ b/kaddressbook/printing/mikesstyle.h @@ -0,0 +1,65 @@ +/* + This file is part of KAddressBook. + Copyright (c) 1996-2002 Mirko Boehm <mirko@kde.org> + 2002 Mike Pilone <mpilone@slac.com> + + 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 MIKESSTYLE_H +#define MIKESSTYLE_H + +#include <qfont.h> + +#include "printstyle.h" + +namespace KABPrinting { + +class PrintProgress; + +class MikesStyle : public PrintStyle +{ + Q_OBJECT + + public: + MikesStyle( PrintingWizard *parent, const char *name ); + ~MikesStyle(); + + void print( const KABC::Addressee::List&, PrintProgress* ); + + protected: + void doPaint( QPainter &painter, const KABC::Addressee &addr, int maxHeight, + const QFont &font, const QFont &bFont ); + int calcHeight( const KABC::Addressee &addr, const QFont &font, const QFont &bFont); + void paintTagLine( QPainter &p, const QFont &font); + QString trimString( const QString &text, int width, QFontMetrics &fm); +}; + +class MikesStyleFactory : public PrintStyleFactory +{ + public: + MikesStyleFactory( PrintingWizard *parent, const char *name = 0 ); + + PrintStyle *create() const; + QString description() const; +}; + +} + +#endif diff --git a/kaddressbook/printing/printingwizard.cpp b/kaddressbook/printing/printingwizard.cpp new file mode 100644 index 000000000..a961ac5fc --- /dev/null +++ b/kaddressbook/printing/printingwizard.cpp @@ -0,0 +1,220 @@ +/* + This file is part of KAddressBook. + Copyright (c) 1996-2002 Mirko Boehm <mirko@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 <qcombobox.h> +#include <qheader.h> +#include <qlabel.h> +#include <qlayout.h> +#include <qlistview.h> +#include <qpixmap.h> +#include <qpushbutton.h> +#include <qradiobutton.h> + +#include <kabc/addresseelist.h> +#include <kapplication.h> +#include <kdebug.h> +#include <kdialog.h> +#include <kdialogbase.h> +#include <klocale.h> +#include <kprinter.h> + +// including the styles +#include "detailledstyle.h" +#include "mikesstyle.h" + +#include "kabprefs.h" +#include "printprogress.h" +#include "printstyle.h" +#include "printsortmode.h" + +#include "printingwizard.h" + +using namespace KABPrinting; + +PrintingWizard::PrintingWizard( KPrinter *printer, KABC::AddressBook* ab, + const QStringList& selection, QWidget *parent, + const char* name ) + : KWizard( parent, name ), mPrinter( printer ), mAddressBook( ab ), + mSelection( selection ), mStyle( 0 ) +{ + mSelectionPage = new SelectionPage( this ); + mSelectionPage->setUseSelection( !selection.isEmpty() ); + insertPage( mSelectionPage, i18n("Choose Contacts to Print"), -1 ); + + mFilters = Filter::restore( kapp->config(), "Filter" ); + QStringList filters; + for ( Filter::List::ConstIterator it = mFilters.begin(); it != mFilters.end(); ++it ) + filters.append( (*it).name() ); + + mSelectionPage->setFilters( filters ); + + mSelectionPage->setCategories( KABPrefs::instance()->customCategories() ); + + setAppropriate( mSelectionPage, true ); + + + mStylePage = new StylePage( mAddressBook, this ); + connect( mStylePage, SIGNAL( styleChanged(int) ), SLOT( slotStyleSelected(int) ) ); + insertPage( mStylePage, i18n("Choose Printing Style"), -1 ); + + registerStyles(); + + if ( mStyleFactories.count() > 0 ) + slotStyleSelected( 0 ); +} + +PrintingWizard::~PrintingWizard() +{ +} + +void PrintingWizard::accept() +{ + print(); + close(); +} + +void PrintingWizard::registerStyles() +{ + mStyleFactories.append( new DetailledPrintStyleFactory( this ) ); + mStyleFactories.append( new MikesStyleFactory( this ) ); + + mStylePage->clearStyleNames(); + for ( uint i = 0; i < mStyleFactories.count(); ++i ) + mStylePage->addStyleName( mStyleFactories.at( i )->description() ); +} + +void PrintingWizard::slotStyleSelected( int index ) +{ + if ( index < 0 || (uint)index >= mStyleFactories.count() ) + return; + + setFinishEnabled( mStylePage, false ); + + if ( mStyle ) + mStyle->hidePages(); + + if ( mStyleList.at( index ) != 0 ) + mStyle = mStyleList.at( index ); + else { + PrintStyleFactory *factory = mStyleFactories.at( index ); + kdDebug(5720) << "PrintingWizardImpl::slotStyleSelected: " + << "creating print style " + << factory->description() << endl; + mStyle = factory->create(); + mStyleList.insert( index, mStyle ); + } + + mStyle->showPages(); + + mStylePage->setPreview( mStyle->preview() ); + + setFinishEnabled( page( pageCount() - 1 ), true ); + + if ( mStyle->preferredSortField() != 0 ) { + mStylePage->setSortField( mStyle->preferredSortField() ); + mStylePage->setSortAscending( mStyle->preferredSortType() ); + } +} + +KABC::AddressBook* PrintingWizard::addressBook() +{ + return mAddressBook; +} + +KPrinter* PrintingWizard::printer() +{ + return mPrinter; +} + +void PrintingWizard::print() +{ + // create and show print progress widget: + PrintProgress *progress = new PrintProgress( this ); + insertPage( progress, i18n( "Print Progress" ), -1 ); + showPage( progress ); + kapp->processEvents(); + + // prepare list of contacts to print: + + KABC::AddresseeList list; + if ( mStyle != 0 ) { + if ( mSelectionPage->useSelection() ) { + QStringList::ConstIterator it; + for ( it = mSelection.begin(); it != mSelection.end(); ++it ) { + KABC::Addressee addr = addressBook()->findByUid( *it ); + if ( !addr.isEmpty() ) + list.append( addr ); + } + } else if ( mSelectionPage->useFilters() ) { + // find contacts that can pass selected filter + Filter::List::ConstIterator filterIt; + for ( filterIt = mFilters.begin(); filterIt != mFilters.end(); ++filterIt ) + if ( (*filterIt).name() == mSelectionPage->filter() ) + break; + + KABC::AddressBook::ConstIterator it; + for ( it = addressBook()->begin(); it != addressBook()->end(); ++it ) { + if ( (*filterIt).filterAddressee( *it ) ) + list.append( *it ); + } + + } else if ( mSelectionPage->useCategories() ) { + QStringList categories = mSelectionPage->categories(); + KABC::AddressBook::ConstIterator it; + for ( it = addressBook()->begin(); it != addressBook()->end(); ++it ) { + const QStringList tmp( (*it).categories() ); + QStringList::ConstIterator tmpIt; + for ( tmpIt = tmp.begin(); tmpIt != tmp.end(); ++tmpIt ) + if ( categories.contains( *tmpIt ) ) { + list.append( *it ); + break; + } + } + } else { + // create a string list of all entries: + KABC::AddressBook::ConstIterator it; + for ( it = addressBook()->begin(); it != addressBook()->end(); ++it ) + list.append( *it ); + } + + list.setReverseSorting( !mStylePage->sortAscending() ); + +#if KDE_IS_VERSION(3,3,91) + PrintSortMode sortMode( mStylePage->sortField() ); + list.sortByMode( &sortMode ); +#else + list.sortByField( mStylePage->sortField() ); +#endif + } + + kdDebug(5720) << "PrintingWizardImpl::print: printing " + << list.count() << " contacts." << endl; + + // ... print: + setBackEnabled( progress, false ); + cancelButton()->setEnabled( false ); + mStyle->print( list, progress ); +} + +#include "printingwizard.moc" diff --git a/kaddressbook/printing/printingwizard.h b/kaddressbook/printing/printingwizard.h new file mode 100644 index 000000000..528aac71f --- /dev/null +++ b/kaddressbook/printing/printingwizard.h @@ -0,0 +1,115 @@ +/* + This file is part of KAddressBook. + Copyright (c) 1996-2002 Mirko Boehm <mirko@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 PRINTINGWIZARD_H +#define PRINTINGWIZARD_H + +#include <qptrlist.h> +#include <qstringlist.h> + +#include <kwizard.h> + +#include "common/filter.h" +#include "kabc/addressbook.h" +#include "printstyle.h" + +#include "selectionpage.h" +#include "stylepage.h" + + +class KPrinter; +class QVBoxLayout; + +namespace KABPrinting { + +/** + The PrintingWizard combines pages common for all print styles + and those provided by the respective style. +*/ +class PrintingWizard : public KWizard +{ + Q_OBJECT + + public: + /** + Construct a printing wizard. Give the addressbook instance to print. + */ + PrintingWizard( KPrinter *printer, + KABC::AddressBook* ab, + const QStringList& selection, + QWidget *parent = 0, const char *name = 0 ); + ~PrintingWizard(); + + /** + Modify this method to add a new PrintStyle. + */ + void registerStyles(); + + /** + Perform the actual printing. + */ + void print(); + + /** + Retrieve the document object. + */ + KABC::AddressBook *addressBook(); + + /** + Retrieve the printer to be used. + */ + KPrinter* printer(); + + protected slots: + /** + A print style has been selected. The argument is the index + in the cbStyle combo and in styles. + */ + void slotStyleSelected(int); + + protected: + QPtrList<PrintStyleFactory> mStyleFactories; + QPtrList<PrintStyle> mStyleList; + Filter::List mFilters; + KPrinter *mPrinter; + KABC::AddressBook *mAddressBook; + QStringList mSelection; + PrintStyle *mStyle; + + StylePage *mStylePage; + SelectionPage *mSelectionPage; + + /** + Overloaded accept slot. This is used to do the actual + printing without having the wizard disappearing + before. What happens is actually up to the print style, + since it does the printing. It could display a progress + window, for example (hint, hint). + */ + void accept(); +}; + +} + +#endif diff --git a/kaddressbook/printing/printprogress.cpp b/kaddressbook/printing/printprogress.cpp new file mode 100644 index 000000000..cb4a91d85 --- /dev/null +++ b/kaddressbook/printing/printprogress.cpp @@ -0,0 +1,83 @@ +/* + This file is part of KAddressBook. + Copyright (c) 1996-2002 Mirko Boehm <mirko@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 <qlayout.h> +#include <qprogressbar.h> +#include <qtextbrowser.h> + +#include <kapplication.h> +#include <kdebug.h> +#include <kdialog.h> +#include <klocale.h> + +#include "printprogress.h" + +using namespace KABPrinting; + +PrintProgress::PrintProgress( QWidget *parent, const char *name ) + : QWidget( parent, name ) +{ + setCaption( i18n( "Printing: Progress" ) ); + + QGridLayout *topLayout = new QGridLayout( this, 1, 1, KDialog::marginHint(), + KDialog::spacingHint() ); + + mLogBrowser = new QTextBrowser( this ); + topLayout->addWidget( mLogBrowser, 0, 0 ); + + mProgressBar = new QProgressBar( this ); + mProgressBar->setProgress( 0 ); + topLayout->addWidget( mProgressBar, 1, 0 ); + + resize( QSize( 370, 220 ).expandedTo( minimumSizeHint() ) ); +} + +PrintProgress::~PrintProgress() +{ +} + +void PrintProgress::addMessage( const QString &msg ) +{ + mMessages.append( msg ); + + QString head = QString( "<qt><b>" ) + i18n( "Progress" ) + + QString( ":</b><ul>" ); + + QString foot = QString( "</ul></qt>" ); + + QString body; + QStringList::ConstIterator it; + for ( it = mMessages.begin(); it != mMessages.end(); ++it ) + body.append( QString( "<li>" ) + (*it) + QString( "</li>" ) ); + + mLogBrowser->setText( head + body + foot ); + kapp->processEvents(); +} + +void PrintProgress::setProgress( int step ) +{ + mProgressBar->setProgress( step ); + kapp->processEvents(); +} + +#include "printprogress.moc" diff --git a/kaddressbook/printing/printprogress.h b/kaddressbook/printing/printprogress.h new file mode 100644 index 000000000..fd2a494f8 --- /dev/null +++ b/kaddressbook/printing/printprogress.h @@ -0,0 +1,67 @@ +/* + This file is part of KAddressBook. + Copyright (c) 1996-2002 Mirko Boehm <mirko@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 PRINTPROGRESS_H +#define PRINTPROGRESS_H + +#include <qwidget.h> + +class QProgressBar; +class QString; +class QTextBrowser; + +namespace KABPrinting { + +/** + This defines a simple widget to display print progress + information. It is provided to all print styles during a print + process. It displays messages and a a progress bar. + */ +class PrintProgress : public QWidget +{ + Q_OBJECT + + public: + PrintProgress( QWidget *parent, const char *name = 0 ); + ~PrintProgress(); + + /** + Add a message to the message log. Give the user something to admire :-) + */ + void addMessage( const QString& ); + + /** + Set the progress to a certain amount. Steps are from 0 to 100. + */ + void setProgress( int ); + + private: + QStringList mMessages; + + QTextBrowser* mLogBrowser; + QProgressBar* mProgressBar; +}; + +} + +#endif diff --git a/kaddressbook/printing/printsortmode.cpp b/kaddressbook/printing/printsortmode.cpp new file mode 100644 index 000000000..49ae25557 --- /dev/null +++ b/kaddressbook/printing/printsortmode.cpp @@ -0,0 +1,76 @@ +/* + This file is part of KAddressBook. + Copyright (c) 2005 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 <kabc/field.h> + +#include "printsortmode.h" + +#if KDE_IS_VERSION(3,3,91) + +PrintSortMode::PrintSortMode( KABC::Field *field, bool ascending ) + : mSortField( field ), mAscending( ascending ) +{ + const KABC::Field::List fields = KABC::Field::allFields(); + KABC::Field::List::ConstIterator it; + for ( it = fields.begin(); it != fields.end(); ++it ) { + if ( (*it)->label() == KABC::Addressee::givenNameLabel() ) + mGivenNameField = *it; + else if ( (*it)->label() == KABC::Addressee::familyNameLabel() ) + mFamilyNameField = *it; + else if ( (*it)->label() == KABC::Addressee::formattedNameLabel() ) + mFormattedNameField = *it; + } +} + +bool PrintSortMode::lesser( const KABC::Addressee &first, + const KABC::Addressee &second ) const +{ + if ( !mSortField ) + return false; + + int result = QString::localeAwareCompare( mSortField->value( first ), + mSortField->value( second ) ); + if ( result == 0 ) { + int givenNameResult = QString::localeAwareCompare( mGivenNameField->value( first ), + mGivenNameField->value( second ) ); + if ( givenNameResult == 0 ) { + int familyNameResult = QString::localeAwareCompare( mFamilyNameField->value( first ), + mFamilyNameField->value( second ) ); + if ( familyNameResult == 0 ) { + result = QString::localeAwareCompare( mFormattedNameField->value( first ), + mFormattedNameField->value( second ) ); + } else + result = familyNameResult; + } else + result = givenNameResult; + } + + bool lesser = result < 0; + + if ( !mAscending ) + lesser = !lesser; + + return lesser; +} + +#endif diff --git a/kaddressbook/printing/printsortmode.h b/kaddressbook/printing/printsortmode.h new file mode 100644 index 000000000..a7992cc6c --- /dev/null +++ b/kaddressbook/printing/printsortmode.h @@ -0,0 +1,50 @@ +/* + This file is part of KAddressBook. + Copyright (c) 2005 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 PRINTSORTMODE_H +#define PRINTSORTMODE_H + +#include <kdeversion.h> + +#if KDE_IS_VERSION(3,3,91) + +#include <kabc/sortmode.h> + +class PrintSortMode : public KABC::SortMode +{ + public: + PrintSortMode( KABC::Field *field, bool ascending = true ); + + virtual bool lesser( const KABC::Addressee&, const KABC::Addressee& ) const; + + private: + KABC::Field *mSortField; + KABC::Field *mGivenNameField; + KABC::Field *mFamilyNameField; + KABC::Field *mFormattedNameField; + bool mAscending; +}; + +#endif // KDE_IS_VERSION + +#endif // PRINTSORTMODE_H diff --git a/kaddressbook/printing/printstyle.cpp b/kaddressbook/printing/printstyle.cpp new file mode 100644 index 000000000..a3cf537d4 --- /dev/null +++ b/kaddressbook/printing/printstyle.cpp @@ -0,0 +1,130 @@ +/* + This file is part of KAddressBook. + Copyright (c) 1996-2002 Mirko Boehm <mirko@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 <kstandarddirs.h> +#include <kdebug.h> + +#include <qwidget.h> + +#include "printstyle.h" +#include "printingwizard.h" + +using namespace KABPrinting; + + +PrintStyle::PrintStyle( PrintingWizard* parent, const char* name ) + : QObject( parent, name ), mWizard( parent ), mSortField( 0 ) +{ +} + +PrintStyle::~PrintStyle() +{ +} + +const QPixmap& PrintStyle::preview() +{ + return mPreview; +} + +void PrintStyle::setPreview( const QPixmap& image ) +{ + mPreview = image; +} + +bool PrintStyle::setPreview( const QString& fileName ) +{ + QPixmap preview; + QString path = locate( "appdata", "printing/" + fileName ); + if ( path.isEmpty() ) { + kdDebug(5720) << "PrintStyle::setPreview: preview not locatable." << endl; + return false; + } else { + if ( preview.load( path ) ) { + setPreview( preview ); + return true; + } else { + kdDebug(5720) << "PrintStyle::setPreview: preview at '" << path << "' cannot be loaded." << endl; + return false; + } + } +} + +PrintingWizard *PrintStyle::wizard() +{ + return mWizard; +} + +void PrintStyle::addPage( QWidget *page, const QString &title ) +{ + if ( mPageList.find( page ) == -1 ) { // not yet in the list + mPageList.append( page ); + mPageTitles.append( title ); + } +} + +void PrintStyle::showPages() +{ + QWidget *wdg = 0; + int i = 0; + for ( wdg = mPageList.first(); wdg; wdg = mPageList.next(), ++i ) { + mWizard->addPage( wdg, mPageTitles[ i ] ); + if ( i == 0 ) + mWizard->setAppropriate( wdg, true ); + } + + if ( wdg ) + mWizard->setFinishEnabled( wdg, true ); +} + +void PrintStyle::hidePages() +{ + for ( QWidget *wdg = mPageList.first(); wdg; wdg = mPageList.next() ) + mWizard->removePage( wdg ); +} + +void PrintStyle::setPreferredSortOptions( KABC::Field *field, bool ascending ) +{ + mSortField = field; + mSortType = ascending; +} + +KABC::Field* PrintStyle::preferredSortField() +{ + return mSortField; +} + +bool PrintStyle::preferredSortType() +{ + return mSortType; +} + +PrintStyleFactory::PrintStyleFactory( PrintingWizard* parent, const char* name ) + : mParent( parent ), mName( name ) +{ +} + +PrintStyleFactory::~PrintStyleFactory() +{ +} + +#include "printstyle.moc" diff --git a/kaddressbook/printing/printstyle.h b/kaddressbook/printing/printstyle.h new file mode 100644 index 000000000..217b80b99 --- /dev/null +++ b/kaddressbook/printing/printstyle.h @@ -0,0 +1,171 @@ +/* + This file is part of KAddressBook. + Copyright (c) 1996-2002 Mirko Boehm <mirko@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 PRINTSTYLE_H +#define PRINTSTYLE_H + +#include <qwidget.h> +#include <qstringlist.h> +#include <qpixmap.h> + +#include <kabc/field.h> + +namespace KABPrinting { + +class PrintingWizard; +class PrintProgress; + +/** + The class PrintStyle implements the abstract interface to the + PrintingWizards style objects. + To implement a print style, derive from this class and read + the information in printingwizard.h to see how this two pieces + work together. Basically, the print style gets the contacts it + is supposed to print from the PrintingWizard is will not + change this set - neither its content nor its order. + To register your new style in the printing wizard, you need to + define a PrintStyleFactory that handles how your objects are + created and deleted. See the existing print styles for + examples. + A print style should have a preview image that gives the user + a basic impression on how it will look. Add this image to the + printing folder (right here :-), and edit Makefile.am to have + it installed along with kaddressbook. Load it using + setPreview(QString). + Your print style is supposed to add its options as pages to + the printing wizard. The method wizard() gives you a pointer + to the wizard object. + */ + +class PrintStyle : public QObject +{ + Q_OBJECT + + public: + PrintStyle( PrintingWizard* parent, const char* name = 0 ); + virtual ~PrintStyle(); + + /** + Reimplement this method to actually print. + */ + virtual void print( const KABC::Addressee::List &contacts, PrintProgress* ) = 0; + + /** + Reimplement this method to provide a preview of what will + be printed. It returns an invalid QPixmap by default, + resulting in a message that no preview is available. + */ + const QPixmap& preview(); + + /** + Hide all style specific pages in the wizard. + */ + void hidePages(); + + /** + Show all style specific pages in the wizard. + */ + void showPages(); + + /** + Returns the preferred sort criterion field. + */ + KABC::Field* preferredSortField(); + + /** + Returns the preferred sort type. + + true = ascending + false = descending + */ + bool preferredSortType(); + + protected: + /** + Load the preview image from the kaddressbook data + directory. The image should be located in the subdirectory + "printing". Give only the file name without any prefix as + the parameter. + */ + bool setPreview( const QString& fileName ); + + /** + Set the preview image. + */ + void setPreview( const QPixmap& image ); + + /** + Set preferred sort options for this printing style. + */ + void setPreferredSortOptions( KABC::Field *field, bool ascending = true ); + + /** + Return the wizard object. + */ + PrintingWizard *wizard(); + + /** + Add additional page to the wizard e.g. a configuration page for + the style. + */ + void addPage( QWidget *page, const QString &title ); + + private: + PrintingWizard *mWizard; + QPixmap mPreview; + QPtrList<QWidget> mPageList; + QStringList mPageTitles; + + KABC::Field *mSortField; + bool mSortType; +}; + + +/** + The factories are used to have all object of the respective + print style created in one place. + This will maybe be changed to a template because of its simple + nature :-) +*/ +class PrintStyleFactory +{ + public: + PrintStyleFactory( PrintingWizard* parent, const char* name = 0 ); + virtual ~PrintStyleFactory(); + + virtual PrintStyle *create() const = 0; + + /** + Overload this method to provide a one-liner description + for your print style. + */ + virtual QString description() const = 0; + + protected: + PrintingWizard* mParent; + const char* mName; +}; + +} + +#endif diff --git a/kaddressbook/printing/selectionpage.cpp b/kaddressbook/printing/selectionpage.cpp new file mode 100644 index 000000000..bf6d71e00 --- /dev/null +++ b/kaddressbook/printing/selectionpage.cpp @@ -0,0 +1,169 @@ +/* + This file is part of KAddressBook. + Copyright (c) 2002 Anders Lund <anders.lund@lund.tdcadsl.dk> + 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 <kdialog.h> +#include <klocale.h> + +#include <qbuttongroup.h> +#include <qcombobox.h> +#include <qheader.h> +#include <qlabel.h> +#include <qlayout.h> +#include <qlistview.h> +#include <qpushbutton.h> +#include <qradiobutton.h> +#include <qstringlist.h> +#include <qwhatsthis.h> + +#include "selectionpage.h" + +SelectionPage::SelectionPage( QWidget* parent, const char* name ) + : QWidget( parent, name ) +{ + setCaption( i18n( "Choose Which Contacts to Print" ) ); + + QVBoxLayout *topLayout = new QVBoxLayout( this, KDialog::marginHint(), + KDialog::spacingHint() ); + + QLabel *label = new QLabel( i18n( "Which contacts do you want to print?" ), this ); + topLayout->addWidget( label ); + + mButtonGroup = new QButtonGroup( this ); + mButtonGroup->setFrameShape( QButtonGroup::NoFrame ); + mButtonGroup->setColumnLayout( 0, Qt::Vertical ); + mButtonGroup->layout()->setSpacing( KDialog::spacingHint() ); + mButtonGroup->layout()->setMargin( KDialog::marginHint() ); + + QGridLayout *groupLayout = new QGridLayout( mButtonGroup->layout() ); + groupLayout->setAlignment( Qt::AlignTop ); + + mUseWholeBook = new QRadioButton( i18n( "&All contacts" ), mButtonGroup ); + mUseWholeBook->setChecked( true ); + QWhatsThis::add( mUseWholeBook, i18n( "Print the entire address book" ) ); + groupLayout->addWidget( mUseWholeBook, 0, 0 ); + + mUseSelection = new QRadioButton( i18n( "&Selected contacts" ), mButtonGroup ); + QWhatsThis::add( mUseSelection, i18n( "Only print contacts selected in KAddressBook.\n" + "This option is disabled if no contacts are selected." ) ); + groupLayout->addWidget( mUseSelection, 1, 0 ); + + mUseFilters = new QRadioButton( i18n( "Contacts matching &filter" ), mButtonGroup ); + QWhatsThis::add( mUseFilters, i18n( "Only print contacts matching the selected filter.\n" + "This option is disabled if you have not defined any filters." ) ); + groupLayout->addWidget( mUseFilters, 2, 0 ); + + mUseCategories = new QRadioButton( i18n( "Category &members" ), mButtonGroup ); + QWhatsThis::add( mUseCategories, i18n( "Only print contacts who are members of a category that is checked on the list to the left.\n" + "This option is disabled if you have no categories." ) ); + groupLayout->addWidget( mUseCategories, 3, 0, Qt::AlignTop ); + + mFiltersCombo = new QComboBox( false, mButtonGroup ); + QWhatsThis::add( mFiltersCombo, i18n( "Select a filter to decide which contacts to print." ) ); + groupLayout->addWidget( mFiltersCombo, 2, 1 ); + + mCategoriesView = new QListView( mButtonGroup ); + mCategoriesView->addColumn( "" ); + mCategoriesView->header()->hide(); + QWhatsThis::add( mCategoriesView, i18n( "Check the categories whose members you want to print." ) ); + groupLayout->addWidget( mCategoriesView, 3, 1 ); + + topLayout->addWidget( mButtonGroup ); + + connect( mFiltersCombo, SIGNAL( activated(int) ), SLOT( filterChanged(int) ) ); + connect( mCategoriesView, SIGNAL( clicked(QListViewItem*) ), SLOT( categoryClicked(QListViewItem*) ) ); +} + +SelectionPage::~SelectionPage() +{ +} + +void SelectionPage::setFilters( const QStringList& filters ) +{ + mFiltersCombo->clear(); + mFiltersCombo->insertStringList( filters ); + + mUseFilters->setEnabled( filters.count() > 0 ); +} + +QString SelectionPage::filter() const +{ + return mFiltersCombo->currentText(); +} + +bool SelectionPage::useFilters() const +{ + return mUseFilters->isChecked(); +} + +void SelectionPage::setCategories( const QStringList& list ) +{ + QStringList::ConstIterator it; + for ( it = list.begin(); it != list.end(); ++it ) + new QCheckListItem( mCategoriesView, *it, QCheckListItem::CheckBox ); + + mUseCategories->setEnabled( list.count() > 0 ); +} + +QStringList SelectionPage::categories() const +{ + QStringList list; + + QListViewItemIterator it( mCategoriesView ); + for ( ; it.current(); ++it ) { + QCheckListItem *qcli = static_cast<QCheckListItem*>(it.current()); + if ( qcli->isOn() ) + list.append( it.current()->text( 0 ) ); + } + + return list; +} + +bool SelectionPage::useCategories() +{ + return mUseCategories->isChecked(); +} + +void SelectionPage::setUseSelection( bool value ) +{ + mUseSelection->setEnabled( value ); +} + +bool SelectionPage::useSelection() const +{ + return mUseSelection->isChecked(); +} + +void SelectionPage::filterChanged( int ) +{ + mUseFilters->setChecked( true ); +} + +void SelectionPage::categoryClicked( QListViewItem *i ) +{ + QCheckListItem *qcli = static_cast<QCheckListItem*>( i ); + if ( i && qcli->isOn() ) + mUseCategories->setChecked( true ); +} + +#include "selectionpage.moc" diff --git a/kaddressbook/printing/selectionpage.h b/kaddressbook/printing/selectionpage.h new file mode 100644 index 000000000..b4dab1f6c --- /dev/null +++ b/kaddressbook/printing/selectionpage.h @@ -0,0 +1,68 @@ +/* + This file is part of KAddressBook. + Copyright (c) 2002 Anders Lund <anders.lund@lund.tdcadsl.dk> + 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 SELECTIONPAGE_H +#define SELECTIONPAGE_H + +#include <qwidget.h> + +class QButtonGroup; +class QComboBox; +class QListView; +class QListViewItem; +class QRadioButton; + +class SelectionPage : public QWidget +{ + Q_OBJECT + + public: + SelectionPage( QWidget* parent = 0, const char* name = 0 ); + ~SelectionPage(); + + void setFilters( const QStringList& ); + QString filter() const; + bool useFilters() const; + + void setCategories( const QStringList& ); + QStringList categories() const; + bool useCategories(); + + void setUseSelection( bool value ); + bool useSelection() const; + + private slots: + void filterChanged( int ); + void categoryClicked( QListViewItem * i ); + + private: + QButtonGroup* mButtonGroup; + QRadioButton* mUseCategories; + QRadioButton* mUseFilters; + QRadioButton* mUseWholeBook; + QRadioButton* mUseSelection; + QComboBox* mFiltersCombo; + QListView* mCategoriesView; +}; + +#endif // SELECTIONPAGE_H diff --git a/kaddressbook/printing/stylepage.cpp b/kaddressbook/printing/stylepage.cpp new file mode 100644 index 000000000..9e1be7bd1 --- /dev/null +++ b/kaddressbook/printing/stylepage.cpp @@ -0,0 +1,162 @@ +/* + This file is part of KAddressBook. + Copyright (c) 2002 Anders Lund <anders.lund@lund.tdcadsl.dk> + 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 <qbuttongroup.h> +#include <qlabel.h> +#include <qlayout.h> +#include <qpixmap.h> +#include <qradiobutton.h> + +#include <kcombobox.h> +#include <kdialog.h> +#include <klocale.h> + +#include "stylepage.h" + +StylePage::StylePage( KABC::AddressBook *ab, QWidget* parent, const char* name ) + : QWidget( parent, name ), mAddressBook( ab ) +{ + initGUI(); + + initFieldCombo(); + + mSortTypeCombo->insertItem( i18n( "Ascending" ) ); + mSortTypeCombo->insertItem( i18n( "Descending" ) ); + + connect( mStyleCombo, SIGNAL( activated( int ) ), SIGNAL( styleChanged( int ) ) ); +} + +StylePage::~StylePage() +{ +} + +void StylePage::setPreview( const QPixmap &pixmap ) +{ + if ( pixmap.isNull() ) + mPreview->setText( i18n( "(No preview available.)" ) ); + else + mPreview->setPixmap( pixmap ); +} + +void StylePage::addStyleName( const QString &name ) +{ + mStyleCombo->insertItem( name ); +} + +void StylePage::clearStyleNames() +{ + mStyleCombo->clear(); +} + +void StylePage::setSortField( KABC::Field *field ) +{ + mFieldCombo->setCurrentText( field->label() ); +} + +void StylePage::setSortAscending( bool value ) +{ + if ( value ) + mSortTypeCombo->setCurrentItem( 0 ); + else + mSortTypeCombo->setCurrentItem( 1 ); +} + +KABC::Field* StylePage::sortField() +{ + if ( mFieldCombo->currentItem() == -1 ) + return mFields[ 0 ]; + + return mFields[ mFieldCombo->currentItem() ]; +} + +bool StylePage::sortAscending() +{ + return ( mSortTypeCombo->currentItem() == 0 ); +} + +void StylePage::initFieldCombo() +{ + if ( !mAddressBook ) + return; + + mFieldCombo->clear(); + + mFields = mAddressBook->fields( KABC::Field::All ); + KABC::Field::List::ConstIterator it; + for ( it = mFields.begin(); it != mFields.end(); ++it ) + mFieldCombo->insertItem( (*it)->label() ); +} + +void StylePage::initGUI() +{ + setCaption( i18n( "Choose Printing Style" ) ); + + QGridLayout *topLayout = new QGridLayout( this, 2, 2, KDialog::marginHint(), + KDialog::spacingHint() ); + + QLabel *label = new QLabel( i18n( "What should the print look like?\n" + "KAddressBook has several printing styles, designed for different purposes.\n" + "Choose the style that suits your needs below." ), this ); + topLayout->addMultiCellWidget( label, 0, 0, 0, 1 ); + + QButtonGroup *group = new QButtonGroup( i18n( "Sorting" ), this ); + group->setColumnLayout( 0, Qt::Vertical ); + QGridLayout *sortLayout = new QGridLayout( group->layout(), 2, 2, + KDialog::spacingHint() ); + sortLayout->setAlignment( Qt::AlignTop ); + + label = new QLabel( i18n( "Criterion:" ), group ); + sortLayout->addWidget( label, 0, 0 ); + + mFieldCombo = new KComboBox( false, group ); + sortLayout->addWidget( mFieldCombo, 0, 1 ); + + label = new QLabel( i18n( "Order:" ), group ); + sortLayout->addWidget( label, 1, 0 ); + + mSortTypeCombo = new KComboBox( false, group ); + sortLayout->addWidget( mSortTypeCombo, 1, 1 ); + + topLayout->addWidget( group, 1, 0 ); + + group = new QButtonGroup( i18n( "Print Style" ), this ); + group->setColumnLayout( 0, Qt::Vertical ); + QVBoxLayout *styleLayout = new QVBoxLayout( group->layout(), + KDialog::spacingHint() ); + + mStyleCombo = new KComboBox( false, group ); + styleLayout->addWidget( mStyleCombo ); + + mPreview = new QLabel( group ); + QFont font( mPreview->font() ); + font.setPointSize( 20 ); + mPreview->setFont( font ); + mPreview->setScaledContents( true ); + mPreview->setAlignment( int( QLabel::WordBreak | QLabel::AlignCenter ) ); + styleLayout->addWidget( mPreview ); + + topLayout->addWidget( group, 1, 1 ); +} + +#include "stylepage.moc" diff --git a/kaddressbook/printing/stylepage.h b/kaddressbook/printing/stylepage.h new file mode 100644 index 000000000..d84394979 --- /dev/null +++ b/kaddressbook/printing/stylepage.h @@ -0,0 +1,102 @@ +/* + This file is part of KAddressBook. + Copyright (c) 2002 Anders Lund <anders.lund@lund.tdcadsl.dk> + 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 STYLEPAGE_H +#define STYLEPAGE_H + +#include <qwidget.h> + +#include <kabc/addressbook.h> +#include <kabc/field.h> + +class QLabel; +class QPixmap; +class QRadioButton; +class KComboBox; + +class StylePage : public QWidget +{ + Q_OBJECT + + public: + StylePage( KABC::AddressBook *ab, QWidget* parent = 0, const char* name = 0 ); + ~StylePage(); + + /** + * Set a preview image. If @ref pixmap is 'null' a text will + * be displayed instead. + */ + void setPreview( const QPixmap &pixmap ); + + /** + * Add a style name. + */ + void addStyleName( const QString &name ); + + /** + * Clear the style name list. + */ + void clearStyleNames(); + + /** + * Set the sort criterion field. + */ + void setSortField( KABC::Field *field ); + + /** + * Returns the sort criterion field. + */ + KABC::Field* sortField(); + + /** + * Set the sort type. + */ + void setSortAscending( bool value = true ); + + /** + * Returns whether the sort type is ascending. + */ + bool sortAscending(); + + signals: + /** + * This signal is emmited when the user selects a new style in the + * style combo box. + */ + void styleChanged( int index ); + + private: + void initGUI(); + void initFieldCombo(); + + KComboBox *mFieldCombo; + KComboBox *mSortTypeCombo; + KComboBox *mStyleCombo; + QLabel *mPreview; + + KABC::AddressBook *mAddressBook; + KABC::Field::List mFields; +}; + +#endif // STYLEPAGE_H diff --git a/kaddressbook/searchmanager.cpp b/kaddressbook/searchmanager.cpp new file mode 100644 index 000000000..1919dfea8 --- /dev/null +++ b/kaddressbook/searchmanager.cpp @@ -0,0 +1,198 @@ +/* + This file is part of KAddressBook. + Copyright (c) 2004 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 <kabc/addresseelist.h> +#include <kdeversion.h> + +#include "searchmanager.h" + +using namespace KAB; + +SearchManager::SearchManager( KABC::AddressBook *ab, + QObject *parent, const char *name ) + : QObject( parent, name ), mAddressBook( ab ) +{ +} + +void SearchManager::search( const QString &pattern, const KABC::Field::List &fields, Type type ) +{ + mPattern = pattern; + mFields = fields; + mType = type; + + KABC::Addressee::List allContacts; + mContacts.clear(); + +#if KDE_VERSION >= 319 + KABC::AddresseeList list( mAddressBook->allAddressees() ); + if ( !fields.isEmpty() ) + list.sortByField( fields.first() ); + + allContacts = list; +#else + KABC::AddressBook::ConstIterator abIt( mAddressBook->begin() ); + const KABC::AddressBook::ConstIterator abEndIt( mAddressBook->end() ); + for ( ; abIt != abEndIt; ++abIt ) + allContacts.append( *abIt ); +#endif + +#ifdef KDEPIM_NEW_DISTRLISTS + // Extract distribution lists from allContacts + mDistributionLists.clear(); + KABC::Addressee::List::Iterator rmIt( allContacts.begin() ); + const KABC::Addressee::List::Iterator rmEndIt( allContacts.end() ); + while ( rmIt != rmEndIt ) { + if ( KPIM::DistributionList::isDistributionList( *rmIt ) ) { + mDistributionLists.append( static_cast<KPIM::DistributionList>( *rmIt ) ); + rmIt = allContacts.remove( rmIt ); + } else + ++rmIt; + } + + typedef KPIM::DistributionList::Entry Entry; + if ( !mSelectedDistributionList.isNull() ) { + const KPIM::DistributionList dl = KPIM::DistributionList::findByName( mAddressBook, mSelectedDistributionList ); + if ( !dl.isEmpty() ) { + allContacts.clear(); + const Entry::List entries = dl.entries( mAddressBook ); + const Entry::List::ConstIterator end = entries.end(); + for ( Entry::List::ConstIterator it = entries.begin(); it != end; ++it ) { + allContacts.append( (*it).addressee ); + } + } + } + +#endif + + if ( mPattern.isEmpty() ) { // no pattern, return all + mContacts = allContacts; + + emit contactsUpdated(); + + return; + } + + const KABC::Field::List fieldList = !mFields.isEmpty() ? mFields : KABC::Field::allFields(); + + KABC::Addressee::List::ConstIterator it( allContacts.begin() ); + const KABC::Addressee::List::ConstIterator endIt( allContacts.end() ); + for ( ; it != endIt; ++it ) { +#ifdef KDEPIM_NEW_DISTRLISTS + if ( KPIM::DistributionList::isDistributionList( *it ) ) + continue; +#endif + + bool found = false; + // search over all fields + KABC::Field::List::ConstIterator fieldIt( fieldList.begin() ); + const KABC::Field::List::ConstIterator fieldEndIt( fieldList.end() ); + for ( ; fieldIt != fieldEndIt; ++fieldIt ) { + + if ( type == StartsWith && (*fieldIt)->value( *it ).startsWith( pattern, false ) ) { + mContacts.append( *it ); + found = true; + break; + } else if ( type == EndsWith && (*fieldIt)->value( *it ).endsWith( pattern, false ) ) { + mContacts.append( *it ); + found = true; + break; + } else if ( type == Contains && (*fieldIt)->value( *it ).find( pattern, 0, false ) != -1 ) { + mContacts.append( *it ); + found = true; + break; + } else if ( type == Equals && (*fieldIt)->value( *it ).localeAwareCompare( pattern ) == 0 ) { + mContacts.append( *it ); + found = true; + break; + } + } + + if ( !found ) { + // search over custom fields + const QStringList customs = (*it).customs(); + + QStringList::ConstIterator customIt( customs.begin() ); + const QStringList::ConstIterator customEndIt( customs.end() ); + for ( ; customIt != customEndIt; ++customIt ) { + int pos = (*customIt).find( ':' ); + if ( pos != -1 ) { + const QString value = (*customIt).mid( pos + 1 ); + if ( type == StartsWith && value.startsWith( pattern, false ) ) { + mContacts.append( *it ); + break; + } else if ( type == EndsWith && value.endsWith( pattern, false ) ) { + mContacts.append( *it ); + break; + } else if ( type == Contains && value.find( pattern, 0, false ) != -1 ) { + mContacts.append( *it ); + break; + } else if ( type == Equals && value.localeAwareCompare( pattern ) == 0 ) { + mContacts.append( *it ); + break; + } + } + } + } + } + + emit contactsUpdated(); +} + +KABC::Addressee::List SearchManager::contacts() const +{ + return mContacts; +} + +void SearchManager::reload() +{ + search( mPattern, mFields, mType ); +} + +#ifdef KDEPIM_NEW_DISTRLISTS + +void KAB::SearchManager::setSelectedDistributionList( const QString &name ) +{ + if ( mSelectedDistributionList == name ) + return; + mSelectedDistributionList = name; + reload(); +} + +KPIM::DistributionList::List KAB::SearchManager::distributionLists() const +{ + return mDistributionLists; +} + +QStringList KAB::SearchManager::distributionListNames() const +{ + QStringList lst; + KPIM::DistributionList::List::ConstIterator it( mDistributionLists.begin() ); + const KPIM::DistributionList::List::ConstIterator endIt( mDistributionLists.end() ); + for ( ; it != endIt; ++it ) { + lst.append( (*it).formattedName() ); + } + return lst; +} +#endif + +#include "searchmanager.moc" diff --git a/kaddressbook/searchmanager.h b/kaddressbook/searchmanager.h new file mode 100644 index 000000000..2179f6f60 --- /dev/null +++ b/kaddressbook/searchmanager.h @@ -0,0 +1,110 @@ +/* + This file is part of KAddressBook. + Copyright (c) 2004 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 SEARCHMANAGER_H +#define SEARCHMANAGER_H + +#include <config.h> // for KDEPIM_NEW_DISTRLISTS +#include <qobject.h> + +#include <kabc/stdaddressbook.h> +#ifdef KDEPIM_NEW_DISTRLISTS +#include <libkdepim/distributionlist.h> +#endif + +namespace KAB { + +class SearchManager : public QObject +{ + Q_OBJECT + + public: + enum Type { + StartsWith, + EndsWith, + Contains, + Equals + }; + + SearchManager( KABC::AddressBook *ab, + QObject *parent, const char *name = 0 ); + + /** + This method takes a pattern and searches for a match of the specified + field of all available contacts. The result is propagated via + contactsUpdated(). + + @param pattern The search string. + @param field The field which shall be compared with the search string. + @param type The type for the matching. + */ + void search( const QString &pattern, const KABC::Field::List &fields, Type type = Contains ); + + /** + Returns the contacts which matched the last search query. + */ + KABC::Addressee::List contacts() const; + + +#ifdef KDEPIM_NEW_DISTRLISTS + /** + sets the distribution list to be shown + */ + void setSelectedDistributionList( const QString &name ); + + /** + Returns all the distribution lists. + */ + KPIM::DistributionList::List distributionLists() const; + + /** + Returns the name of all the distribution lists. + */ + QStringList distributionListNames() const; +#endif + + signals: + /** + Emitted whenever the contacts have changed. + */ + void contactsUpdated(); + + public slots: + void reload(); + + private: + KABC::Addressee::List mContacts; +#ifdef KDEPIM_NEW_DISTRLISTS + QString mSelectedDistributionList; + KPIM::DistributionList::List mDistributionLists; +#endif + KABC::AddressBook *mAddressBook; + + QString mPattern; + KABC::Field::List mFields; + Type mType; +}; + +} + +#endif diff --git a/kaddressbook/secrecywidget.cpp b/kaddressbook/secrecywidget.cpp new file mode 100644 index 000000000..70b3bf3c8 --- /dev/null +++ b/kaddressbook/secrecywidget.cpp @@ -0,0 +1,72 @@ +/* + 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 <qlayout.h> + +#include <kabc/secrecy.h> +#include <kcombobox.h> +#include <kdialog.h> + +#include "secrecywidget.h" + +SecrecyWidget::SecrecyWidget( QWidget *parent, const char *name ) + : QWidget( parent, name ) +{ + QVBoxLayout *layout = new QVBoxLayout( this, KDialog::marginHint(), + KDialog::spacingHint() ); + mSecrecyCombo = new KComboBox( this ); + layout->addWidget( mSecrecyCombo ); + + const KABC::Secrecy::TypeList list = KABC::Secrecy::typeList(); + KABC::Secrecy::TypeList::ConstIterator it; + for ( it = list.begin(); it != list.end(); ++it ) + mSecrecyCombo->insertItem( KABC::Secrecy::typeLabel( *it ), *it ); + + connect( mSecrecyCombo, SIGNAL( activated( const QString& ) ), + SIGNAL( changed() ) ); +} + +SecrecyWidget::~SecrecyWidget() +{ +} + +void SecrecyWidget::setReadOnly( bool readOnly ) +{ + mSecrecyCombo->setEnabled( !readOnly ); +} + +void SecrecyWidget::setSecrecy( const KABC::Secrecy &secrecy ) +{ + if ( secrecy.type() != KABC::Secrecy::Invalid ) + mSecrecyCombo->setCurrentItem( secrecy.type() ); +} + +KABC::Secrecy SecrecyWidget::secrecy() const +{ + KABC::Secrecy secrecy; + secrecy.setType( mSecrecyCombo->currentItem() ); + + return secrecy; +} + +#include "secrecywidget.moc" diff --git a/kaddressbook/secrecywidget.h b/kaddressbook/secrecywidget.h new file mode 100644 index 000000000..e73e6fac0 --- /dev/null +++ b/kaddressbook/secrecywidget.h @@ -0,0 +1,52 @@ +/* + 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 SECRECYWIDGET_H +#define SECRECYWIDGET_H + +#include <qwidget.h> + +namespace KABC { class Secrecy; } +class KComboBox; + +class SecrecyWidget : public QWidget +{ + Q_OBJECT + + public: + SecrecyWidget( QWidget *parent, const char *name = 0 ); + ~SecrecyWidget(); + + void setSecrecy( const KABC::Secrecy &secrecy ); + KABC::Secrecy secrecy() const; + + void setReadOnly( bool readOnly ); + + signals: + void changed(); + + private: + KComboBox *mSecrecyCombo; +}; + +#endif diff --git a/kaddressbook/simpleaddresseeeditor.cpp b/kaddressbook/simpleaddresseeeditor.cpp new file mode 100644 index 000000000..e377feeed --- /dev/null +++ b/kaddressbook/simpleaddresseeeditor.cpp @@ -0,0 +1,129 @@ +/* + This file is part of KAddressBook. + Copyright (c) 2002 Mike Pilone <mpilone@slac.com> + + 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 <qlayout.h> +#include <qlabel.h> + +#include <klineedit.h> +#include <klocale.h> +#include <kdialog.h> + +#include "simpleaddresseeeditor.h" + +SimpleAddresseeEditor::SimpleAddresseeEditor( QWidget *parent, const char *name ) + : AddresseeEditorBase( parent, name ), + mDirty( false ), + mBlockModified( false ) +{ + kdDebug(5720) << "SimpleAddresseeEditor()" << endl; + + initGui(); +} + +SimpleAddresseeEditor::~SimpleAddresseeEditor() +{ + kdDebug(5720) << "~SimpleAddresseeEditor()" << endl; +} + +void SimpleAddresseeEditor::setAddressee( const KABC::Addressee &addr ) +{ + mAddressee = addr; + + load(); +} + +const KABC::Addressee &SimpleAddresseeEditor::addressee() +{ + return mAddressee; +} + +void SimpleAddresseeEditor::setInitialFocus() +{ + mNameEdit->setFocus(); +} + +void SimpleAddresseeEditor::initGui() +{ + QGridLayout *topLayout = new QGridLayout( this, 2, 2, KDialog::marginHint(), + KDialog::spacingHint() ); + + QLabel *label = new QLabel( i18n( "Name:" ), this ); + topLayout->addWidget( label, 0, 0 ); + + mNameEdit = new KLineEdit( this ); + topLayout->addWidget( mNameEdit, 0, 1 ); + connect( mNameEdit, SIGNAL( textChanged( const QString & ) ), + SLOT( emitModified() ) ); + + label = new QLabel( i18n( "Email:" ), this ); + topLayout->addWidget( label, 1, 0 ); + + mEmailEdit = new KLineEdit( this ); + topLayout->addWidget( mEmailEdit, 1, 1 ); + connect( mEmailEdit, SIGNAL( textChanged( const QString & ) ), + SLOT( emitModified() ) ); +} + +void SimpleAddresseeEditor::load() +{ + kdDebug(5720) << "SimpleAddresseeEditor::load()" << endl; + + kdDebug(5720) << "ASSEMBLED NAME: " << mAddressee.assembledName() << endl; + kdDebug(5720) << "EMAIL NAME: " << mAddressee.preferredEmail() << endl; + + mBlockModified = true; + + mNameEdit->setText( mAddressee.assembledName() ); + mEmailEdit->setText( mAddressee.preferredEmail() ); + + mBlockModified = false; + + mDirty = false; +} + +void SimpleAddresseeEditor::save() +{ + if ( !mDirty ) return; + + mAddressee.setNameFromString( mNameEdit->text() ); + mAddressee.insertEmail( mEmailEdit->text(), true ); + + mDirty = false; +} + +bool SimpleAddresseeEditor::dirty() +{ + return mDirty; +} + +void SimpleAddresseeEditor::emitModified() +{ + if ( mBlockModified ) + return; + + mDirty = true; + + emit modified(); +} + +#include "simpleaddresseeeditor.moc" diff --git a/kaddressbook/simpleaddresseeeditor.h b/kaddressbook/simpleaddresseeeditor.h new file mode 100644 index 000000000..560148901 --- /dev/null +++ b/kaddressbook/simpleaddresseeeditor.h @@ -0,0 +1,65 @@ +/* + This file is part of KAddressBook. + + Copyright (c) 2003 Cornelius Schumacher <schumacher@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 SIMPLEADDRESSEEEDITOR_H +#define SIMPLEADDRESSEEEDITOR_H + +#include "addresseeeditorwidget.h" + +class KLineEdit; + +class SimpleAddresseeEditor : public AddresseeEditorBase +{ + Q_OBJECT + public: + SimpleAddresseeEditor( QWidget *parent, const char *name = 0 ); + ~SimpleAddresseeEditor(); + + void setAddressee( const KABC::Addressee& ); + const KABC::Addressee &addressee(); + + void load(); + void save(); + + bool dirty(); + + void setInitialFocus(); + + protected slots: + void emitModified(); + + protected: + void initGui(); + + private: + KLineEdit *mNameEdit; + KLineEdit *mEmailEdit; + + KABC::Addressee mAddressee; + + bool mDirty; + bool mBlockModified; +}; + +#endif diff --git a/kaddressbook/soundwidget.cpp b/kaddressbook/soundwidget.cpp new file mode 100644 index 000000000..74b8137ef --- /dev/null +++ b/kaddressbook/soundwidget.cpp @@ -0,0 +1,179 @@ +/* + This file is part of KAddressBook. + Copyright (c) 2003 - 2004 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 <kabc/sound.h> +#include <kaudioplayer.h> +#include <kdebug.h> +#include <kdialog.h> +#include <kiconloader.h> +#include <kio/netaccess.h> +#include <klocale.h> +#include <ktempfile.h> +#include <kurlrequester.h> + +#include <qcheckbox.h> +#include <qlabel.h> +#include <qlayout.h> +#include <qpushbutton.h> +#include <qwhatsthis.h> + +#include "soundwidget.h" + +SoundWidget::SoundWidget( KABC::AddressBook *ab, QWidget *parent, const char *name ) + : KAB::ContactEditorWidget( ab, parent, name ), mReadOnly( false ) +{ + QGridLayout *topLayout = new QGridLayout( this, 2, 3, KDialog::marginHint(), + KDialog::spacingHint() ); + + QLabel *label = new QLabel( this ); + label->setPixmap( KGlobal::iconLoader()->loadIcon( "multimedia", + KIcon::Desktop, KIcon::SizeMedium ) ); + label->setAlignment( Qt::AlignTop ); + topLayout->addMultiCellWidget( label, 0, 1, 0, 0 ); + + mPlayButton = new QPushButton( i18n( "Play" ), this ); + mPlayButton->setEnabled( false ); + topLayout->addWidget( mPlayButton, 0, 1 ); + + mSoundUrl = new KURLRequester( this ); + topLayout->addWidget( mSoundUrl, 0, 2 ); + + mUseSoundUrl = new QCheckBox( i18n( "Store as URL" ), this ); + mUseSoundUrl->setEnabled( false ); + topLayout->addWidget( mUseSoundUrl, 1, 2 ); + + connect( mSoundUrl, SIGNAL( textChanged( const QString& ) ), + SLOT( setModified() ) ); + connect( mSoundUrl, SIGNAL( textChanged( const QString& ) ), + SLOT( urlChanged( const QString& ) ) ); + connect( mUseSoundUrl, SIGNAL( toggled( bool ) ), + SLOT( setModified() ) ); + connect( mUseSoundUrl, SIGNAL( toggled( bool ) ), + mPlayButton, SLOT( setDisabled( bool ) ) ); + connect( mSoundUrl, SIGNAL( urlSelected( const QString& ) ), + SLOT( loadSound() ) ); + connect( mSoundUrl, SIGNAL( urlSelected( const QString& ) ), + SLOT( updateGUI() ) ); + connect( mPlayButton, SIGNAL( clicked() ), + SLOT( playSound() ) ); + + QWhatsThis::add( this, i18n( "This field stores a sound file which contains the name of the contact to clarify the pronunciation." ) ); + QWhatsThis::add( mUseSoundUrl, i18n( "Save only the URL to the sound file, not the whole object." ) ); +} + +SoundWidget::~SoundWidget() +{ +} + +void SoundWidget::loadContact( KABC::Addressee *addr ) +{ + bool blocked = signalsBlocked(); + blockSignals( true ); + + KABC::Sound sound = addr->sound(); + if ( sound.isIntern() ) { + mSound.setData( sound.data() ); + mPlayButton->setEnabled( true ); + mUseSoundUrl->setChecked( false ); + } else { + mSoundUrl->setURL( sound.url() ); + mPlayButton->setEnabled( false ); + if ( !sound.url().isEmpty() ) + mUseSoundUrl->setChecked( true ); + } + + blockSignals( blocked ); +} + +void SoundWidget::storeContact( KABC::Addressee *addr ) +{ + KABC::Sound sound; + + if ( mUseSoundUrl->isChecked() ) + sound.setUrl( mSoundUrl->url() ); + else + sound.setData( mSound.data() ); + + addr->setSound( sound ); +} + +void SoundWidget::setReadOnly( bool readOnly ) +{ + mReadOnly = readOnly; + mSoundUrl->setEnabled( !mReadOnly ); +} + +void SoundWidget::playSound() +{ + KTempFile tmp; + + tmp.file()->writeBlock( mSound.data() ); + tmp.close(); + + KAudioPlayer::play( tmp.name() ); + + // we can't remove the sound file from within the program, because + // KAudioPlay uses a async dcop call... :( +} + +void SoundWidget::loadSound() +{ + QString fileName; + + KURL url( mSoundUrl->url() ); + + if ( url.isEmpty() ) + return; + + if ( url.isLocalFile() ) + fileName = url.path(); + else if ( !KIO::NetAccess::download( url, fileName, this ) ) + return; + + QFile file( fileName ); + if ( !file.open( IO_ReadOnly ) ) + return; + + mSound.setData( file.readAll() ); + + file.close(); + + if ( !url.isLocalFile() ) + KIO::NetAccess::removeTempFile( fileName ); +} + +void SoundWidget::updateGUI() +{ + mUseSoundUrl->setEnabled( !mReadOnly ); +} + +void SoundWidget::urlChanged( const QString &url ) +{ + if ( !mUseSoundUrl->isChecked() ) { + bool state = !url.isEmpty(); + mPlayButton->setEnabled( state ); + mUseSoundUrl->setEnabled( state && !mSound.isIntern() ); + } +} + +#include "soundwidget.moc" diff --git a/kaddressbook/soundwidget.h b/kaddressbook/soundwidget.h new file mode 100644 index 000000000..b0ad168a7 --- /dev/null +++ b/kaddressbook/soundwidget.h @@ -0,0 +1,75 @@ +/* + This file is part of KAddressBook. + Copyright (c) 2003 - 2004 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 SOUNDWIDGET_H +#define SOUNDWIDGET_H + +#include <kabc/sound.h> + +#include "contacteditorwidget.h" + +class KURLRequester; + +class QCheckBox; +class QPushButton; + +class SoundWidget : public KAB::ContactEditorWidget +{ + Q_OBJECT + + public: + SoundWidget( KABC::AddressBook *ab, QWidget *parent, const char *name = 0 ); + ~SoundWidget(); + + void loadContact( KABC::Addressee *addr ); + void storeContact( KABC::Addressee *addr ); + void setReadOnly( bool readOnly ); + + private slots: + void playSound(); + void loadSound(); + void updateGUI(); + void urlChanged( const QString& ); + + private: + KURLRequester *mSoundUrl; + + QCheckBox *mUseSoundUrl; + QPushButton *mPlayButton; + + KABC::Sound mSound; + bool mReadOnly; +}; + +class SoundWidgetFactory : public KAB::ContactEditorWidgetFactory +{ + public: + KAB::ContactEditorWidget *createWidget( KABC::AddressBook *ab, QWidget *parent, const char *name ) + { + return new SoundWidget( ab, parent, name ); + } + + QString pageIdentifier() const { return "misc"; } +}; + +#endif diff --git a/kaddressbook/thumbnailcreator/Makefile.am b/kaddressbook/thumbnailcreator/Makefile.am new file mode 100644 index 000000000..2e37c0098 --- /dev/null +++ b/kaddressbook/thumbnailcreator/Makefile.am @@ -0,0 +1,15 @@ +# kioslave to generate thumbnails for vCard and LDIF-Files in Konqueror +INCLUDES = $(all_includes) + +kde_module_LTLIBRARIES = ldifvcardthumbnail.la + +ldifvcardthumbnail_la_SOURCES = ldifvcardcreator.cpp +ldifvcardthumbnail_la_LDFLAGS = -module $(KDE_PLUGIN) $(KDE_RPATH) $(all_libraries) -no-undefined +ldifvcardthumbnail_la_LIBADD = $(LIB_KDECORE) $(LIB_KABC) -lkdefx + +noinst_HEADERS = ldifvcardcreator.h + +METASOURCES = AUTO + +servicesdir = $(kde_servicesdir) +services_DATA = ldifvcardthumbnail.desktop diff --git a/kaddressbook/thumbnailcreator/ldifvcardcreator.cpp b/kaddressbook/thumbnailcreator/ldifvcardcreator.cpp new file mode 100644 index 000000000..4c8a5611e --- /dev/null +++ b/kaddressbook/thumbnailcreator/ldifvcardcreator.cpp @@ -0,0 +1,297 @@ +/* + This file is part of KAddressBook. + Copyright (C) 2003 Helge Deller <deller@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + version 2 License as published by the Free Software Foundation. + + 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. +*/ + +/* + * - ldifvcardthumbnail - + * + * kioslave which generates tumbnails for vCard and LDIF files. + * The thumbnails are used e.g. by Konqueror or in the file selection + * dialog. + * + */ + +#include <qdatetime.h> +#include <qfile.h> +#include <qpixmap.h> +#include <qimage.h> +#include <qpainter.h> +#include <qtextstream.h> + +#include <kdebug.h> +#include <kglobal.h> +#include <klocale.h> +#include <kabc/ldifconverter.h> +#include <kabc/vcardconverter.h> +#include <kpixmapsplitter.h> +#include <kstandarddirs.h> +#include <kglobalsettings.h> + +#include "ldifvcardcreator.h" + +extern "C" +{ + ThumbCreator *new_creator() + { + KGlobal::locale()->insertCatalogue( "kaddressbook" ); + return new VCard_LDIFCreator; + } +} + +VCard_LDIFCreator::VCard_LDIFCreator() + : mSplitter( 0 ) +{ +} + +VCard_LDIFCreator::~VCard_LDIFCreator() +{ + delete mSplitter; +} + + +bool VCard_LDIFCreator::readContents( const QString &path ) +{ + // read file contents + QFile file( path ); + if ( !file.open( IO_ReadOnly ) ) + return false; + + QString info; + text.truncate(0); + + // read the file + QString contents = file.readAll(); + file.close(); + + // convert the file contents to a KABC::Addressee address + KABC::AddresseeList addrList; + KABC::Addressee addr; + KABC::VCardConverter converter; + + addrList = converter.parseVCards( contents ); + if ( addrList.count() == 0 ) + if ( !KABC::LDIFConverter::LDIFToAddressee( contents, addrList ) ) + return false; + if ( addrList.count()>1 ) { + // create an overview (list of all names) + name = i18n("One contact found:", "%n contacts found:", addrList.count()); + unsigned int no, linenr; + for (linenr=no=0; linenr<30 && no<addrList.count(); ++no) { + addr = addrList[no]; + info = addr.formattedName().simplifyWhiteSpace(); + if (info.isEmpty()) + info = addr.givenName() + " " + addr.familyName(); + info = info.simplifyWhiteSpace(); + if (info.isEmpty()) + continue; + text.append(info); + text.append("\n"); + ++linenr; + } + return true; + } + + // create card for _one_ contact + addr = addrList[ 0 ]; + + // prepare the text + name = addr.formattedName().simplifyWhiteSpace(); + if ( name.isEmpty() ) + name = addr.givenName() + " " + addr.familyName(); + name = name.simplifyWhiteSpace(); + + + KABC::PhoneNumber::List pnList = addr.phoneNumbers(); + QStringList phoneNumbers; + for (unsigned int no=0; no<pnList.count(); ++no) { + QString pn = pnList[no].number().simplifyWhiteSpace(); + if (!pn.isEmpty() && !phoneNumbers.contains(pn)) + phoneNumbers.append(pn); + } + if ( !phoneNumbers.isEmpty() ) + text += phoneNumbers.join("\n") + "\n"; + + info = addr.organization().simplifyWhiteSpace(); + if ( !info.isEmpty() ) + text += info + "\n"; + + // get an address + KABC::Address address = addr.address(KABC::Address::Work); + if (address.isEmpty()) + address = addr.address(KABC::Address::Home); + if (address.isEmpty()) + address = addr.address(KABC::Address::Pref); + info = address.formattedAddress(); + if ( !info.isEmpty() ) + text += info + "\n"; + + return true; +} + + +bool VCard_LDIFCreator::createImageSmall() +{ + text = name + "\n" + text; + + if ( !mSplitter ) { + mSplitter = new KPixmapSplitter; + QString pixmap = locate( "data", "konqueror/pics/thumbnailfont_7x4.png" ); + if ( pixmap.isEmpty() ) { + delete mSplitter; + mSplitter=0; + kdWarning() << "VCard_LDIFCreator: Font image \"thumbnailfont_7x4.png\" not found!\n"; + return false; + } + mSplitter->setPixmap( QPixmap( pixmap ) ); + mSplitter->setItemSize( QSize( 4, 7 ) ); + } + + QSize chSize = mSplitter->itemSize(); // the size of one char + int xOffset = chSize.width(); + int yOffset = chSize.height(); + + // calculate a better border so that the text is centered + int canvasWidth = pixmapSize.width() - 2 * xborder; + int canvasHeight = pixmapSize.height() - 2 * yborder; + int numCharsPerLine = (int) (canvasWidth / chSize.width()); + int numLines = (int) (canvasHeight / chSize.height()); + + // render the information + QRect rect; + int rest = mPixmap.width() - (numCharsPerLine * chSize.width()); + xborder = QMAX( xborder, rest / 2 ); // center horizontally + rest = mPixmap.height() - (numLines * chSize.height()); + yborder = QMAX( yborder, rest / 2 ); // center vertically + // end centering + + int x = xborder, y = yborder; // where to paint the characters + int posNewLine = mPixmap.width() - (chSize.width() + xborder); + int posLastLine = mPixmap.height() - (chSize.height() + yborder); + bool newLine = false; + Q_ASSERT( posNewLine > 0 ); + const QPixmap *fontPixmap = &(mSplitter->pixmap()); + + for ( uint i = 0; i < text.length(); i++ ) { + if ( x > posNewLine || newLine ) { // start a new line? + x = xborder; + y += yOffset; + + if ( y > posLastLine ) // more text than space + break; + + // after starting a new line, we also jump to the next + // physical newline in the file if we don't come from one + if ( !newLine ) { + int pos = text.find( '\n', i ); + if ( pos > (int) i ) + i = pos +1; + } + + newLine = false; + } + + // check for newlines in the text (unix,dos) + QChar ch = text.at( i ); + if ( ch == '\n' ) { + newLine = true; + continue; + } else if ( ch == '\r' && text.at(i+1) == '\n' ) { + newLine = true; + i++; // skip the next character (\n) as well + continue; + } + + rect = mSplitter->coordinates( ch ); + if ( !rect.isEmpty() ) + bitBlt( &mPixmap, QPoint(x,y), fontPixmap, rect, Qt::CopyROP ); + + x += xOffset; // next character + } + + return true; +} + +bool VCard_LDIFCreator::createImageBig() +{ + QFont normalFont( KGlobalSettings::generalFont() ); + QFont titleFont( normalFont ); + titleFont.setBold(true); + // titleFont.setUnderline(true); + titleFont.setItalic(true); + + QPainter painter(&mPixmap); + painter.setFont(titleFont); + QFontMetrics fm(painter.fontMetrics()); + + // draw contact name + painter.setClipRect(2, 2, pixmapSize.width()-4, pixmapSize.height()-4); + QPoint p(5, fm.height()+2); + painter.drawText(p, name); + p.setY( 3*p.y()/2 ); + + // draw contact information + painter.setFont(normalFont); + fm = painter.fontMetrics(); + + const QStringList list( QStringList::split('\n', text) ); + for ( QStringList::ConstIterator it = list.begin(); + p.y()<=pixmapSize.height() && it != list.end(); ++it ) { + p.setY( p.y() + fm.height() ); + painter.drawText(p, *it); + } + + return true; +} + +bool VCard_LDIFCreator::create(const QString &path, int width, int height, QImage &img) +{ + if ( !readContents(path) ) + return false; + + // resize the image if necessary + pixmapSize = QSize( width, height ); + if (height * 3 > width * 4) + pixmapSize.setHeight( width * 4 / 3 ); + else + pixmapSize.setWidth( height * 3 / 4 ); + + if ( pixmapSize != mPixmap.size() ) + mPixmap.resize( pixmapSize ); + + mPixmap.fill( QColor( 245, 245, 245 ) ); // light-grey background + + // one pixel for the rectangle, the rest. whitespace + xborder = 1 + pixmapSize.width()/16; // minimum x-border + yborder = 1 + pixmapSize.height()/16; // minimum y-border + + bool ok; + if ( width >= 150 /*pixel*/ ) + ok = createImageBig(); + else + ok = createImageSmall(); + if (!ok) + return false; + + img = mPixmap.convertToImage(); + return true; +} + +ThumbCreator::Flags VCard_LDIFCreator::flags() const +{ + return (Flags)(DrawFrame | BlendIcon); +} diff --git a/kaddressbook/thumbnailcreator/ldifvcardcreator.h b/kaddressbook/thumbnailcreator/ldifvcardcreator.h new file mode 100644 index 000000000..e6ae6ba42 --- /dev/null +++ b/kaddressbook/thumbnailcreator/ldifvcardcreator.h @@ -0,0 +1,50 @@ +/* + This file is part of KAddressBook. + Copyright (C) 2003 Helge Deller <deller@kde.org> + + 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 VCARD_LDIFCREATOR_H +#define VCARD_LDIFCREATOR_H + +#include <qpixmap.h> +#include <kio/thumbcreator.h> + +class KPixmapSplitter; + +class VCard_LDIFCreator : public ThumbCreator +{ + public: + VCard_LDIFCreator(); + virtual ~VCard_LDIFCreator(); + virtual bool create(const QString &path, int width, int height, QImage &img); + virtual Flags flags() const; + + private: + KPixmapSplitter *mSplitter; + QPixmap mPixmap; + + QString name; + QString text; + bool readContents( const QString &path ); + int xborder, yborder; + QSize pixmapSize; + bool createImageSmall(); + bool createImageBig(); +}; + +#endif diff --git a/kaddressbook/thumbnailcreator/ldifvcardthumbnail.desktop b/kaddressbook/thumbnailcreator/ldifvcardthumbnail.desktop new file mode 100644 index 000000000..2eb63ab57 --- /dev/null +++ b/kaddressbook/thumbnailcreator/ldifvcardthumbnail.desktop @@ -0,0 +1,57 @@ +[Desktop Entry] +Type=Service +Name=Electronic Business Card Files +Name[af]=Elektroniese Besigheid kaartjie lêers +Name[ar]=ملفّات بطاقة الأعمال الإلكترونيّة +Name[bg]=Файлове за електронна визитка +Name[bs]=Datoteke elektronskih vizit karti +Name[ca]=Fitxers targeta de visita electrònica +Name[cs]=Soubory s elektronickými vizitkami +Name[cy]=Ffeiliau Cerdyn Busnes Electronig +Name[da]=Elektroniske forretningskort-filer +Name[de]=Dateien für elektronische Visitenkarten +Name[el]=Αρχεία επαγγελματικών ηλεκτρονικών καρτών +Name[eo]=Dosieroj de Elektronika Vizitkarto +Name[es]=Archivos de tarjetas de visita electrónicas +Name[et]=Elektrooniline visiitkaart +Name[eu]=Electronic Business Card fitxategiak +Name[fa]=پروندههای کارت تجاری الکترونیکی +Name[fi]=Sähköiset käyntikorttitiedostot +Name[fr]=Fichiers de cartes de commerce électroniques +Name[fy]=Elektronyske fisitekaartsjetriemmen +Name[gl]=Ficheiros de Tarxetas de Visita Electrónicas +Name[hi]=इलेक्ट्रानिक व्यापार कार्ड फ़ाइलें +Name[hu]=Elektronikus névjegykártyák +Name[is]=Skrár með rafrænum nafnspjöldum +Name[it]=Biglietto da visita elettronico +Name[ja]=電子ビジネスカードファイル +Name[ka]=ელექტრონული სავიზიტო ბარათების ფაილები +Name[kk]=Электрондық визитка файлдары +Name[km]=ឯកសារនាមប័ណ្ណអេឡិចត្រូនិច +Name[lt]=Elektroninės verslo kortelės bylos +Name[mk]=Датотеки со електронски деловни картички +Name[ms]=Fail Kad Perniagaan Elektronik +Name[nb]=Filer for elektroniske visittkort +Name[nds]=Dateien mit elektroonsche Visitenkoorten +Name[ne]=बिद्युतीय व्यवसायीक कार्ड फाइल +Name[nl]=Elektronische visitekaartbestanden +Name[nn]=Filer for elektroniske visittkort +Name[pl]=Pliki elektronicznych wizytówek +Name[pt]=Ficheiros de Cartões Profissionais Electrónicos +Name[pt_BR]=Arquivos de Cartão de Visita Eletrônico +Name[ru]=Файлы электронных визиток +Name[sk]=Súbory elektronických vizitiek +Name[sl]=Datoteke elektronskih vizitk +Name[sr]=Фајлови електронске пословне картице +Name[sr@Latn]=Fajlovi elektronske poslovne kartice +Name[sv]=Elektroniska visitkortsfiler +Name[ta]=மின்னணு தொழில் அட்டை கோப்புகள் +Name[tg]=Файлҳои визиткаи электронӣ +Name[tr]=Elektronik İş Kartı Dosyaları +Name[uk]=файли електронних візитних карток +Name[zh_CN]=电子名片文件 +Name[zh_TW]=電子名片檔 +ServiceTypes=ThumbCreator +MimeTypes=text/x-vcard,text/x-ldif +X-KDE-Library=ldifvcardthumbnail +CacheThumbnail=false diff --git a/kaddressbook/typecombo.h b/kaddressbook/typecombo.h new file mode 100644 index 000000000..3b411c86c --- /dev/null +++ b/kaddressbook/typecombo.h @@ -0,0 +1,177 @@ +/* + This file is part of KAddressBook. + Copyright (c) 2002 Cornelius Schumacher <schumacher@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 TYPECOMBO_H +#define TYPECOMBO_H + +#include <kabc/phonenumber.h> +#include <kcombobox.h> + +/** + Combo box for type information of Addresses and Phone numbers. +*/ +template <class T> +class TypeCombo : public KComboBox +{ + public: + typedef typename T::List List; + typedef typename T::List::Iterator Iterator; + + TypeCombo( List &list, QWidget *parent, const char *name = 0 ); + + void setLineEdit( QLineEdit *edit ) { mLineEdit = edit; } + QLineEdit *lineEdit() const { return mLineEdit; } + + void updateTypes(); + + void selectType( int type ); + + int selectedType(); + + Iterator selectedElement(); + + void insertType( const List &list, int type, + const T &defaultObject ); + void insertTypeList( const List &list ); + + bool hasType( int type ); + + private: + List &mTypeList; + QLineEdit *mLineEdit; +}; + +template <class T> +TypeCombo<T>::TypeCombo( TypeCombo::List &list, QWidget *parent, + const char *name ) + : KComboBox( parent, name ), + mTypeList( list ) +{ +} + +template <class T> +void TypeCombo<T>::updateTypes() +{ + // Remember current item + QString currentId; + int current = currentItem(); + if ( current >= 0 ) currentId = mTypeList[ current ].id(); + + clear(); + + QMap<int,int> labelCount; + + uint i; + for ( i = 0; i < mTypeList.count(); ++i ) { + int type = ( mTypeList[ i ].type() & ~( T::Pref ) ); + QString label = mTypeList[ i ].typeLabel( type ); + int count = 1; + if ( labelCount.contains( type ) ) { + count = labelCount[ type ] + 1; + } + labelCount[ type ] = count; + if ( count > 1 ) { + label = i18n("label (number)", "%1 (%2)").arg( label ) + .arg( QString::number( count ) ); + } + insertItem( label ); + } + + // Restore previous current item + if ( !currentId.isEmpty() ) { + for ( i = 0; i < mTypeList.count(); ++i ) { + if ( mTypeList[ i ].id() == currentId ) { + setCurrentItem( i ); + break; + } + } + } +} + +template <class T> +void TypeCombo<T>::selectType( int type ) +{ + uint i; + for ( i = 0; i < mTypeList.count(); ++i ) { + if ( (mTypeList[ i ].type() & ~T::Pref) == type ) { + setCurrentItem( i ); + break; + } + } +} + +template <class T> +int TypeCombo<T>::selectedType() +{ + return mTypeList[ currentItem() ].type(); +} + +template <class T> +typename TypeCombo<T>::Iterator TypeCombo<T>::selectedElement() +{ + return mTypeList.at( currentItem() ); +} + +template <class T> +void TypeCombo<T>::insertType( const TypeCombo::List &list, int type, + const T &defaultObject ) +{ + uint i; + for ( i = 0; i < list.count(); ++i ) { + if ( list[ i ].type() == type ) { + mTypeList.append( list[ i ] ); + break; + } + } + if ( i == list.count() ) { + mTypeList.append( defaultObject ); + } +} + +template <class T> +void TypeCombo<T>::insertTypeList( const TypeCombo::List &list ) +{ + uint i; + for ( i = 0; i < list.count(); ++i ) { + uint j; + for ( j = 0; j < mTypeList.count(); ++j ) { + if ( list[ i ].id() == mTypeList[ j ].id() ) break; + } + if ( j == mTypeList.count() ) { + mTypeList.append( list[ i ] ); + } + } +} + +template <class T> +bool TypeCombo<T>::hasType( int type ) +{ + for ( uint i = 0; i < mTypeList.count(); ++i ) { + if ( ( mTypeList[ i ].type() & ~T::Pref ) == type ) + return true; + } + + return false; +} + +#endif diff --git a/kaddressbook/undocmds.cpp b/kaddressbook/undocmds.cpp new file mode 100644 index 000000000..e9350c1bf --- /dev/null +++ b/kaddressbook/undocmds.cpp @@ -0,0 +1,272 @@ +/* + This file is part of KAddressBook. + Copyright (C) 1999 Don Sanders <sanders@kde.org> + 2005 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 <qapplication.h> +#include <qclipboard.h> + +#include <klocale.h> +#include <kapplication.h> + +#include "addresseeutil.h" +#include "addresseeconfig.h" +#include "core.h" +#include "kablock.h" + +#include "undocmds.h" + +DeleteCommand::DeleteCommand( KABC::AddressBook *addressBook, + const QStringList &uidList) + : Command( addressBook ), mUIDList( uidList ) +{ +} + +QString DeleteCommand::name() const +{ + return i18n( "Delete Contact", "Delete %n Contacts", mUIDList.count() ); +} + +void DeleteCommand::unexecute() +{ + // Put it back in the document + KABC::Addressee::List::ConstIterator it; + const KABC::Addressee::List::ConstIterator endIt( mAddresseeList.end() ); + + // lock resources + for ( it = mAddresseeList.begin(); it != endIt; ++it ) + lock()->lock( (*it).resource() ); + + for ( it = mAddresseeList.begin(); it != endIt; ++it ) { + addressBook()->insertAddressee( *it ); + lock()->unlock( (*it).resource() ); + } + + mAddresseeList.clear(); +} + +void DeleteCommand::execute() +{ + KABC::Addressee addr; + + QStringList::ConstIterator it; + const QStringList::ConstIterator endIt( mUIDList.end() ); + for ( it = mUIDList.begin(); it != endIt; ++it ) { + addr = addressBook()->findByUid( *it ); + lock()->lock( addr.resource() ); + mAddresseeList.append( addr ); + AddresseeConfig cfg( addr ); + cfg.remove(); + } + + KABC::Addressee::List::ConstIterator addrIt; + const KABC::Addressee::List::ConstIterator addrEndIt( mAddresseeList.end() ); + for ( addrIt = mAddresseeList.begin(); addrIt != addrEndIt; ++addrIt ) { + addressBook()->removeAddressee( *addrIt ); + lock()->unlock( (*addrIt).resource() ); + } +} + + +PasteCommand::PasteCommand( KAB::Core *core, const KABC::Addressee::List &addressees ) + : Command( core->addressBook() ), mAddresseeList( addressees ), mCore( core ) +{ +} + +QString PasteCommand::name() const +{ + return i18n( "Paste Contact", "Paste %n Contacts", mAddresseeList.count() ); +} + +void PasteCommand::unexecute() +{ + KABC::Addressee::List::ConstIterator it; + const KABC::Addressee::List::ConstIterator endIt( mAddresseeList.end() ); + + // lock resources + for ( it = mAddresseeList.begin(); it != endIt; ++it ) + lock()->lock( (*it).resource() ); + + for ( it = mAddresseeList.begin(); it != endIt; ++it ) { + addressBook()->removeAddressee( *it ); + lock()->unlock( (*it).resource() ); + } +} + +void PasteCommand::execute() +{ + QStringList uids; + + KABC::Addressee::List::ConstIterator constIt; + const KABC::Addressee::List::ConstIterator constEndIt( mAddresseeList.end() ); + + // lock resources + for ( constIt = mAddresseeList.begin(); constIt != constEndIt; ++constIt ) + lock()->lock( (*constIt).resource() ); + + KABC::Addressee::List::Iterator it; + const KABC::Addressee::List::Iterator endIt( mAddresseeList.end() ); + for ( it = mAddresseeList.begin(); it != endIt; ++it ) { + /** + We have to set a new uid for the contact, otherwise insertAddressee() + ignore it. + */ + (*it).setUid( KApplication::randomString( 10 ) ); + uids.append( (*it).uid() ); + addressBook()->insertAddressee( *it ); + lock()->unlock( (*it).resource() ); + } + + QStringList::ConstIterator uidIt; + const QStringList::ConstIterator uidEndIt( uids.end() ); + for ( uidIt = uids.begin(); uidIt != uidEndIt; ++uidIt ) + mCore->editContact( *uidIt ); +} + + +NewCommand::NewCommand( KABC::AddressBook *addressBook, const KABC::Addressee::List &addressees ) + : Command( addressBook ), mAddresseeList( addressees ) +{ +} + +QString NewCommand::name() const +{ + return i18n( "New Contact", "New %n Contacts", mAddresseeList.count() ); +} + +void NewCommand::unexecute() +{ + KABC::Addressee::List::ConstIterator it; + const KABC::Addressee::List::ConstIterator endIt( mAddresseeList.end() ); + + // lock resources + for ( it = mAddresseeList.begin(); it != endIt; ++it ) + lock()->lock( (*it).resource() ); + + for ( it = mAddresseeList.begin(); it != endIt; ++it ) { + addressBook()->removeAddressee( *it ); + lock()->unlock( (*it).resource() ); + } +} + +void NewCommand::execute() +{ + KABC::Addressee::List::Iterator it; + const KABC::Addressee::List::Iterator endIt( mAddresseeList.end() ); + + // lock resources + for ( it = mAddresseeList.begin(); it != endIt; ++it ) + lock()->lock( (*it).resource() ); + + for ( it = mAddresseeList.begin(); it != endIt; ++it ) { + addressBook()->insertAddressee( *it ); + lock()->unlock( (*it).resource() ); + } +} + + +EditCommand::EditCommand( KABC::AddressBook *addressBook, + const KABC::Addressee &oldAddressee, + const KABC::Addressee &newAddressee ) + : Command( addressBook ), + mOldAddressee( oldAddressee ), mNewAddressee( newAddressee ) +{ +} + +QString EditCommand::name() const +{ + return i18n( "Edit Contact" ); +} + +void EditCommand::unexecute() +{ + lock()->lock( mOldAddressee.resource() ); + addressBook()->insertAddressee( mOldAddressee ); + lock()->unlock( mOldAddressee.resource() ); +} + +void EditCommand::execute() +{ + lock()->lock( mNewAddressee.resource() ); + addressBook()->insertAddressee( mNewAddressee ); + lock()->unlock( mNewAddressee.resource() ); +} + + +CutCommand::CutCommand( KABC::AddressBook *addressBook, const QStringList &uidList ) + : Command( addressBook ), mUIDList( uidList ) +{ +} + +QString CutCommand::name() const +{ + return i18n( "Cut Contact", "Cut %n Contacts", mUIDList.count() ); +} + +void CutCommand::unexecute() +{ + KABC::Addressee::List::ConstIterator it; + const KABC::Addressee::List::ConstIterator endIt( mAddresseeList.end() ); + + // lock resources + for ( it = mAddresseeList.begin(); it != endIt; ++it ) + lock()->lock( (*it).resource() ); + + for ( it = mAddresseeList.begin(); it != endIt; ++it ) { + addressBook()->insertAddressee( *it ); + lock()->unlock( (*it).resource() ); + } + + mAddresseeList.clear(); + + QClipboard *cb = QApplication::clipboard(); + kapp->processEvents(); + cb->setText( mOldText ); +} + +void CutCommand::execute() +{ + KABC::Addressee addr; + + QStringList::ConstIterator it; + const QStringList::ConstIterator endIt( mUIDList.end() ); + for ( it = mUIDList.begin(); it != endIt; ++it ) { + addr = addressBook()->findByUid( *it ); + mAddresseeList.append( addr ); + lock()->lock( addr.resource() ); + } + + KABC::Addressee::List::ConstIterator addrIt; + const KABC::Addressee::List::ConstIterator addrEndIt( mAddresseeList.end() ); + for ( addrIt = mAddresseeList.begin(); addrIt != addrEndIt; ++addrIt ) { + addressBook()->removeAddressee( *addrIt ); + lock()->unlock( addr.resource() ); + } + + // Convert to clipboard + mClipText = AddresseeUtil::addresseesToClipboard( mAddresseeList ); + + QClipboard *cb = QApplication::clipboard(); + mOldText = cb->text(); + kapp->processEvents(); + cb->setText( mClipText ); +} diff --git a/kaddressbook/undocmds.h b/kaddressbook/undocmds.h new file mode 100644 index 000000000..27f7f24b9 --- /dev/null +++ b/kaddressbook/undocmds.h @@ -0,0 +1,130 @@ +/* + This file is part of KAddressBook. + Copyright (C) 1999 Don Sanders <sanders@kde.org> + 2005 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 COMMANDS_H +#define COMMANDS_H + +// Commands for undo/redo functionality. + +#include <qstring.h> +#include <qstringlist.h> + +#include <kabc/addressbook.h> +#include <kabc/addressee.h> +#include <kcommand.h> + +#include "kablock.h" + +namespace KAB { +class Core; +} + +class Command : public KCommand +{ + public: + Command( KABC::AddressBook *addressBook ) { mAddressBook = addressBook; } + + protected: + KABC::AddressBook *addressBook() const { return mAddressBook; } + KABLock *lock() const { return KABLock::self( mAddressBook ); } + + private: + KABC::AddressBook *mAddressBook; +}; + +class DeleteCommand : public Command +{ + public: + DeleteCommand( KABC::AddressBook *addressBook, const QStringList &uidList ); + + virtual QString name() const; + virtual void unexecute(); + virtual void execute(); + + private: + KABC::Addressee::List mAddresseeList; + QStringList mUIDList; +}; + +class PasteCommand : public Command +{ + public: + PasteCommand( KAB::Core *core, + const KABC::Addressee::List &addressees ); + + virtual QString name() const; + virtual void unexecute(); + virtual void execute(); + + private: + KABC::Addressee::List mAddresseeList; + KAB::Core *mCore; +}; + +class CutCommand : public Command +{ + public: + CutCommand( KABC::AddressBook *addressBook, const QStringList &uidList ); + + virtual QString name() const; + virtual void unexecute(); + virtual void execute(); + + private: + KABC::Addressee::List mAddresseeList; + QStringList mUIDList; + QString mClipText; + QString mOldText; +}; + +class NewCommand : public Command +{ + public: + NewCommand( KABC::AddressBook *addressBook, + const KABC::Addressee::List &addressees ); + + virtual QString name() const; + virtual void unexecute(); + virtual void execute(); + + private: + KABC::Addressee::List mAddresseeList; +}; + +class EditCommand : public Command +{ + public: + EditCommand( KABC::AddressBook *addressBook, const KABC::Addressee &oldAddressee, + const KABC::Addressee &newAddressee ); + + virtual QString name() const; + virtual void unexecute(); + virtual void execute(); + + private: + KABC::Addressee mOldAddressee; + KABC::Addressee mNewAddressee; +}; + +#endif diff --git a/kaddressbook/viewconfigurefieldspage.cpp b/kaddressbook/viewconfigurefieldspage.cpp new file mode 100644 index 000000000..fd50d92fe --- /dev/null +++ b/kaddressbook/viewconfigurefieldspage.cpp @@ -0,0 +1,285 @@ +/* + This file is part of KAddressBook. + Copyright (c) 2002 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 <qlabel.h> +#include <qlayout.h> +#include <qlistbox.h> +#include <qpushbutton.h> +#include <qtoolbutton.h> +#include <qapplication.h> + +#include <kcombobox.h> +#include <kdebug.h> +#include <kdialog.h> +#include <kiconloader.h> +#include <klocale.h> + +#include "viewconfigurefieldspage.h" + +class FieldItem : public QListBoxText +{ + public: + FieldItem( QListBox *parent, KABC::Field *field ) + : QListBoxText( parent, field->label() ), mField( field ) {} + + FieldItem( QListBox *parent, KABC::Field *field, int index ) + : QListBoxText( parent, field->label(), parent->item( index ) ), + mField( field ) {} + + KABC::Field *field() { return mField; } + + private: + KABC::Field *mField; +}; + + +ViewConfigureFieldsPage::ViewConfigureFieldsPage( KABC::AddressBook *ab, + QWidget *parent, + const char *name ) + : QWidget( parent, name ), mAddressBook( ab ) +{ + initGUI(); +} + +void ViewConfigureFieldsPage::restoreSettings( KConfig *config ) +{ + KABC::Field::List fields = KABC::Field::restoreFields( config, "KABCFields" ); + + if ( fields.isEmpty() ) + fields = KABC::Field::defaultFields(); + + KABC::Field::List::ConstIterator it; + for ( it = fields.begin(); it != fields.end(); ++it ) + new FieldItem( mSelectedBox, *it ); + + slotShowFields( mCategoryCombo->currentItem() ); +} + +void ViewConfigureFieldsPage::saveSettings( KConfig *config ) +{ + KABC::Field::List fields; + + for ( uint i = 0; i < mSelectedBox->count(); ++i ) { + FieldItem *fieldItem = static_cast<FieldItem *>( mSelectedBox->item( i ) ); + fields.append( fieldItem->field() ); + } + + KABC::Field::saveFields( config, "KABCFields", fields ); +} + +void ViewConfigureFieldsPage::slotShowFields( int index ) +{ + int currentPos = mUnSelectedBox->currentItem(); + mUnSelectedBox->clear(); + + int category; + if ( index == 0 ) category = KABC::Field::All; + else category = 1 << ( index - 1 ); + + KABC::Field::List allFields = mAddressBook->fields( category ); + + KABC::Field::List::ConstIterator it; + for ( it = allFields.begin(); it != allFields.end(); ++it ) { + QListBoxItem *item = mSelectedBox->firstItem(); + while( item ) { + FieldItem *fieldItem = static_cast<FieldItem *>( item ); + if ( (*it)->equals( fieldItem->field() ) ) + break; + item = item->next(); + } + + if ( !item ) + new FieldItem( mUnSelectedBox, *it ); + } + + mUnSelectedBox->sort(); + mUnSelectedBox->setCurrentItem( currentPos ); +} + +void ViewConfigureFieldsPage::slotSelect() +{ + // insert selected items in the unselected list to the selected list, + // directoy under the current item if selected, or at the bottonm if + // nothing is selected in the selected list + int where = mSelectedBox->currentItem(); + if ( !(where > -1 && mSelectedBox->item( where )->isSelected()) ) + where = mSelectedBox->count() - 1; + + for ( uint i = 0; i < mUnSelectedBox->count(); ++i ) + if ( mUnSelectedBox->isSelected( mUnSelectedBox->item( i ) ) ) { + FieldItem *fieldItem = static_cast<FieldItem *>( mUnSelectedBox->item( i ) ); + new FieldItem( mSelectedBox, fieldItem->field(), where ); + where++; + } + + slotShowFields( mCategoryCombo->currentItem() ); +} + +void ViewConfigureFieldsPage::slotUnSelect() +{ + for ( uint i = 0; i < mSelectedBox->count(); ++i ) + if ( mSelectedBox->isSelected( mSelectedBox->item( i ) ) ) { + mSelectedBox->removeItem( i ); + --i; + } + + slotShowFields( mCategoryCombo->currentItem() ); +} + +void ViewConfigureFieldsPage::slotButtonsEnabled() +{ + bool state = false; + // add button: enabled if any items are selected in the unselected list + for ( uint i = 0; i < mUnSelectedBox->count(); ++i ) + if ( mUnSelectedBox->item( i )->isSelected() ) { + state = true; + break; + } + mAddButton->setEnabled( state ); + + int j = mSelectedBox->currentItem(); + state = ( j > -1 && mSelectedBox->isSelected( j ) ); + + // up button: enabled if there is a current item > 0 and that is selected + mUpButton->setEnabled( ( j > 0 && state ) ); + + // down button: enabled if there is a current item < count - 2 and that is selected + mDownButton->setEnabled( ( j > -1 && j < (int)mSelectedBox->count() - 1 && state ) ); + + // remove button: enabled if any items are selected in the selected list + state = false; + for ( uint i = 0; i < mSelectedBox->count(); ++i ) + if ( mSelectedBox->item( i )->isSelected() ) { + state = true; + break; + } + mRemoveButton->setEnabled( state ); +} + +void ViewConfigureFieldsPage::slotMoveUp() +{ + int i = mSelectedBox->currentItem(); + if ( i > 0 ) { + QListBoxItem *item = mSelectedBox->item( i ); + mSelectedBox->takeItem( item ); + mSelectedBox->insertItem( item, i - 1 ); + mSelectedBox->setCurrentItem( item ); + mSelectedBox->setSelected( i - 1, true ); + } +} + +void ViewConfigureFieldsPage::slotMoveDown() +{ + int i = mSelectedBox->currentItem(); + if ( i > -1 && i < (int)mSelectedBox->count() - 1 ) { + QListBoxItem *item = mSelectedBox->item( i ); + mSelectedBox->takeItem( item ); + mSelectedBox->insertItem( item, i + 1 ); + mSelectedBox->setCurrentItem( item ); + mSelectedBox->setSelected( i + 1, true ); + } +} + +void ViewConfigureFieldsPage::initGUI() +{ + setCaption( i18n("Select Fields to Display") ); + + QGridLayout *gl = new QGridLayout( this , 6, 4, 0, KDialog::spacingHint() ); + + mCategoryCombo = new KComboBox( false, this ); + mCategoryCombo->insertItem( KABC::Field::categoryLabel( KABC::Field::All ) ); + mCategoryCombo->insertItem( KABC::Field::categoryLabel( KABC::Field::Frequent ) ); + mCategoryCombo->insertItem( KABC::Field::categoryLabel( KABC::Field::Address ) ); + mCategoryCombo->insertItem( KABC::Field::categoryLabel( KABC::Field::Email ) ); + mCategoryCombo->insertItem( KABC::Field::categoryLabel( KABC::Field::Personal ) ); + mCategoryCombo->insertItem( KABC::Field::categoryLabel( KABC::Field::Organization ) ); + mCategoryCombo->insertItem( KABC::Field::categoryLabel( KABC::Field::CustomCategory ) ); + connect( mCategoryCombo, SIGNAL( activated(int) ), SLOT( slotShowFields(int) ) ); + gl->addWidget( mCategoryCombo, 0, 0 ); + + QLabel *label = new QLabel( i18n( "&Selected fields:" ), this ); + gl->addWidget( label, 0, 2 ); + + mUnSelectedBox = new QListBox( this ); + mUnSelectedBox->setSelectionMode( QListBox::Extended ); + mUnSelectedBox->setMinimumHeight( 100 ); + gl->addWidget( mUnSelectedBox, 1, 0 ); + + mSelectedBox = new QListBox( this ); + mSelectedBox->setSelectionMode( QListBox::Extended ); + label->setBuddy( mSelectedBox ); + gl->addWidget( mSelectedBox, 1, 2 ); + + QBoxLayout *vb1 = new QBoxLayout( QBoxLayout::TopToBottom, KDialog::spacingHint() ); + vb1->addStretch(); + + mAddButton = new QToolButton( this ); + mAddButton->setIconSet( QApplication::reverseLayout() ? SmallIconSet( "1leftarrow" ) : SmallIconSet( "1rightarrow" ) ); + connect( mAddButton, SIGNAL( clicked() ), SLOT( slotSelect() ) ); + vb1->addWidget( mAddButton ); + + mRemoveButton = new QToolButton( this ); + mRemoveButton->setIconSet( QApplication::reverseLayout() ? SmallIconSet( "1rightarrow" ) : SmallIconSet( "1leftarrow" ) ); + connect( mRemoveButton, SIGNAL( clicked() ), SLOT( slotUnSelect() ) ); + vb1->addWidget( mRemoveButton ); + + vb1->addStretch(); + gl->addLayout( vb1, 1, 1 ); + + QBoxLayout *vb2 = new QBoxLayout( QBoxLayout::TopToBottom, KDialog::spacingHint() ); + vb2->addStretch(); + + mUpButton = new QToolButton( this ); + mUpButton->setIconSet( SmallIconSet( "1uparrow" ) ); + connect( mUpButton, SIGNAL( clicked() ), SLOT( slotMoveUp() ) ); + vb2->addWidget( mUpButton ); + + mDownButton = new QToolButton( this ); + mDownButton->setIconSet( SmallIconSet( "1downarrow" ) ); + connect( mDownButton, SIGNAL( clicked() ), SLOT( slotMoveDown() ) ); + vb2->addWidget( mDownButton ); + + vb2->addStretch(); + gl->addLayout( vb2, 1, 3 ); + + QSize sizeHint = mUnSelectedBox->sizeHint(); + + // make sure we fill the list with all items, so that we can + // get the maxItemWidth we need to not truncate the view + slotShowFields( 0 ); + + sizeHint = sizeHint.expandedTo( mSelectedBox->sizeHint() ); + sizeHint.setWidth( mUnSelectedBox->maxItemWidth() ); + mUnSelectedBox->setMinimumSize( sizeHint ); + mSelectedBox->setMinimumSize( sizeHint ); + + gl->activate(); + + connect( mUnSelectedBox, SIGNAL( selectionChanged() ), SLOT( slotButtonsEnabled() ) ); + connect( mSelectedBox, SIGNAL( selectionChanged() ), SLOT( slotButtonsEnabled() ) ); + connect( mSelectedBox, SIGNAL( currentChanged( QListBoxItem * ) ), SLOT( slotButtonsEnabled() ) ); + + slotButtonsEnabled(); +} + +#include "viewconfigurefieldspage.moc" diff --git a/kaddressbook/viewconfigurefieldspage.h b/kaddressbook/viewconfigurefieldspage.h new file mode 100644 index 000000000..27b421c6f --- /dev/null +++ b/kaddressbook/viewconfigurefieldspage.h @@ -0,0 +1,72 @@ +/* + This file is part of KAddressBook. + Copyright (c) 2002 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 VIEWCONFIGUREFIELDSPAGE_H +#define VIEWCONFIGUREFIELDSPAGE_H + +#include <qwidget.h> + +#include <kabc/field.h> +#include <kabc/addressbook.h> + +class KComboBox; +class QListBox; +class QListBoxItem; +class QPushButton; +class QToolButton; + +class ViewConfigureFieldsPage : public QWidget +{ + Q_OBJECT + + public: + ViewConfigureFieldsPage( KABC::AddressBook *ab, QWidget *parent = 0, + const char *name = 0 ); + + void restoreSettings( KConfig* ); + void saveSettings( KConfig* ); + + public slots: + void slotSelect(); + void slotUnSelect(); + void slotMoveUp(); + void slotMoveDown(); + + void slotShowFields( int ); + void slotButtonsEnabled(); + + private: + void initGUI(); + + KComboBox *mCategoryCombo; + QListBox *mSelectedBox; + QListBox *mUnSelectedBox; + QToolButton *mAddButton; + QToolButton *mRemoveButton; + QToolButton *mUpButton; + QToolButton *mDownButton; + + KABC::AddressBook *mAddressBook; +}; + +#endif diff --git a/kaddressbook/viewconfigurefilterpage.cpp b/kaddressbook/viewconfigurefilterpage.cpp new file mode 100644 index 000000000..2db6e4923 --- /dev/null +++ b/kaddressbook/viewconfigurefilterpage.cpp @@ -0,0 +1,111 @@ +/* + This file is part of KAddressBook. + Copyright (c) 2002 Mike Pilone <mpilone@slac.com> + + 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 <qbuttongroup.h> +#include <qlabel.h> +#include <qlayout.h> +#include <qradiobutton.h> + +#include <kconfig.h> +#include <kcombobox.h> +#include <kdialog.h> +#include <klocale.h> + +#include "viewconfigurefilterpage.h" +#include "filter.h" + +ViewConfigureFilterPage::ViewConfigureFilterPage( QWidget *parent, + const char *name ) + : QWidget( parent, name ) +{ + QBoxLayout *topLayout = new QVBoxLayout( this, 0, KDialog::spacingHint() ); + + mFilterGroup = new QButtonGroup(); + connect( mFilterGroup, SIGNAL( clicked( int ) ), SLOT( buttonClicked( int ) ) ); + + QLabel *label = new QLabel( i18n( "The default filter will be activated whenever" + " this view is displayed. This feature allows you to configure views that only" + " interact with certain types of information based on the filter. Once the view" + " is activated, the filter can be changed at anytime." ), this ); + label->setAlignment( Qt::AlignLeft | Qt::AlignTop | Qt::WordBreak ); + topLayout->addWidget( label ); + + QWidget *spacer = new QWidget( this ); + spacer->setMinimumHeight( 5 ); + topLayout->addWidget( spacer ); + + QRadioButton *button = new QRadioButton( i18n( "No default filter" ), this ); + mFilterGroup->insert( button ); + topLayout->addWidget( button ); + + button = new QRadioButton( i18n( "Use last active filter" ), this ); + mFilterGroup->insert( button ); + topLayout->addWidget( button ); + + QBoxLayout *comboLayout = new QHBoxLayout(); + topLayout->addLayout( comboLayout ); + button = new QRadioButton( i18n( "Use filter:" ), this ); + mFilterGroup->insert( button ); + comboLayout->addWidget( button ); + + mFilterCombo = new KComboBox( this ); + comboLayout->addWidget( mFilterCombo ); + + topLayout->addStretch( 100 ); +} + +ViewConfigureFilterPage::~ViewConfigureFilterPage() +{ + delete mFilterGroup; +} + +void ViewConfigureFilterPage::restoreSettings( KConfig *config ) +{ + mFilterCombo->clear(); + + // Load the filter combo + const Filter::List list = Filter::restore( config, "Filter" ); + Filter::List::ConstIterator it; + for ( it = list.begin(); it != list.end(); ++it ) + mFilterCombo->insertItem( (*it).name() ); + + int id = config->readNumEntry( "DefaultFilterType", 1 ); + mFilterGroup->setButton( id ); + buttonClicked( id ); + + if ( id == 2 ) // has default filter + mFilterCombo->setCurrentText( config->readEntry( "DefaultFilterName" ) ); +} + +void ViewConfigureFilterPage::saveSettings( KConfig *config ) +{ + config->writeEntry( "DefaultFilterName", mFilterCombo->currentText() ); + config->writeEntry( "DefaultFilterType", mFilterGroup->id( mFilterGroup->selected() ) ); +} + +void ViewConfigureFilterPage::buttonClicked( int id ) +{ + mFilterCombo->setEnabled( id == 2 ); +} + +#include "viewconfigurefilterpage.moc" diff --git a/kaddressbook/viewconfigurefilterpage.h b/kaddressbook/viewconfigurefilterpage.h new file mode 100644 index 000000000..bc50b3096 --- /dev/null +++ b/kaddressbook/viewconfigurefilterpage.h @@ -0,0 +1,53 @@ +/* + This file is part of KAddressBook. + Copyright (c) 2002 Mike Pilone <mpilone@slac.com> + + 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 VIEWCONFIGUREFILTERPAGE +#define VIEWCONFIGUREFILTERPAGE + +#include <qwidget.h> + +class QButtonGroup; + +class KComboBox; +class KConfig; + +class ViewConfigureFilterPage : public QWidget +{ + Q_OBJECT + + public: + ViewConfigureFilterPage( QWidget *parent, const char *name = 0 ); + ~ViewConfigureFilterPage(); + + void restoreSettings( KConfig* ); + void saveSettings( KConfig* ); + + protected slots: + void buttonClicked( int id ); + + private: + KComboBox *mFilterCombo; + QButtonGroup *mFilterGroup; +}; + +#endif diff --git a/kaddressbook/viewconfigurewidget.cpp b/kaddressbook/viewconfigurewidget.cpp new file mode 100644 index 000000000..f8e883f0b --- /dev/null +++ b/kaddressbook/viewconfigurewidget.cpp @@ -0,0 +1,116 @@ +/* + This file is part of KAddressBook. + Copyright (c) 2002 Mike Pilone <mpilone@slac.com> + + 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 <qlayout.h> +#include <qvbox.h> + +#include <kapplication.h> +#include <kconfig.h> +#include <kdebug.h> +#include <kglobal.h> +#include <kiconloader.h> +#include <klocale.h> + +#include "viewconfigurefieldspage.h" +#include "viewconfigurefilterpage.h" +#include "viewmanager.h" + +#include "viewconfigurewidget.h" + +ViewConfigureWidget::ViewConfigureWidget( KABC::AddressBook *ab, QWidget *parent, + const char *name ) + : KAB::ConfigureWidget( ab, parent, name ) +{ + QVBoxLayout *topLayout = new QVBoxLayout( this ); + + mMainWidget = new KJanusWidget( this, "JanusWidget", KJanusWidget::IconList ); + topLayout->addWidget( mMainWidget ); + + // Add the first page, the attributes + QVBox *page = addPage( i18n( "Fields" ), QString::null, + KGlobal::iconLoader()->loadIcon( "view_detailed", + KIcon::Panel ) ); + + // Add the select fields page + mFieldsPage = new ViewConfigureFieldsPage( addressBook(), page ); + + // Add the second page, the filter selection + page = addPage( i18n( "Default Filter" ), QString::null, + KGlobal::iconLoader()->loadIcon( "filter", + KIcon::Panel ) ); + + mFilterPage = new ViewConfigureFilterPage( page ); +} + +ViewConfigureWidget::~ViewConfigureWidget() +{ +} + +void ViewConfigureWidget::restoreSettings( KConfig *config ) +{ + mFieldsPage->restoreSettings( config ); + mFilterPage->restoreSettings( config ); +} + +void ViewConfigureWidget::saveSettings( KConfig *config ) +{ + mFieldsPage->saveSettings( config ); + mFilterPage->saveSettings( config ); +} + +QVBox *ViewConfigureWidget::addPage( const QString &item, const QString &header, + const QPixmap &pixmap ) +{ + return mMainWidget->addVBoxPage( item, header, pixmap ); +} + +ViewConfigureDialog::ViewConfigureDialog( ViewConfigureWidget *wdg, const QString &viewName, + QWidget *parent, const char *name ) + : KDialogBase( Swallow, i18n( "Modify View: " ) + viewName, Help | Ok | Cancel, + Ok, parent, name, true, true ), mConfigWidget( wdg ) +{ + setMainWidget( mConfigWidget ); + + resize( 600, 300 ); +} + +ViewConfigureDialog::~ViewConfigureDialog() +{ +} + +void ViewConfigureDialog::restoreSettings( KConfig *config ) +{ + mConfigWidget->restoreSettings( config ); +} + +void ViewConfigureDialog::saveSettings( KConfig *config ) +{ + mConfigWidget->saveSettings( config ); +} + +void ViewConfigureDialog::slotHelp() +{ + kapp->invokeHelp( "using-views" ); +} + +#include "viewconfigurewidget.moc" diff --git a/kaddressbook/viewconfigurewidget.h b/kaddressbook/viewconfigurewidget.h new file mode 100644 index 000000000..f5511b7e1 --- /dev/null +++ b/kaddressbook/viewconfigurewidget.h @@ -0,0 +1,106 @@ +/* + This file is part of KAddressBook. + Copyright (c) 2002 Mike Pilone <mpilone@slac.com> + + 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 VIEWCONFIGUREWIDGET_H +#define VIEWCONFIGUREWIDGET_H + +#include <kdialogbase.h> +#include <kdepimmacros.h> +#include <qpixmap.h> + +#include "configurewidget.h" + +class KJanusWidget; + +class QString; +class QVBox; + +class ViewConfigureFieldsPage; +class ViewConfigureFilterPage; + +/** + This widget is the base class for all view configuration widgets. The + author of a view may wish to inherit from this widget and add config pages + that add custom config options. The default implementation of this widget + is to show a page with the select fields widget. For simple views this may + be sufficient. +*/ +class KDE_EXPORT ViewConfigureWidget : public KAB::ConfigureWidget +{ + Q_OBJECT + + public: + ViewConfigureWidget( KABC::AddressBook *ab, QWidget *parent, const char *name = 0 ); + virtual ~ViewConfigureWidget(); + + /** + Reads the configuration from the config object and sets the values + in the GUI. If this method is overloaded, be sure to call the base + class's method. + + Do not change the group of the config object in this method. + */ + virtual void restoreSettings( KConfig *config ); + + /** + Writes the configuration from the GUI to the config object. If this + method is overloaded, be sure to call the base class's method. + + Do not change the group of the config object in this method. + */ + virtual void saveSettings( KConfig *config ); + + + /** + Use this method to add new pages to the widget. + */ + QVBox *addPage( const QString &item, const QString &header = QString::null, + const QPixmap &pixmap = QPixmap() ); + + private: + KJanusWidget *mMainWidget; + + ViewConfigureFieldsPage *mFieldsPage; + ViewConfigureFilterPage *mFilterPage; +}; + +class ViewConfigureDialog : public KDialogBase +{ + Q_OBJECT + + public: + ViewConfigureDialog( ViewConfigureWidget *wdg, const QString &viewName, + QWidget *parent, const char *name = 0 ); + ~ViewConfigureDialog(); + + void restoreSettings( KConfig* ); + void saveSettings( KConfig* ); + + protected slots: + void slotHelp(); + + private: + ViewConfigureWidget *mConfigWidget; +}; + +#endif diff --git a/kaddressbook/viewmanager.cpp b/kaddressbook/viewmanager.cpp new file mode 100644 index 000000000..9d2f632ed --- /dev/null +++ b/kaddressbook/viewmanager.cpp @@ -0,0 +1,604 @@ +/* + This file is part of KAddressBook. + Copyright (c) 2002 Mike Pilone <mpilone@slac.com> + + 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 <qlayout.h> +#include <qwidgetstack.h> + +#include <libkdepim/kvcarddrag.h> +#include <kabc/addressbook.h> +#include <kabc/vcardconverter.h> +#include <kactionclasses.h> +#include <kconfig.h> +#include <kdebug.h> +#include <kdeversion.h> +#include <kiconloader.h> +#include <klocale.h> +#include <kmessagebox.h> +#include <kmultipledrag.h> +#include <ktempdir.h> +#include <ktrader.h> +#include <kurldrag.h> + +#include "addviewdialog.h" +#include "addresseeutil.h" +#include "core.h" +#include "filtereditdialog.h" +#include "filterselectionwidget.h" +#include "kabprefs.h" + +#include "viewmanager.h" + +ViewManager::ViewManager( KAB::Core *core, QWidget *parent, const char *name ) + : QWidget( parent, name ), mCore( core ), mActiveView( 0 ), + mFilterSelectionWidget( 0 ) +{ + initGUI(); + initActions(); + + mViewDict.setAutoDelete( true ); + + createViewFactories(); +} + +ViewManager::~ViewManager() +{ + unloadViews(); + mViewFactoryDict.clear(); +} + +void ViewManager::restoreSettings() +{ + mViewNameList = KABPrefs::instance()->viewNames(); + QString activeViewName = KABPrefs::instance()->currentView(); + + mActionSelectView->setItems( mViewNameList ); + + // Filter + mFilterList = Filter::restore( mCore->config(), "Filter" ); + mFilterSelectionWidget->setItems( filterNames() ); + mFilterSelectionWidget->setCurrentItem( KABPrefs::instance()->currentFilter() ); + + // Tell the views to reread their config, since they may have + // been modified by global settings + QDictIterator<KAddressBookView> it( mViewDict ); + for ( it.toFirst(); it.current(); ++it ) { + KConfigGroupSaver saver( mCore->config(), it.currentKey() ); + it.current()->readConfig( mCore->config() ); + } + + setActiveView( activeViewName ); + + mActionDeleteView->setEnabled( mViewNameList.count() > 1 ); +} + +void ViewManager::saveSettings() +{ + QDictIterator<KAddressBookView> it( mViewDict ); + for ( it.toFirst(); it.current(); ++it ) { + KConfigGroupSaver saver( mCore->config(), it.currentKey() ); + (*it)->writeConfig( mCore->config() ); + } + + Filter::save( mCore->config(), "Filter", mFilterList ); + KABPrefs::instance()->setCurrentFilter( mFilterSelectionWidget->currentItem() ); + + // write the view name list + KABPrefs::instance()->setViewNames( mViewNameList ); + + if ( mActiveView ) + KABPrefs::instance()->setCurrentView( mActiveView->caption() ); +} + +QStringList ViewManager::selectedUids() const +{ + if ( mActiveView ) { + return mActiveView->selectedUids(); + } else + return QStringList(); +} + +QStringList ViewManager::selectedEmails() const +{ + if ( mActiveView ) + return mActiveView->selectedEmails(); + else + return QStringList(); +} + +KABC::Addressee::List ViewManager::selectedAddressees() const +{ + KABC::Addressee::List list; + + const QStringList uids = selectedUids(); + QStringList::ConstIterator it; + for ( it = uids.begin(); it != uids.end(); ++it ) { + KABC::Addressee addr = mCore->addressBook()->findByUid( *it ); + if ( !addr.isEmpty() ) + list.append( addr ); + } + + return list; +} + +void ViewManager::setFilterSelectionWidget( FilterSelectionWidget *wdg ) +{ + mFilterSelectionWidget = wdg; +} + +KABC::Field *ViewManager::currentSortField() const +{ + if ( mActiveView ) + return mActiveView->sortField(); + else + return 0; +} + +KABC::Field::List ViewManager::viewFields() const +{ +/* + if ( mActiveView ) + return mActiveView->fields(); + else +*/ + return KABC::Field::List(); +} + +void ViewManager::setSelected( const QString &uid, bool selected ) +{ + if ( mActiveView ) + mActiveView->setSelected( uid, selected ); +} + +void ViewManager::setFirstSelected( bool selected ) +{ + if ( mActiveView ) + mActiveView->setFirstSelected( selected ); +} + +void ViewManager::unloadViews() +{ + mViewDict.clear(); + mActiveView = 0; +} + +void ViewManager::setActiveView( const QString &name ) +{ + KAddressBookView *view = 0; + + // Check that this isn't the same as the current active view + if ( mActiveView && ( mActiveView->caption() == name ) ) + return; + + // At this point we know the view that should be active is not + // currently active. We will try to find the new on in the list. If + // we can't find it, it means it hasn't been instantiated, so we will + // create it on demand. + + view = mViewDict.find( name ); + + // Check if we found the view. If we didn't, then we need to create it + if ( view == 0 ) { + KConfig *config = mCore->config(); + KConfigGroupSaver saver( config, name ); + QString type = config->readEntry( "Type", "Table" ); + + kdDebug(5720) << "ViewManager::setActiveView: creating view - " << name << endl; + + ViewFactory *factory = mViewFactoryDict.find( type ); + if ( factory ) + view = factory->view( mCore, mViewWidgetStack ); + + if ( view ) { + view->setCaption( name ); + mViewDict.insert( name, view ); + mViewWidgetStack->addWidget( view ); + view->readConfig( config ); + + // The manager just relays the signals + connect( view, SIGNAL( selected( const QString& ) ), + SIGNAL( selected( const QString & ) ) ); + connect( view, SIGNAL( executed( const QString& ) ), + SIGNAL( executed( const QString& ) ) ); + connect( view, SIGNAL( modified() ), SIGNAL( modified() ) ); + connect( view, SIGNAL( dropped( QDropEvent* ) ), + SLOT( dropped( QDropEvent* ) ) ); + connect( view, SIGNAL( startDrag() ), SLOT( startDrag() ) ); + connect( view, SIGNAL( sortFieldChanged() ), SIGNAL( sortFieldChanged() ) ); + } + } + + // If we found or created the view, raise it and refresh it + if ( view ) { + mActiveView = view; + mViewWidgetStack->raiseWidget( view ); + // Set the proper filter in the view. By setting the combo + // box, the activated slot will be called, which will push + // the filter to the view and refresh it. + if ( view->defaultFilterType() == KAddressBookView::None ) { + mFilterSelectionWidget->setCurrentItem( 0 ); + setActiveFilter( 0 ); + } else if ( view->defaultFilterType() == KAddressBookView::Active ) { + setActiveFilter( mFilterSelectionWidget->currentItem() ); + } else { + uint pos = filterPosition( view->defaultFilterName() ); + mFilterSelectionWidget->setCurrentItem( pos ); + setActiveFilter( pos ); + } + + // Update the inc search widget to show the fields in the new active + // view. + mActiveView->refresh(); + + } else + kdDebug(5720) << "ViewManager::setActiveView: unable to find view\n"; +} + +void ViewManager::refreshView( const QString &uid ) +{ + if ( mActiveView ) + mActiveView->refresh( uid ); +} + +void ViewManager::editView() +{ + if ( !mActiveView ) + return; + + ViewFactory *factory = mViewFactoryDict.find( mActiveView->type() ); + ViewConfigureWidget *wdg = 0; + + if ( factory ) { + // Save the filters so the dialog has the latest set + Filter::save( mCore->config(), "Filter", mFilterList ); + + wdg = factory->configureWidget( mCore->addressBook(), 0 ); + } + + if ( wdg ) { + ViewConfigureDialog dlg( wdg, mActiveView->caption(), this ); + + KConfigGroupSaver saver( mCore->config(), mActiveView->caption() ); + dlg.restoreSettings( mCore->config() ); + + if ( dlg.exec() ) { + dlg.saveSettings( mCore->config() ); + mActiveView->readConfig( mCore->config() ); + // Set the proper filter in the view. By setting the combo + // box, the activated slot will be called, which will push + // the filter to the view and refresh it. + if ( mActiveView->defaultFilterType() == KAddressBookView::None ) { + mFilterSelectionWidget->setCurrentItem( 0 ); + setActiveFilter( 0 ); + } else if ( mActiveView->defaultFilterType() == KAddressBookView::Active ) { + setActiveFilter( mFilterSelectionWidget->currentItem() ); + } else { + uint pos = filterPosition( mActiveView->defaultFilterName() ); + mFilterSelectionWidget->setCurrentItem( pos ); + setActiveFilter( pos ); + } + + mActiveView->refresh(); + emit viewFieldsChanged(); + } + } +} + +void ViewManager::deleteView() +{ + QString text = i18n( "<qt>Are you sure that you want to delete the view <b>%1</b>?</qt>" ) + .arg( mActiveView->caption() ); + QString caption = i18n( "Confirm Delete" ); + + if ( KMessageBox::warningContinueCancel( this, text, caption, KGuiItem( i18n("&Delete"), "editdelete") ) == KMessageBox::Continue ) { + mViewNameList.remove( mActiveView->caption() ); + + // remove the view from the config file + KConfig *config = mCore->config(); + config->deleteGroup( mActiveView->caption() ); + + mViewDict.remove( mActiveView->caption() ); + mActiveView = 0; + + // we are in an invalid state now, but that should be fixed after + // we emit the signal + mActionSelectView->setItems( mViewNameList ); + if ( mViewNameList.count() > 0 ) { + mActionSelectView->setCurrentItem( 0 ); + setActiveView( mViewNameList[ 0 ] ); + } + mActionDeleteView->setEnabled( mViewNameList.count() > 1 ); + } +} + +void ViewManager::addView() +{ + AddViewDialog dialog( &mViewFactoryDict, this ); + + if ( dialog.exec() ) { + QString newName = dialog.viewName(); + QString type = dialog.viewType(); + + // Check for name conflicts + bool firstConflict = true; + int numTries = 1; + while ( mViewNameList.contains( newName ) > 0 ) { + if ( !firstConflict ) { + newName = newName.left( newName.length() - 4 ); + firstConflict = false; + } + + newName = QString( "%1 <%2>" ).arg( newName ).arg( numTries ); + numTries++; + } + + // Add the new one to the list + mViewNameList.append( newName ); + + // write the view to the config file, + KConfig *config = mCore->config(); + config->deleteGroup( newName ); + KConfigGroupSaver saver( config, newName ); + config->writeEntry( "Type", type ); + + // try to set the active view + mActionSelectView->setItems( mViewNameList ); + mActionSelectView->setCurrentItem( mViewNameList.findIndex( newName ) ); + setActiveView( newName ); + + editView(); + + mActionDeleteView->setEnabled( mViewNameList.count() > 1 ); + } +} + +void ViewManager::scrollUp() +{ + if ( mActiveView ) + mActiveView->scrollUp(); +} + +void ViewManager::scrollDown() +{ + if ( mActiveView ) + mActiveView->scrollDown(); +} + +void ViewManager::createViewFactories() +{ + const KTrader::OfferList plugins = KTrader::self()->query( "KAddressBook/View", + QString( "[X-KDE-KAddressBook-ViewPluginVersion] == %1" ).arg( KAB_VIEW_PLUGIN_VERSION ) ); + KTrader::OfferList::ConstIterator it; + for ( it = plugins.begin(); it != plugins.end(); ++it ) { + if ( !(*it)->hasServiceType( "KAddressBook/View" ) ) + continue; + + KLibFactory *factory = KLibLoader::self()->factory( (*it)->library().latin1() ); + + if ( !factory ) { + kdDebug(5720) << "ViewManager::createViewFactories(): Factory creation failed" << endl; + continue; + } + + ViewFactory *viewFactory = static_cast<ViewFactory*>( factory ); + + if ( !viewFactory ) { + kdDebug(5720) << "ViewManager::createViewFactories(): Cast failed" << endl; + continue; + } + + mViewFactoryDict.insert( viewFactory->type(), viewFactory ); + } +} + +void ViewManager::dropped( QDropEvent *e ) +{ + kdDebug(5720) << "ViewManager::dropped: got a drop event" << endl; + + // don't allow drops from our own drags + if ( e->source() == this ) + return; + + QString clipText, vcards; + KURL::List urls; + + if ( KURLDrag::decode( e, urls) ) { + KURL::List::ConstIterator it = urls.begin(); + int c = urls.count(); + if ( c > 1 ) { + QString questionString = i18n( "Import one contact into your addressbook?", "Import %n contacts into your addressbook?", c ); + if ( KMessageBox::questionYesNo( this, questionString, i18n( "Import Contacts?" ), i18n("Import"), i18n("Do Not Import") ) == KMessageBox::Yes ) { + for ( ; it != urls.end(); ++it ) + emit urlDropped( *it ); + } + } else if ( c == 1 ) + emit urlDropped( *it ); + } else if ( KVCardDrag::decode( e, vcards ) ) { + KABC::VCardConverter converter; + + const KABC::Addressee::List list = converter.parseVCards( vcards ); + KABC::Addressee::List::ConstIterator it; + for ( it = list.begin(); it != list.end(); ++it ) { + KABC::Addressee a = mCore->addressBook()->findByUid( (*it).uid() ); + if ( a.isEmpty() ) { // not yet in address book + mCore->addressBook()->insertAddressee( *it ); + emit modified(); + } + } + + mActiveView->refresh(); + } +} + +void ViewManager::startDrag() +{ + // Get the list of all the selected addressees + KABC::Addressee::List addrList; + const QStringList uidList = selectedUids(); + if ( uidList.isEmpty() ) + return; + + kdDebug(5720) << "ViewManager::startDrag: starting to drag" << endl; + + QStringList::ConstIterator it; + for ( it = uidList.begin(); it != uidList.end(); ++it ) + addrList.append( mCore->addressBook()->findByUid( *it ) ); + + KMultipleDrag *drag = new KMultipleDrag( this ); + + KABC::VCardConverter converter; + QString vcards = converter.createVCards( addrList ); + + // Best text representation is given by textdrag, so it must be first + drag->addDragObject( new QTextDrag( AddresseeUtil::addresseesToEmails( addrList ), this ) ); + drag->addDragObject( new KVCardDrag( vcards, this ) ); + + KTempDir tempDir; + // can't set tempDir to autoDelete, in case of dropping on the desktop, the copy is async... + if ( tempDir.status() == 0 ) { + QString fileName; + if ( addrList.count() == 1 ) + fileName = addrList[ 0 ].givenName() + "_" + addrList[ 0 ].familyName() + ".vcf"; + else + fileName = "contacts.vcf"; + + QFile tempFile( tempDir.name() + "/" + fileName ); + if ( tempFile.open( IO_WriteOnly ) ) { + tempFile.writeBlock( vcards.utf8() ); + tempFile.close(); + + KURLDrag *urlDrag = new KURLDrag( KURL( tempFile.name() ), this ); + drag->addDragObject( urlDrag ); + } + } + + drag->setPixmap( KGlobal::iconLoader()->loadIcon( "vcard", KIcon::Desktop ) ); + drag->dragCopy(); +} + +void ViewManager::setActiveFilter( int index ) +{ + Filter currentFilter; + + if ( ( index - 1 ) < 0 ) + currentFilter = Filter(); + else if ( ( index - 1 ) < 1 ) { + currentFilter = Filter(); + currentFilter.setMatchRule(Filter::NotMatching); + } + else + currentFilter = mFilterList[ index - 2 ]; + + // Check if we have a view. Since the filter combo is created before + // the view, this slot could be called before there is a valid view. + if ( mActiveView ) { + mActiveView->setFilter( currentFilter ); + mActiveView->refresh(); + emit selected( QString::null ); + } +} + +void ViewManager::configureFilters() +{ + FilterDialog dlg( this ); + + dlg.setFilters( mFilterList ); + + if ( dlg.exec() ) + mFilterList = dlg.filters(); + + uint pos = mFilterSelectionWidget->currentItem(); + mFilterSelectionWidget->setItems( filterNames() ); + mFilterSelectionWidget->setCurrentItem( pos ); + setActiveFilter( pos ); +} + +QStringList ViewManager::filterNames() const +{ + QStringList names( i18n( "None" ) ); + names.append( i18n( "Unfiled" ) ); + + Filter::List::ConstIterator it; + for ( it = mFilterList.begin(); it != mFilterList.end(); ++it ) + names.append( (*it).name() ); + + return names; +} + +int ViewManager::filterPosition( const QString &name ) const +{ + int pos = 0; + + Filter::List::ConstIterator it; + for ( it = mFilterList.begin(); it != mFilterList.end(); ++it, ++pos ) + if ( name == (*it).name() ) + return pos + 2; + + return 0; +} + +void ViewManager::initActions() +{ + mActionSelectView = new KSelectAction( i18n( "Select View" ), 0, mCore->actionCollection(), "select_view" ); +#if KDE_VERSION >= 309 + mActionSelectView->setMenuAccelsEnabled( false ); +#endif + connect( mActionSelectView, SIGNAL( activated( const QString& ) ), + SLOT( setActiveView( const QString& ) ) ); + + KAction *action; + + action = new KAction( i18n( "Modify View..." ), "configure", 0, this, + SLOT( editView() ), mCore->actionCollection(), + "view_modify" ); + action->setWhatsThis( i18n( "By pressing this button a dialog opens that allows you to modify the view of the addressbook. There you can add or remove fields that you want to be shown or hidden in the addressbook like the name for example." ) ); + + action = new KAction( i18n( "Add View..." ), "window_new", 0, this, + SLOT( addView() ), mCore->actionCollection(), + "view_add" ); + action->setWhatsThis( i18n( "You can add a new view by choosing one from the dialog that appears after pressing the button. You have to give the view a name, so that you can distinguish between the different views." ) ); + + mActionDeleteView = new KAction( i18n( "Delete View" ), "view_remove", 0, + this, SLOT( deleteView() ), + mCore->actionCollection(), "view_delete" ); + mActionDeleteView->setWhatsThis( i18n( "By pressing this button you can delete the actual view, which you have added before." ) ); + + action = new KAction( i18n( "Refresh View" ), "reload", 0, this, + SLOT( refreshView() ), mCore->actionCollection(), + "view_refresh" ); + action->setWhatsThis( i18n( "The view will be refreshed by pressing this button." ) ); + + action = new KAction( i18n( "Edit &Filters..." ), "filter", 0, this, + SLOT( configureFilters() ), mCore->actionCollection(), + "options_edit_filters" ); + action->setWhatsThis( i18n( "Edit the contact filters<p>You will be presented with a dialog, where you can add, remove and edit filters." ) ); +} + +void ViewManager::initGUI() +{ + QHBoxLayout *layout = new QHBoxLayout( this ); + mViewWidgetStack = new QWidgetStack( this ); + layout->addWidget( mViewWidgetStack ); +} + +#include "viewmanager.moc" diff --git a/kaddressbook/viewmanager.h b/kaddressbook/viewmanager.h new file mode 100644 index 000000000..b74f025ee --- /dev/null +++ b/kaddressbook/viewmanager.h @@ -0,0 +1,162 @@ +/* + This file is part of KAddressBook. + Copyright (c) 2002 Mike Pilone <mpilone@slac.com> + + 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 VIEWMANAGER_H +#define VIEWMANAGER_H + +#include <qdict.h> +#include <qwidget.h> +#include <kaddressbookview.h> + +class QDropEvent; +class QWidgetStack; + +class KAction; +class KSelectAction; + +class FilterSelectionWidget; + +namespace KAB { class Core; } +namespace KABC { class AddressBook; } + +/** + The view manager manages the views and everything related to them. The + manager will load the views at startup and display a view when told to + make one active. + + The view manager will also create and manage all dialogs directly related to + views (ie: AddView, ConfigureView, DeleteView, etc). + */ +class ViewManager : public QWidget +{ + Q_OBJECT + + public: + ViewManager( KAB::Core *core, QWidget *parent, const char *name = 0 ); + ~ViewManager(); + + void restoreSettings(); + void saveSettings(); + + void unloadViews(); + + QStringList selectedUids() const; + QStringList selectedEmails() const; + KABC::Addressee::List selectedAddressees() const; + + void setFilterSelectionWidget( FilterSelectionWidget *wdg ); + + KABC::Field *currentSortField() const; + KABC::Field::List viewFields() const; + + public slots: + void setSelected( const QString &uid = QString::null, bool selected = true ); + void setFirstSelected( bool selected = true ); + + void refreshView( const QString &uid = QString::null ); + void editView(); + void deleteView(); + void addView(); + + void scrollUp(); + void scrollDown(); + + protected slots: + /** + Called whenever the user drops something in the active view. + This method will try to decode what was dropped, and if it was + a valid addressee, add it to the addressbook. + */ + void dropped( QDropEvent* ); + + /** + Called whenever the user attempts to start a drag in the view. + This method will convert all the selected addressees into text (vcard) + and create a drag object. + */ + void startDrag(); + + signals: + /** + Emitted whenever the user selects an entry in the view. + */ + void selected( const QString &uid ); + + /** + Emitted whenever the user activates an entry in the view. + */ + void executed( const QString &uid ); + + /** + Emitted whenever the address book is modified in some way. + */ + void modified(); + + /** + Emitted whenever a url is dragged on a view. + */ + void urlDropped( const KURL& ); + + /** + Emitted whenever the sort field of a view has changed. + */ + void sortFieldChanged(); + + /** + Emitted whenever the view fields changed. + */ + void viewFieldsChanged(); + + private slots: + void setActiveView( const QString &name ); + void setActiveFilter( int index ); + void configureFilters(); + + private: + void createViewFactories(); + QStringList filterNames() const; + int filterPosition( const QString &name ) const; + QStringList viewNames() const; + int viewPosition( const QString &name ) const; + void initActions(); + void initGUI(); + + KAB::Core *mCore; + + Filter mCurrentFilter; + Filter::List mFilterList; + + QDict<KAddressBookView> mViewDict; + QDict<ViewFactory> mViewFactoryDict; + QStringList mViewNameList; + + QWidgetStack *mViewWidgetStack; + KAddressBookView *mActiveView; + + KAction *mActionDeleteView; + KSelectAction *mActionSelectView; + + FilterSelectionWidget *mFilterSelectionWidget; +}; + +#endif diff --git a/kaddressbook/views/Makefile.am b/kaddressbook/views/Makefile.am new file mode 100644 index 000000000..39db0f589 --- /dev/null +++ b/kaddressbook/views/Makefile.am @@ -0,0 +1,38 @@ +INCLUDES = -I$(top_srcdir) -I$(top_builddir)/kaddressbook/common \ + -I$(top_srcdir)/kaddressbook/common \ + -I$(top_srcdir)/kaddressbook/interfaces \ + -I$(top_srcdir)/kaddressbook $(all_includes) + +kde_module_LTLIBRARIES = libkaddrbk_cardview.la libkaddrbk_iconview.la \ + libkaddrbk_tableview.la + +XXLIBS = $(top_builddir)/kaddressbook/libkaddressbook.la + +libkaddrbk_cardview_la_SOURCES = cardview.cpp colorlistbox.cpp \ + configurecardviewdialog.cpp \ + kaddressbookcardview.cpp +libkaddrbk_cardview_la_LDFLAGS = -module $(KDE_PLUGIN) $(KDE_RPATH) $(all_libraries) -no-undefined +libkaddrbk_cardview_la_LIBADD = $(XXLIBS) + +libkaddrbk_iconview_la_SOURCES = kaddressbookiconview.cpp +libkaddrbk_iconview_la_LDFLAGS = -module $(KDE_PLUGIN) $(KDE_RPATH) $(all_libraries) -no-undefined +libkaddrbk_iconview_la_LIBADD = $(XXLIBS) + +libkaddrbk_tableview_la_SOURCES = configuretableviewdialog.cpp \ + contactlistview.cpp \ + kaddressbooktableview.cpp +libkaddrbk_tableview_la_LDFLAGS = -module $(KDE_PLUGIN) $(KDE_RPATH) $(all_libraries) -no-undefined +libkaddrbk_tableview_la_LIBADD = $(XXLIBS) + +noinst_HEADERS = cardview.h colorlistbox.h configurecardviewdialog.h \ + configuretableviewdialog.h contactlistview.h \ + kaddressbookcardview.h kaddressbookiconview.h \ + kaddressbooktableview.h + +METASOURCES = AUTO + +servicedir = $(kde_servicesdir)/kaddressbook +service_DATA = cardview.desktop iconview.desktop tableview.desktop + +kaddressbookiconview.lo kaddressbooktableview.lo kaddressbookcardview.lo: ../common/kabprefs_base.h + diff --git a/kaddressbook/views/cardview.cpp b/kaddressbook/views/cardview.cpp new file mode 100644 index 000000000..82e987794 --- /dev/null +++ b/kaddressbook/views/cardview.cpp @@ -0,0 +1,1563 @@ +/* + This file is part of KAddressBook. + Copyright (c) 2002 Mike Pilone <mpilone@slac.com> + + 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 <limits.h> + +#include <qcursor.h> +#include <qdatetime.h> +#include <qlabel.h> +#include <qpainter.h> +#include <qstyle.h> +#include <qtimer.h> +#include <qtooltip.h> + +#include <kdebug.h> +#include <kglobalsettings.h> + +#include "cardview.h" + +#define MIN_ITEM_WIDTH 80 + +class CardViewTip : public QLabel +{ + public: + CardViewTip( QWidget *parent = 0, const char *name = 0 ) + : QLabel( parent, name ) + { + setPalette( QToolTip::palette() ); + setFrameStyle( Panel | Plain ); + setMidLineWidth( 0 ); + setIndent( 1 ); + } + + ~CardViewTip() {}; + + protected: + void leaveEvent( QEvent* ) + { + hide(); + } +}; + +// +// Warning: make sure you use findRef() instead of find() to find an +// item! Only the pointer value is unique in the list. +// +class CardViewItemList : public QPtrList<CardViewItem> +{ + protected: + virtual int compareItems( QPtrCollection::Item item1, + QPtrCollection::Item item2 ) + { + CardViewItem *cItem1 = (CardViewItem*)item1; + CardViewItem *cItem2 = (CardViewItem*)item2; + + if ( cItem1 == cItem2 ) + return 0; + + if ( (cItem1 == 0) || (cItem2 == 0) ) + return cItem1 ? -1 : 1; + + if ( cItem1->caption() < cItem2->caption() ) + return -1; + else if ( cItem1->caption() > cItem2->caption() ) + return 1; + + return 0; + } +}; + +class CardViewSeparator +{ + friend class CardView; + + public: + CardViewSeparator( CardView *view ) + : mView( view ) + { + mRect = QRect( 0, 0, view->separatorWidth(), 0 ); + } + + ~CardViewSeparator() {} + + void paintSeparator( QPainter *p, QColorGroup &cg ) + { + p->fillRect( 0, 0, mRect.width(), mRect.height(), + cg.brush(QColorGroup::Button) ); + } + + void repaintSeparator() + { + mView->repaintContents( mRect ); + } + + private: + CardView *mView; + QRect mRect; +}; + +class CardViewPrivate +{ + public: + CardViewPrivate() + : mSelectionMode( CardView::Multi ), + mDrawCardBorder( true ), + mDrawFieldLabels( true ), + mDrawSeparators( true), + mSepWidth( 2 ), + mShowEmptyFields( false ), + mLayoutDirty( true ), + mLastClickOnItem( false ), + mItemMargin( 0 ), + mItemSpacing( 10 ), + mItemWidth( 200 ), + mMaxFieldLines( INT_MAX ), + mCurrentItem( 0L ), + mLastClickPos( QPoint(0, 0) ), + mRubberBandAnchor( 0 ), + mCompText( QString::null ) + {}; + + CardViewItemList mItemList; + QPtrList<CardViewSeparator> mSeparatorList; + QFontMetrics *mFm; + QFontMetrics *mBFm; + QFont mHeaderFont; + CardView::SelectionMode mSelectionMode; + bool mDrawCardBorder; + bool mDrawFieldLabels; + bool mDrawSeparators; + int mSepWidth; + bool mShowEmptyFields; + bool mLayoutDirty; + bool mLastClickOnItem; + uint mItemMargin; // internal margin in items + uint mItemSpacing; // spacing between items, column seperators and border + int mItemWidth; // width of all items + uint mMaxFieldLines; // Max lines to dispaly pr field + CardViewItem *mCurrentItem; + QPoint mLastClickPos; + QTimer *mTimer; // times out if mouse rests for more than 500 msecs + CardViewTip *mTip; // passed to the item under a resting cursor to display full text + bool mOnSeparator; // set/reset on mouse movement + // for resizing by dragging the separators + int mResizeAnchor; // uint, ulong? the mouse down separator left + int mRubberBandAnchor; // for erasing rubber bands + // data used for resizing. + // as they are beeded by each mouse move while resizing, we store them here, + // saving 8 calculations in each mouse move. + int mColspace; // amount of space between items pr column + uint mFirst; // the first col to anchor at for painting rubber bands + int mFirstX; // X position of first in pixel + int mPressed; // the colummn that was pressed on at resizing start + int mSpan; // pressed - first + // key completion + QString mCompText; // current completion string + QDateTime mCompUpdated; // ...was updated at this time +}; + +class CardViewItemPrivate +{ + public: + CardViewItemPrivate() {} + + QString mCaption; + QPtrList< CardViewItem::Field > mFieldList; + bool mSelected; + int x; // horizontal position, set by the view + int y; // vertical position, set by the view + int maxLabelWidth; // the width of the widest label, according to the view font. + int hcache; // height cache +}; + + +CardViewItem::CardViewItem( CardView *parent, const QString &caption ) + : d( new CardViewItemPrivate() ), mView( parent ) +{ + d->mCaption = caption; + + initialize(); +} + +CardViewItem::~CardViewItem() +{ + // Remove ourself from the view + if ( mView != 0 ) + mView->takeItem( this ); + + delete d; + d = 0; +} + +void CardViewItem::initialize() +{ + d->mSelected = false; + d->mFieldList.setAutoDelete( true ); + d->maxLabelWidth = 0; + d->hcache = 0; + + // Add ourself to the view + if ( mView != 0 ) + mView->insertItem( this ); +} + +void CardViewItem::paintCard( QPainter *p, QColorGroup &cg ) +{ + if ( !mView ) + return; + + QPen pen; + QBrush brush; + QFontMetrics fm = *(mView->d->mFm); + QFontMetrics bFm = *(mView->d->mBFm); + bool drawLabels = mView->d->mDrawFieldLabels; + bool drawBorder = mView->d->mDrawCardBorder; + int mg = mView->itemMargin(); + int w = mView->itemWidth() - ( mg * 2 ); + int h = height() - ( mg * 2 ); + const int colonWidth( fm.width( ":" ) ); + int labelXPos = 2 + mg; + int labelWidth = QMIN( w / 2 - 4 - mg, d->maxLabelWidth + colonWidth + 4 ); + int valueXPos = labelWidth + 4 + mg; + int valueWidth = w - labelWidth - 4 - mg; + + p->setFont( mView->font() ); + labelWidth -= colonWidth; // extra space for the colon + + if ( !drawLabels ) { + valueXPos = labelXPos; + valueWidth = w - 4; + } + + // Draw a simple box + if ( isSelected() ) + pen = QPen( cg.highlight(), 1 ); + else + pen = QPen( cg.button(), 1 ); + p->setPen( pen ); + + // Draw the border - this is only draw if the user asks for it. + if ( drawBorder ) + p->drawRect( mg, mg, w, h ); + + // set the proper pen color for the caption box + if ( isSelected() ) + brush = cg.brush( QColorGroup::Highlight ); + else + brush = cg.brush( QColorGroup::Button ); + + p->fillRect( mg, mg, w, 4 + bFm.height(), brush ); + + // Now paint the caption + p->save(); + QFont bFont = mView->headerFont(); + p->setFont( bFont ); + if ( isSelected() ) + p->setPen( cg.highlightedText() ); + else + p->setPen( cg.buttonText() ); + + p->drawText( 2 + mg, 2 + mg + bFm.ascent(), trimString( d->mCaption, w - 4, bFm ) ); + p->restore(); + + // Go through the fields and draw them + QPtrListIterator<CardViewItem::Field> iter( d->mFieldList ); + QString label, value; + int yPos = mg + 4 + bFm.height() + fm.height(); + p->setPen( cg.text() ); + + int fh = fm.height(); + int cln( 0 ); + QString tmp; + int maxLines = mView->maxFieldLines(); + for ( iter.toFirst(); iter.current(); ++iter ) { + value = (*iter)->second; + if ( value.isEmpty() && ! mView->d->mShowEmptyFields ) + continue; + + if ( drawLabels ) { + label = trimString( (*iter)->first, labelWidth, fm ); + p->drawText( labelXPos, yPos, label + ":" ); + } + + for ( cln = 0; cln <= maxLines; cln++ ) { + tmp = value.section( '\n', cln, cln ); + if ( !tmp.isEmpty() ) + p->drawText( valueXPos, yPos + cln * fh, trimString( tmp, valueWidth, fm ) ); + else + break; + } + + if ( cln == 0 ) + cln = 1; + yPos += cln * fh + 2; + } + + // if we are the current item and the view has focus, draw focus rect + if ( mView->currentItem() == this && mView->hasFocus() ) { + mView->style().drawPrimitive( QStyle::PE_FocusRect, p, + QRect( 0, 0, mView->itemWidth(), h + (2 * mg) ), cg, + QStyle::Style_FocusAtBorder, + QStyleOption( isSelected() ? cg.highlight() : cg.base() ) ); + } +} + +const QString &CardViewItem::caption() const +{ + return d->mCaption; +} + + +int CardViewItem::height( bool allowCache ) const +{ + // use cache + if ( allowCache && d->hcache ) + return d->hcache; + + // Base height: + // 2 for line width + // 2 for top caption pad + // 2 for bottom caption pad + // 2 pad for the end + // + 2 times the advised margin + int baseHeight = 8 + ( 2 * mView->itemMargin() ); + + // size of font for each field + // 2 pad for each field + + bool sef = mView->showEmptyFields(); + int fh = mView->d->mFm->height(); + int fieldHeight = 0; + int lines; + int maxLines( mView->maxFieldLines() ); + QPtrListIterator<CardViewItem::Field> iter( d->mFieldList ); + for ( iter.toFirst(); iter.current(); ++iter ) { + if ( !sef && (*iter)->second.isEmpty() ) + continue; + lines = QMIN( (*iter)->second.contains( '\n' ) + 1, maxLines ); + fieldHeight += ( lines * fh ) + 2; + } + + // height of caption font (bold) + fieldHeight += mView->d->mBFm->height(); + d->hcache = baseHeight + fieldHeight; + return d->hcache; +} + +bool CardViewItem::isSelected() const +{ + return d->mSelected; +} + +void CardViewItem::setSelected( bool selected ) +{ + d->mSelected = selected; +} + +void CardViewItem::insertField( const QString &label, const QString &value ) +{ + CardViewItem::Field *f = new CardViewItem::Field( label, value ); + d->mFieldList.append( f ); + d->hcache = 0; + + if ( mView ) { + mView->setLayoutDirty( true ); + d->maxLabelWidth = QMAX( mView->d->mFm->width( label ), d->maxLabelWidth ); + } +} + +void CardViewItem::removeField( const QString &label ) +{ + CardViewItem::Field *f; + + QPtrListIterator<CardViewItem::Field> iter( d->mFieldList ); + for ( iter.toFirst(); iter.current(); ++iter ) { + f = *iter; + if ( f->first == label ) + break; + } + + if (*iter) + d->mFieldList.remove( *iter ); + d->hcache = 0; + + if ( mView ) + mView->setLayoutDirty( true ); +} + +void CardViewItem::clearFields() +{ + d->mFieldList.clear(); + d->hcache = 0; + + if ( mView ) + mView->setLayoutDirty( true ); +} + +QString CardViewItem::trimString( const QString &text, int width, + QFontMetrics &fm ) const +{ + if ( fm.width( text ) <= width ) + return text; + + QString dots = "..."; + int dotWidth = fm.width( dots ); + QString trimmed; + int charNum = 0; + + while ( fm.width( trimmed ) + dotWidth < width ) { + trimmed += text[ charNum ]; + charNum++; + } + + // Now trim the last char, since it put the width over the top + trimmed = trimmed.left( trimmed.length() - 1 ); + trimmed += dots; + + return trimmed; +} + +CardViewItem *CardViewItem::nextItem() const +{ + CardViewItem *item = 0; + + if ( mView ) + item = mView->itemAfter( this ); + + return item; +} + +void CardViewItem::repaintCard() +{ + if ( mView ) + mView->repaintItem( this ); +} + +void CardViewItem::setCaption( const QString &caption ) +{ + d->mCaption = caption; + repaintCard(); +} + +QString CardViewItem::fieldValue( const QString &label ) const +{ + QPtrListIterator<CardViewItem::Field> iter( d->mFieldList ); + for ( iter.toFirst(); iter.current(); ++iter ) + if ( (*iter)->first == label ) + return (*iter)->second; + + return QString(); +} + + +void CardViewItem::showFullString( const QPoint &itempos, CardViewTip *tip ) +{ + bool trimmed( false ); + QString s; + int mrg = mView->itemMargin(); + int y = mView->d->mBFm->height() + 6 + mrg; + int w = mView->itemWidth() - (2 * mrg); + int lw; + bool drawLabels = mView->drawFieldLabels(); + bool isLabel = drawLabels && itempos.x() < w / 2 ? true : false; + + if ( itempos.y() < y ) { + if ( itempos.y() < 8 + mrg || itempos.y() > y - 4 ) + return; + // this is the caption + s = caption(); + trimmed = mView->d->mBFm->width( s ) > w - 4; + y = 2 + mrg; + lw = 0; + isLabel = true; + } else { + // find the field + Field *f = fieldAt( itempos ); + if ( !f || ( !mView->showEmptyFields() && f->second.isEmpty() ) ) + return; + + // y position: + // header font height + 4px hader margin + 2px leading + item margin + // + actual field index * (fontheight + 2px leading) + int maxLines = mView->maxFieldLines(); + bool se = mView->showEmptyFields(); + int fh = mView->d->mFm->height(); + + Field *_f; + for ( _f = d->mFieldList.first(); _f != f; _f = d->mFieldList.next() ) + if ( se || ! _f->second.isEmpty() ) + y += ( QMIN( _f->second.contains( '\n' ) + 1, maxLines ) * fh ) + 2; + + if ( isLabel && itempos.y() > y + fh ) + return; + + s = isLabel ? f->first : f->second; + + int colonWidth = mView->d->mFm->width(":"); + lw = drawLabels ? QMIN( w / 2 - 4 - mrg, d->maxLabelWidth + colonWidth + 4 ) : 0; + int mw = isLabel ? lw - colonWidth : w - lw - ( mrg * 2 ); + if ( isLabel ) { + trimmed = mView->d->mFm->width( s ) > mw - colonWidth; + } else { + QRect r( mView->d->mFm->boundingRect( 0, 0, INT_MAX, INT_MAX, Qt::AlignTop|Qt::AlignLeft, s ) ); + trimmed = r.width() > mw || r.height() / fh > QMIN( s.contains( '\n' ) + 1, maxLines ); + } + } + + if ( trimmed ) { + tip->setFont( (isLabel && !lw) ? mView->headerFont() : mView->font() ); + tip->setText( s ); + tip->adjustSize(); + // find a proper position + int lx; + lx = isLabel || !drawLabels ? mrg : lw + mrg + 2; + QPoint pnt( mView->contentsToViewport( QPoint( d->x, d->y ) ) ); + pnt += QPoint( lx, y ); + if ( pnt.x() < 0 ) + pnt.setX( 0 ); + if ( pnt.x() + tip->width() > mView->visibleWidth() ) + pnt.setX( mView->visibleWidth() - tip->width() ); + if ( pnt.y() + tip->height() > mView->visibleHeight() ) + pnt.setY( QMAX( 0, mView->visibleHeight() - tip->height() ) ); + // show + tip->move( pnt ); + tip->show(); + } +} + +CardViewItem::Field *CardViewItem::fieldAt( const QPoint & itempos ) const +{ + int ypos = mView->d->mBFm->height() + 7 + mView->d->mItemMargin; + int iy = itempos.y(); + // skip below caption + if ( iy <= ypos ) + return 0; + // try find a field + bool showEmpty = mView->showEmptyFields(); + int fh = mView->d->mFm->height(); + int maxLines = mView->maxFieldLines(); + Field *f; + for ( f = d->mFieldList.first(); f; f = d->mFieldList.next() ) { + if ( showEmpty || !f->second.isEmpty() ) + ypos += (QMIN( f->second.contains( '\n' )+1, maxLines ) * fh) + 2; + if ( iy <= ypos ) + break; + } + + return f ? f : 0; +} + + +CardView::CardView( QWidget *parent, const char *name ) + : QScrollView( parent, name ), + d( new CardViewPrivate() ) +{ + d->mItemList.setAutoDelete( true ); + d->mSeparatorList.setAutoDelete( true ); + + QFont f = font(); + d->mFm = new QFontMetrics( f ); + f.setBold( true ); + d->mHeaderFont = f; + d->mBFm = new QFontMetrics( f ); + d->mTip = new CardViewTip( viewport() ); + d->mTip->hide(); + d->mTimer = new QTimer( this, "mouseTimer" ); + + viewport()->setMouseTracking( true ); + viewport()->setFocusProxy( this ); + viewport()->setFocusPolicy( WheelFocus ); + viewport()->setBackgroundMode( PaletteBase ); + + connect( d->mTimer, SIGNAL( timeout() ), this, SLOT( tryShowFullText() ) ); + + setBackgroundMode( PaletteBackground, PaletteBase ); + + // no reason for a vertical scrollbar + setVScrollBarMode( AlwaysOff ); +} + +CardView::~CardView() +{ + delete d->mFm; + delete d->mBFm; + delete d; + d = 0; +} + +void CardView::insertItem( CardViewItem *item ) +{ + d->mItemList.inSort( item ); + setLayoutDirty( true ); +} + +void CardView::takeItem( CardViewItem *item ) +{ + if ( d->mCurrentItem == item ) + d->mCurrentItem = item->nextItem(); + d->mItemList.take( d->mItemList.findRef( item ) ); + + setLayoutDirty( true ); +} + +void CardView::clear() +{ + d->mItemList.clear(); + + setLayoutDirty( true ); +} + +CardViewItem *CardView::currentItem() const +{ + if ( !d->mCurrentItem && d->mItemList.count() ) + d->mCurrentItem = d->mItemList.first(); + + return d->mCurrentItem; +} + +void CardView::setCurrentItem( CardViewItem *item ) +{ + if ( !item ) + return; + else if ( item->cardView() != this ) { + kdDebug(5720)<<"CardView::setCurrentItem: Item ("<<item<<") not owned! Backing out.."<<endl; + return; + } else if ( item == currentItem() ) { + return; + } + + if ( d->mSelectionMode == Single ) { + setSelected( item, true ); + } else { + CardViewItem *it = d->mCurrentItem; + d->mCurrentItem = item; + if ( it ) + it->repaintCard(); + + item->repaintCard(); + } + + if ( ! d->mOnSeparator ) + ensureItemVisible( item ); + + emit currentChanged( item ); +} + +CardViewItem *CardView::itemAt( const QPoint &viewPos ) const +{ + CardViewItem *item = 0; + QPtrListIterator<CardViewItem> iter( d->mItemList ); + bool found = false; + for ( iter.toFirst(); iter.current() && !found; ++iter ) { + item = *iter; + if ( QRect( item->d->x, item->d->y, d->mItemWidth, item->height() ).contains( viewPos ) ) + found = true; + } + + if ( found ) + return item; + + return 0; +} + +QRect CardView::itemRect( const CardViewItem *item ) const +{ + return QRect( item->d->x, item->d->y, d->mItemWidth, item->height() ); +} + +void CardView::ensureItemVisible( const CardViewItem *item ) +{ + ensureVisible( item->d->x, item->d->y, d->mItemSpacing, 0 ); + ensureVisible( item->d->x + d->mItemWidth, item->d->y, d->mItemSpacing, 0 ); +} + +void CardView::repaintItem( const CardViewItem *item ) +{ + repaintContents( QRect( item->d->x, item->d->y, d->mItemWidth, item->height() ) ); +} + +void CardView::setSelectionMode( CardView::SelectionMode mode ) +{ + selectAll( false ); + + d->mSelectionMode = mode; +} + +CardView::SelectionMode CardView::selectionMode() const +{ + return d->mSelectionMode; +} + +void CardView::selectAll( bool state ) +{ + QPtrListIterator<CardViewItem> iter( d->mItemList ); + if ( !state ) { + for ( iter.toFirst(); iter.current(); ++iter ) { + if ( (*iter)->isSelected() ) { + (*iter)->setSelected( false ); + (*iter)->repaintCard(); + } + } + + emit selectionChanged( 0 ); + } else if ( d->mSelectionMode != CardView::Single ) { + for ( iter.toFirst(); iter.current(); ++iter ) { + (*iter)->setSelected( true ); + } + + if ( d->mItemList.count() > 0 ) { + // emit, since there must have been at least one selected + emit selectionChanged(); + viewport()->update(); + } + } +} + +void CardView::setSelected( CardViewItem *item, bool selected ) +{ + if ( (item == 0) || (item->isSelected() == selected) ) + return; + + if ( selected && d->mCurrentItem != item ) { + CardViewItem *it = d->mCurrentItem; + d->mCurrentItem = item; + if ( it ) + it->repaintCard(); + } + + if ( d->mSelectionMode == CardView::Single ) { + bool b = signalsBlocked(); + blockSignals( true ); + selectAll( false ); + blockSignals( b ); + + if ( selected ) { + item->setSelected( selected ); + item->repaintCard(); + emit selectionChanged(); + emit selectionChanged( item ); + } else { + emit selectionChanged(); + emit selectionChanged( 0 ); + } + } else if ( d->mSelectionMode == CardView::Multi ) { + item->setSelected( selected ); + item->repaintCard(); + emit selectionChanged(); + } else if ( d->mSelectionMode == CardView::Extended ) { + bool b = signalsBlocked(); + blockSignals( true ); + selectAll( false ); + blockSignals( b ); + + item->setSelected( selected ); + item->repaintCard(); + emit selectionChanged(); + } +} + +bool CardView::isSelected( CardViewItem *item ) const +{ + return (item && item->isSelected()); +} + +CardViewItem *CardView::selectedItem() const +{ + // find the first selected item + QPtrListIterator<CardViewItem> iter( d->mItemList ); + for ( iter.toFirst(); iter.current(); ++iter ) { + if ( (*iter)->isSelected() ) + return *iter; + } + + return 0; +} + +CardViewItem *CardView::firstItem() const +{ + return d->mItemList.first(); +} + +int CardView::childCount() const +{ + return d->mItemList.count(); +} + +CardViewItem *CardView::findItem( const QString &text, const QString &label, + Qt::StringComparisonMode compare ) const +{ + // If the text is empty, we will return null, since empty text will + // match anything! + if ( text.isEmpty() ) + return 0; + + QPtrListIterator<CardViewItem> iter( d->mItemList ); + if ( compare & Qt::BeginsWith ) { + QString value; + for ( iter.toFirst(); iter.current(); ++iter ) { + value = (*iter)->fieldValue( label ).upper(); + if ( value.startsWith( text.upper() ) ) + return *iter; + } + } else { + kdDebug(5720) << "CardView::findItem: search method not implemented" << endl; + } + + return 0; +} + +uint CardView::columnWidth() const +{ + return d->mDrawSeparators ? + d->mItemWidth + ( 2 * d->mItemSpacing ) + d->mSepWidth : + d->mItemWidth + d->mItemSpacing; +} + +void CardView::drawContents( QPainter *p, int clipx, int clipy, + int clipw, int cliph ) +{ + QScrollView::drawContents( p, clipx, clipy, clipw, cliph ); + + if ( d->mLayoutDirty ) + calcLayout(); + + // allow setting costum colors in the viewport pale + QColorGroup cg = viewport()->palette().active(); + + QRect clipRect( clipx, clipy, clipw, cliph ); + QRect cardRect; + QRect sepRect; + CardViewItem *item; + CardViewSeparator *sep; + + // make sure the viewport is a pure background + viewport()->erase( clipRect ); + + // Now tell the cards to draw, if they are in the clip region + QPtrListIterator<CardViewItem> iter( d->mItemList ); + for ( iter.toFirst(); iter.current(); ++iter) { + item = *iter; + cardRect.setRect( item->d->x, item->d->y, d->mItemWidth, item->height() ); + + if ( clipRect.intersects( cardRect ) || clipRect.contains( cardRect ) ) { + // Tell the card to paint + p->save(); + p->translate( cardRect.x(), cardRect.y() ); + item->paintCard( p, cg ); + p->restore(); + } + } + + // Followed by the separators if they are in the clip region + QPtrListIterator<CardViewSeparator> sepIter( d->mSeparatorList ); + for ( sepIter.toFirst(); sepIter.current(); ++sepIter ) { + sep = *sepIter; + sepRect = sep->mRect; + + if ( clipRect.intersects( sepRect ) || clipRect.contains( sepRect ) ) { + p->save(); + p->translate( sepRect.x(), sepRect.y() ); + sep->paintSeparator( p, cg ); + p->restore(); + } + } +} + +void CardView::resizeEvent( QResizeEvent *event ) +{ + QScrollView::resizeEvent( event ); + + setLayoutDirty( true ); +} + +void CardView::calcLayout() +{ + // Start in the upper left corner and layout all the + // cars using their height and width + int maxWidth = 0; + int maxHeight = 0; + int xPos = 0; + int yPos = 0; + int cardSpacing = d->mItemSpacing; + + // delete the old separators + d->mSeparatorList.clear(); + + QPtrListIterator<CardViewItem> iter( d->mItemList ); + CardViewItem *item = 0; + CardViewSeparator *sep = 0; + xPos += cardSpacing; + + for ( iter.toFirst(); iter.current(); ++iter ) { + item = *iter; + + yPos += cardSpacing; + + if ( yPos + item->height() + cardSpacing >= height() - horizontalScrollBar()->height() ) { + maxHeight = QMAX( maxHeight, yPos ); + + // Drawing in this column would be greater than the height + // of the scroll view, so move to next column + yPos = cardSpacing; + xPos += cardSpacing + maxWidth; + if ( d->mDrawSeparators ) { + // Create a separator since the user asked + sep = new CardViewSeparator( this ); + sep->mRect.moveTopLeft( QPoint( xPos, yPos + d->mItemMargin ) ); + xPos += d->mSepWidth + cardSpacing; + d->mSeparatorList.append( sep ); + } + + maxWidth = 0; + } + + item->d->x = xPos; + item->d->y = yPos; + + yPos += item->height(); + maxWidth = QMAX( maxWidth, d->mItemWidth ); + } + + xPos += maxWidth; + resizeContents( xPos + cardSpacing, maxHeight ); + + // Update the height of all the separators now that we know the + // max height of a column + QPtrListIterator<CardViewSeparator> sepIter( d->mSeparatorList ); + for ( sepIter.toFirst(); sepIter.current(); ++sepIter ) + (*sepIter)->mRect.setHeight( maxHeight - 2 * cardSpacing - 2 * d->mItemMargin ); + + d->mLayoutDirty = false; +} + +CardViewItem *CardView::itemAfter( const CardViewItem *item ) const +{ + d->mItemList.findRef( item ); + return d->mItemList.next(); +} + +uint CardView::itemMargin() const +{ + return d->mItemMargin; +} + +void CardView::setItemMargin( uint margin ) +{ + if ( margin == d->mItemMargin ) + return; + + d->mItemMargin = margin; + setLayoutDirty( true ); +} + +uint CardView::itemSpacing() const +{ + return d->mItemSpacing; +} + +void CardView::setItemSpacing( uint spacing ) +{ + if ( spacing == d->mItemSpacing ) + return; + + d->mItemSpacing = spacing; + setLayoutDirty( true ); +} + +void CardView::contentsMousePressEvent( QMouseEvent *e ) +{ + QScrollView::contentsMousePressEvent( e ); + + QPoint pos = contentsToViewport( e->pos() ); + d->mLastClickPos = e->pos(); + + CardViewItem *item = itemAt( e->pos() ); + + if ( item == 0 ) { + d->mLastClickOnItem = false; + if ( d->mOnSeparator) { + d->mResizeAnchor = e->x() + contentsX(); + d->mColspace = (2 * d->mItemSpacing); + int ccw = d->mItemWidth + d->mColspace + d->mSepWidth; + d->mFirst = (contentsX() + d->mSepWidth) / ccw; + d->mPressed = (d->mResizeAnchor + d->mSepWidth) / ccw; + d->mSpan = d->mPressed - d->mFirst; + d->mFirstX = d->mFirst * ccw; + if ( d->mFirstX ) + d->mFirstX -= d->mSepWidth; + } else { + selectAll( false ); + } + + return; + } + + d->mLastClickOnItem = true; + + CardViewItem *other = d->mCurrentItem; + setCurrentItem( item ); + + // Always emit the selection + emit clicked( item ); + + // The RMB click + if ( e->button() & Qt::RightButton ) { + // clear previous selection + bool blocked = signalsBlocked(); + blockSignals( true ); + selectAll( false ); + blockSignals( blocked ); + + // select current item + item->setSelected( true ); + + emit contextMenuRequested( item, mapToGlobal( pos ) ); + return; + } + + // Check the selection type and update accordingly + if ( d->mSelectionMode == CardView::Single ) { + // make sure it isn't already selected + if ( item->isSelected() ) + return; + + bool b = signalsBlocked(); + blockSignals( true ); + selectAll( false ); + blockSignals( b ); + + item->setSelected( true ); + item->repaintCard(); + emit selectionChanged( item ); + } else if ( d->mSelectionMode == CardView::Multi ) { + // toggle the selection + item->setSelected( !item->isSelected() ); + item->repaintCard(); + emit selectionChanged(); + } else if ( d->mSelectionMode == CardView::Extended ) { + if ( (e->button() & Qt::LeftButton) && (e->state() & Qt::ShiftButton) ) { + if ( item == other ) + return; + + bool s = !item->isSelected(); + + if ( s && !(e->state() & ControlButton) ) { + bool b = signalsBlocked(); + blockSignals( true ); + selectAll( false ); + blockSignals( b ); + } + + int from, to, a, b; + a = d->mItemList.findRef( item ); + b = d->mItemList.findRef( other ); + from = a < b ? a : b; + to = a > b ? a : b; + + CardViewItem *aItem; + for ( ; from <= to; from++ ) { + aItem = d->mItemList.at( from ); + aItem->setSelected( s ); + repaintItem( aItem ); + } + + emit selectionChanged(); + } else if ( (e->button() & Qt::LeftButton) && (e->state() & Qt::ControlButton) ) { + item->setSelected( !item->isSelected() ); + item->repaintCard(); + emit selectionChanged(); + } else if ( e->button() & Qt::LeftButton ) { + bool b = signalsBlocked(); + blockSignals( true ); + selectAll( false ); + blockSignals( b ); + + item->setSelected( true ); + item->repaintCard(); + emit selectionChanged(); + } + } +} + +void CardView::contentsMouseReleaseEvent( QMouseEvent *e ) +{ + QScrollView::contentsMouseReleaseEvent( e ); + + if ( d->mResizeAnchor && d->mSpan ) { + unsetCursor(); + // hide rubber bands + int newiw = d->mItemWidth - ((d->mResizeAnchor - d->mRubberBandAnchor) / d->mSpan); + drawRubberBands( 0 ); + // we should move to reflect the new position if we are scrolled. + if ( contentsX() ) { + int newX = QMAX( 0, ( d->mPressed * ( newiw + d->mColspace + d->mSepWidth ) ) - e->x() ); + setContentsPos( newX, contentsY() ); + } + // set new item width + setItemWidth( newiw ); + // reset anchors + d->mResizeAnchor = 0; + d->mRubberBandAnchor = 0; + return; + } + + // If there are accel keys, we will not emit signals + if ( (e->state() & Qt::ShiftButton) || (e->state() & Qt::ControlButton) ) + return; + + // Get the item at this position + CardViewItem *item = itemAt( e->pos() ); + + if ( item && KGlobalSettings::singleClick() ) + emit executed( item ); +} + +void CardView::contentsMouseDoubleClickEvent( QMouseEvent *e ) +{ + QScrollView::contentsMouseDoubleClickEvent( e ); + + CardViewItem *item = itemAt( e->pos() ); + + if ( item ) + d->mCurrentItem = item; + + if ( item && !KGlobalSettings::singleClick() ) + emit executed(item); + + emit doubleClicked( item ); +} + +void CardView::contentsMouseMoveEvent( QMouseEvent *e ) +{ + // resizing + if ( d->mResizeAnchor ) { + int x = e->x(); + if ( x != d->mRubberBandAnchor ) + drawRubberBands( x ); + return; + } + + if ( d->mLastClickOnItem && (e->state() & Qt::LeftButton) && + ((e->pos() - d->mLastClickPos).manhattanLength() > 4)) { + + startDrag(); + return; + } + + d->mTimer->start( 500 ); + + // see if we are over a separator + // only if we actually have them painted? + if ( d->mDrawSeparators ) { + int colcontentw = d->mItemWidth + (2 * d->mItemSpacing); + int colw = colcontentw + d->mSepWidth; + int m = e->x() % colw; + if ( m >= colcontentw && m > 0 ) { + setCursor( SplitHCursor ); + d->mOnSeparator = true; + } else { + setCursor( ArrowCursor ); + d->mOnSeparator = false; + } + } +} + +void CardView::enterEvent( QEvent* ) +{ + d->mTimer->start( 500 ); +} + +void CardView::leaveEvent( QEvent* ) +{ + d->mTimer->stop(); + if ( d->mOnSeparator ) { + d->mOnSeparator = false; + setCursor( ArrowCursor ); + } +} + +void CardView::focusInEvent( QFocusEvent* ) +{ + if ( !d->mCurrentItem && d->mItemList.count() ) + setCurrentItem( d->mItemList.first() ); + else if ( d->mCurrentItem ) + d->mCurrentItem->repaintCard(); +} + +void CardView::focusOutEvent( QFocusEvent* ) +{ + if ( d->mCurrentItem ) + d->mCurrentItem->repaintCard(); +} + +void CardView::keyPressEvent( QKeyEvent *e ) +{ + if ( !(childCount() && d->mCurrentItem) ) { + e->ignore(); + return; + } + + uint pos = d->mItemList.findRef( d->mCurrentItem ); + CardViewItem *aItem = 0; + CardViewItem *old = d->mCurrentItem; + + switch ( e->key() ) { + case Key_Up: + if ( pos > 0 ) { + aItem = d->mItemList.at( pos - 1 ); + setCurrentItem( aItem ); + } + break; + case Key_Down: + if ( pos < d->mItemList.count() - 1 ) { + aItem = d->mItemList.at( pos + 1 ); + setCurrentItem( aItem ); + } + break; + case Key_Left: + { + // look for an item in the previous/next column, starting from + // the vertical middle of the current item. + // FIXME use nice calculatd measures!!! + QPoint aPoint( d->mCurrentItem->d->x, d->mCurrentItem->d->y ); + aPoint -= QPoint( 30, -(d->mCurrentItem->height() / 2) ); + aItem = itemAt( aPoint ); + // maybe we hit some space below an item + while ( !aItem && aPoint.y() > 27 ) { + aPoint -= QPoint( 0, 16 ); + aItem = itemAt( aPoint ); + } + if ( aItem ) + setCurrentItem( aItem ); + + break; + } + case Key_Right: + { + // FIXME use nice calculated measures!!! + QPoint aPoint( d->mCurrentItem->d->x + d->mItemWidth, d->mCurrentItem->d->y ); + aPoint += QPoint( 30, (d->mCurrentItem->height() / 2) ); + aItem = itemAt( aPoint ); + while ( !aItem && aPoint.y() > 27 ) { + aPoint -= QPoint( 0, 16 ); + aItem = itemAt( aPoint ); + } + if ( aItem ) + setCurrentItem( aItem ); + + break; + } + case Key_Home: + aItem = d->mItemList.first(); + setCurrentItem( aItem ); + break; + case Key_End: + aItem = d->mItemList.last(); + setCurrentItem( aItem ); + break; + case Key_Prior: // PageUp + { + // QListView: "Make the item above the top visible and current" + // TODO if contentsY(), pick the top item of the leftmost visible column + if ( contentsX() <= 0 ) + return; + int cw = columnWidth(); + int theCol = ( QMAX( 0, ( contentsX() / cw) * cw ) ) + d->mItemSpacing; + aItem = itemAt( QPoint( theCol + 1, d->mItemSpacing + 1 ) ); + if ( aItem ) + setCurrentItem( aItem ); + + break; + } + case Key_Next: // PageDown + { + // QListView: "Make the item below the bottom visible and current" + // find the first not fully visible column. + // TODO: consider if a partly visible (or even hidden) item at the + // bottom of the rightmost column exists + int cw = columnWidth(); + int theCol = ( (( contentsX() + visibleWidth() ) / cw) * cw ) + d->mItemSpacing + 1; + // if separators are on, we may need to we may be one column further right if only the spacing/sep is hidden + if ( d->mDrawSeparators && cw - (( contentsX() + visibleWidth() ) % cw) <= int( d->mItemSpacing + d->mSepWidth ) ) + theCol += cw; + + // make sure this is not too far right + while ( theCol > contentsWidth() ) + theCol -= columnWidth(); + + aItem = itemAt( QPoint( theCol, d->mItemSpacing + 1 ) ); + + if ( aItem ) + setCurrentItem( aItem ); + + break; + } + case Key_Space: + setSelected( d->mCurrentItem, !d->mCurrentItem->isSelected() ); + emit selectionChanged(); + break; + case Key_Return: + case Key_Enter: + emit returnPressed( d->mCurrentItem ); + emit executed( d->mCurrentItem ); + break; + case Key_Menu: + emit contextMenuRequested( d->mCurrentItem, viewport()->mapToGlobal( + itemRect(d->mCurrentItem).center() ) ); + break; + default: + if ( (e->state() & ControlButton) && e->key() == Key_A ) { + // select all + selectAll( true ); + break; + } else if ( !e->text().isEmpty() && e->text()[ 0 ].isPrint() ) { + // if we have a string, do autosearch + } + break; + } + + // handle selection + if ( aItem ) { + if ( d->mSelectionMode == CardView::Extended ) { + if ( e->state() & ShiftButton ) { + // shift button: toggle range + // if control button is pressed, leave all items + // and toggle selection current->old current + // otherwise, ?????? + bool s = ! aItem->isSelected(); + int from, to, a, b; + a = d->mItemList.findRef( aItem ); + b = d->mItemList.findRef( old ); + from = a < b ? a : b; + to = a > b ? a : b; + + if ( to - from > 1 ) { + bool b = signalsBlocked(); + blockSignals( true ); + selectAll( false ); + blockSignals( b ); + } + + CardViewItem *item; + for ( ; from <= to; from++ ) { + item = d->mItemList.at( from ); + item->setSelected( s ); + repaintItem( item ); + } + + emit selectionChanged(); + } else if ( e->state() & ControlButton ) { + // control button: do nothing + } else { + // no button: move selection to this item + bool b = signalsBlocked(); + blockSignals( true ); + selectAll( false ); + blockSignals( b ); + + setSelected( aItem, true ); + emit selectionChanged(); + } + } + } +} + +void CardView::contentsWheelEvent( QWheelEvent *e ) +{ + scrollBy( 2 * e->delta() / -3, 0 ); +} + +void CardView::setLayoutDirty( bool dirty ) +{ + if ( d->mLayoutDirty != dirty ) { + d->mLayoutDirty = dirty; + repaint(); + } +} + +void CardView::setDrawCardBorder( bool enabled ) +{ + if ( enabled != d->mDrawCardBorder ) { + d->mDrawCardBorder = enabled; + repaint(); + } +} + +bool CardView::drawCardBorder() const +{ + return d->mDrawCardBorder; +} + +void CardView::setDrawColSeparators( bool enabled ) +{ + if ( enabled != d->mDrawSeparators ) { + d->mDrawSeparators = enabled; + setLayoutDirty( true ); + } +} + +bool CardView::drawColSeparators() const +{ + return d->mDrawSeparators; +} + +void CardView::setDrawFieldLabels( bool enabled ) +{ + if ( enabled != d->mDrawFieldLabels ) { + d->mDrawFieldLabels = enabled; + repaint(); + } +} + +bool CardView::drawFieldLabels() const +{ + return d->mDrawFieldLabels; +} + +void CardView::setShowEmptyFields( bool show ) +{ + if ( show != d->mShowEmptyFields ) { + d->mShowEmptyFields = show; + setLayoutDirty( true ); + } +} + +bool CardView::showEmptyFields() const +{ + return d->mShowEmptyFields; +} + +void CardView::startDrag() +{ + // The default implementation is a no-op. It must be + // reimplemented in a subclass to be useful +} + +void CardView::tryShowFullText() +{ + d->mTimer->stop(); + // if we have an item + QPoint cpos = viewportToContents( viewport()->mapFromGlobal( QCursor::pos() ) ); + CardViewItem *item = itemAt( cpos ); + if ( item ) { + // query it for a value to display + QPoint ipos = cpos - itemRect( item ).topLeft(); + item->showFullString( ipos, d->mTip ); + } +} + +void CardView::drawRubberBands( int pos ) +{ + if ( pos && d && + (!d->mSpan || ((pos - d->mFirstX) / d->mSpan) - d->mColspace - d->mSepWidth < MIN_ITEM_WIDTH) ) + return; + + int tmpcw = (d->mRubberBandAnchor - d->mFirstX) / d->mSpan; + int x = d->mFirstX + tmpcw - d->mSepWidth - contentsX(); + int h = visibleHeight(); + + QPainter p( viewport() ); + p.setRasterOp( XorROP ); + p.setPen( gray ); + p.setBrush( gray ); + uint n = d->mFirst; + // erase + if ( d->mRubberBandAnchor ) + do { + p.drawRect( x, 0, 2, h ); + x += tmpcw; + n++; + } while ( x < visibleWidth() && n < d->mSeparatorList.count() ); + // paint new + if ( ! pos ) + return; + tmpcw = (pos - d->mFirstX) / d->mSpan; + n = d->mFirst; + x = d->mFirstX + tmpcw - d->mSepWidth - contentsX(); + do { + p.drawRect( x, 0, 2, h ); + x += tmpcw; + n++; + } while ( x < visibleWidth() && n < d->mSeparatorList.count() ); + d->mRubberBandAnchor = pos; +} + +int CardView::itemWidth() const +{ + return d->mItemWidth; +} + +void CardView::setItemWidth( int w ) +{ + if ( w == d->mItemWidth ) + return; + if ( w < MIN_ITEM_WIDTH ) + w = MIN_ITEM_WIDTH; + d->mItemWidth = w; + setLayoutDirty( true ); + updateContents(); +} + +void CardView::setHeaderFont( const QFont &fnt ) +{ + d->mHeaderFont = fnt; + delete d->mBFm; + d->mBFm = new QFontMetrics( fnt ); +} + +QFont CardView::headerFont() const +{ + return d->mHeaderFont; +} + +void CardView::setFont( const QFont &fnt ) +{ + QScrollView::setFont( fnt ); + delete d->mFm; + d->mFm = new QFontMetrics( fnt ); +} + +int CardView::separatorWidth() const +{ + return d->mSepWidth; +} + +void CardView::setSeparatorWidth( int width ) +{ + d->mSepWidth = width; + setLayoutDirty( true ); +} + +int CardView::maxFieldLines() const +{ + return d->mMaxFieldLines; +} + +void CardView::setMaxFieldLines( int howmany ) +{ + d->mMaxFieldLines = howmany ? howmany : INT_MAX; + // FIXME update, forcing the items to recalc height!! +} + +#include "cardview.moc" diff --git a/kaddressbook/views/cardview.desktop b/kaddressbook/views/cardview.desktop new file mode 100644 index 000000000..cb8d35cb0 --- /dev/null +++ b/kaddressbook/views/cardview.desktop @@ -0,0 +1,62 @@ +[Desktop Entry] +X-KDE-Library=libkaddrbk_cardview +Name=Card View +Name[af]=Kaard Aansig +Name[ar]=عرض البظاقة +Name[be]=У выглядзе картак +Name[bg]=Преглед като карти +Name[br]=Gwell ar c'hartennoù +Name[bs]=Pogled kartice +Name[ca]=Vista de targeta +Name[cs]=Pohled s kartičkami +Name[cy]=Gweld Cerdyn +Name[da]=Kort-visning +Name[de]=Visitenkarten-Betrachter +Name[el]=Προβολή καρτών +Name[eo]=Kartrigardo +Name[es]=Vista de tarjeta +Name[et]=Kaardivaade +Name[eu]=Txartel ikuspegia +Name[fa]=نمای کارت +Name[fi]=Korttinäkymä +Name[fr]=Vue en cartes +Name[fy]=Kaartwerjefte +Name[gl]=Vista de tarxetas +Name[he]=תצוגת כרטיס +Name[hi]=कार्ड दृश्य +Name[hu]=Kártyanézet +Name[is]=Spjaldsýn +Name[it]=Vista scheda +Name[ja]=カードビュー +Name[ka]=ბარათების ჩვენება +Name[kk]=Визитка +Name[km]=ទិដ្ឋភាពកាត +Name[lt]=Kortelės vaizdas +Name[mk]=Преглед со картички +Name[ms]=Pelihat Kad +Name[nb]=Kortvisning +Name[nds]=Visitenkoort-Kieker +Name[ne]=कार्ड दृश्य +Name[nl]=Kaartweergave +Name[nn]=Kortvising +Name[pa]=ਕਾਰਡ ਦਰਿਸ਼ +Name[pl]=Widok kartek +Name[pt]=Vista em Cartões +Name[pt_BR]=Visualização de Cartão +Name[ro]=Vizualizare card +Name[ru]=Карточки +Name[se]=Goartačájeheapmi +Name[sk]=Prezeranie karty +Name[sl]=Kartični prikaz +Name[sr]=Приказ са картицама +Name[sr@Latn]=Prikaz sa karticama +Name[sv]=Kortvy +Name[ta]=அட்டைக் காட்சி +Name[tg]=Варақа +Name[tr]=Kart Görünümü +Name[uk]=Вигляд картками +Name[zh_CN]=卡片视图 +Name[zh_TW]=卡片檢視 +Type=Service +ServiceTypes=KAddressBook/View +X-KDE-KAddressBook-ViewPluginVersion=1 diff --git a/kaddressbook/views/cardview.h b/kaddressbook/views/cardview.h new file mode 100644 index 000000000..e38a82d53 --- /dev/null +++ b/kaddressbook/views/cardview.h @@ -0,0 +1,579 @@ +/* + This file is part of KAddressBook. + Copyright (c) 2002 Mike Pilone <mpilone@slac.com> + + 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 CARDVIEW_H +#define CARDVIEW_H + +#include <qpair.h> +#include <qpoint.h> +#include <qptrlist.h> +#include <qrect.h> +#include <qscrollview.h> +#include <qstring.h> + +class QLabel; +class QMouseEvent; +class QPainter; +class QResizeEvent; + +class CardView; +class CardViewItemPrivate; +class CardViewPrivate; +class CardViewTip; + +/** + Represents a single card (item) in the card view. A card has a caption + and a list of fields. A Field is a label<->value pair. The labels in a + card should be unique, since they will be used to index the values. + */ +class CardViewItem +{ + friend class CardView; + + public: + /** + A single field in the card view. The first item is the label + and the second item is the value. + */ + typedef QPair<QString, QString> Field; + + /** + Constructor. + + @param parent The CardView that this card should be displayed on. + @param caption The caption of the card. This is the text that will + appear at the top of the card. This is also the string that will + be used to sort the cards in the view. + */ + CardViewItem( CardView *parent, const QString &caption = QString() ); + virtual ~CardViewItem(); + + /** + @return The caption of the card, or QString::null if none was ever set. + */ + const QString &caption() const; + + /** + Sets the caption of the card. This is the text that will + appear at the top of the card. This is also the string that will + be used to sort the cards in the view. + */ + void setCaption( const QString &caption ); + + /** + Paints the card using the given painter and color group. The + card will handle painting itself selected if it is selected. + */ + virtual void paintCard( QPainter *p, QColorGroup &cg ); + + /** + Repaints the card. This is done by sending a repaint event to the + view with the clip rect defined as this card. + */ + virtual void repaintCard(); + + /** + Adds a field to the card. + + @param label The label of the field. The field labels must be unique + within a card. + @param value The value of the field. + */ + void insertField( const QString &label, const QString &value ); + + /** + Removes the field with label <i>label</i> from the card. + */ + void removeField( const QString &label ); + + /** + @return The value of the field with label <i>label</i>. + */ + QString fieldValue( const QString &label ) const; + + /** + Removes all the fields from this card. + */ + void clearFields(); + + /** + @return The next card item. The order of the items will be the same + as the display order in the view. 0 will be returned if this is the + last card. + */ + CardViewItem *nextItem() const; + + /** + @return True if this card is currently selected, false otherwise. + */ + bool isSelected() const; + + /** + Called by the parent card view when the mouse has been resting for + a certain amount of time. If the label or value at pos is obscured + (trimmed) make the label display the full text. + */ + void showFullString( const QPoint &pos, CardViewTip *tip ); + + /** + @return a pointer to the Field at the position itempos + in this item. 0 is returned if itempos is in the caption. + @param itempos the position in item coordinates + */ + Field *fieldAt( const QPoint &itempos ) const; + + CardView *cardView() const { return mView; }; + + /** + @return The height of this item as rendered, in pixels. + + if @p allowCache is true, the item may use an internally + cached value rather than recalculating from scratch. The + argument is mainly to allow the cardView to change global settings (like + maxFieldLines) that might influence the items heights + */ + int height( bool allowCache = true ) const; + + protected: + /** + Sets the card as selected. This is usually only called from the + card view. + */ + void setSelected( bool selected ); + + private: + /** + Sets the default values. + */ + void initialize(); + + /** + Trims a string to the width <i>width</i> using the font metrics + to determine the width of each char. If the string is longer than + <i>width</i>, then the string will be trimmed and a '...' will + be appended. + */ + QString trimString( const QString &text, int width, QFontMetrics &fm ) const; + + CardViewItemPrivate *d; + CardView *mView; +}; + +/** + The CardView is a method of displaying data in cards. This idea is + similar to the idea of a rolodex or business cards. Each card has a + caption and a list of fields, which are label<->value pairs. The CardView + displays multiple cards in a grid. The Cards are sorted based on their + caption. + + The CardView class is designed to mirror the API of the QListView or + QIconView. The CardView is also completely independant of KAddressBook and + can be used elsewhere. With the exception of a few simple config checks, + the CardView is also 100% independant of KDE. + */ +class CardView : public QScrollView +{ + friend class CardViewItem; + + Q_OBJECT + + public: + /** + Constructor. + */ + CardView( QWidget *parent, const char *name ); + virtual ~CardView(); + + /** + Inserts the item into the card view. This method does not have + to be called if you created the item with a proper parent. Once + inserted, the CardView takes ownership of the item. + */ + void insertItem( CardViewItem *item ); + + /** + Takes the item from the view. The item will not be deleted and + ownership of the item is returned to the caller. + */ + void takeItem( CardViewItem *item ); + + /** + Clears the view and deletes all card view items + */ + void clear(); + + /** + @return The current item, the item that has the focus. + Whenever the view has focus, this item has a focus rectangle painted + at it's border. + @sa setCurrentItem() + */ + CardViewItem *currentItem() const; + + /** + Sets the CardViewItem @p item to the current item in the view. + */ + void setCurrentItem( CardViewItem *item ); + + /** + @return The item found at the given point, or 0 if there is no item + at that point. + */ + CardViewItem *itemAt( const QPoint &viewPos ) const; + + /** + @return The bounding rect of the given item. + */ + QRect itemRect( const CardViewItem *item ) const; + + /** + Ensures that the given item is in the viewable area of the widget + */ + void ensureItemVisible( const CardViewItem *item ); + + /** + Repaints the given item. + */ + void repaintItem( const CardViewItem *item ); + + enum SelectionMode { Single, Multi, Extended, NoSelection }; + + /** + Sets the selection mode. + + @see QListView + */ + void setSelectionMode( SelectionMode mode ); + + /** + @return The current selection mode. + */ + SelectionMode selectionMode() const; + + /** + Selects or deselects the given item. This method honors the current + selection mode, so if other items are selected, they may be unselected. + */ + void setSelected( CardViewItem *item, bool selected ); + + /** + Selects or deselects all items. + */ + void selectAll( bool state ); + + /** + @return True if the given item is selected, false otherwise. + */ + bool isSelected( CardViewItem *item ) const; + + /** + @return The first selected item. In single select mode, this will be + the only selected item, in other modes this will be the first selected + item, but others may exist. 0 if no item is selected. + */ + CardViewItem *selectedItem() const; + + /** + @return The first item in the view. This may be 0 if no items have + been inserted. This method combined with CardViewItem::nextItem() + can be used to iterator through the list of items. + */ + CardViewItem *firstItem() const; + + /** + @return The item after the given item or 0 if the item is the last + item. + */ + CardViewItem *itemAfter( const CardViewItem *item ) const; + + /** + @return The number of items in the view. + */ + int childCount() const; + + /** + Attempts to find the first item matching the params. + + @param text The text to match. + @param label The label of the field to match against. + @param compare The compare method to use in doing the search. + + @return The first matching item, or 0 if no items match. + */ + CardViewItem *findItem( const QString &text, const QString &label, + Qt::StringComparisonMode compare = Qt::BeginsWith ) const; + + /** + Returns the amounts of pixels required for one column. + This depends on wheather drawSeparators is enabled: + If so, it is itemWidth + 2*itemSpacing + separatorWidth + If not, it is itemWidth + itemSpacing + @see itemWidth(), setItemWidth(), itemSpacing() and setItemSpacing() + */ + uint columnWidth() const; + + /** + Sets if the border around a card should be draw. The border is a thing + (1 or 2 pixel) line that bounds the card. When drawn, it shows when + a card is highlighted and when it isn't. + */ + void setDrawCardBorder( bool enabled ); + + /** + @return True if borders are drawn, false otherwise. + */ + bool drawCardBorder() const; + + /** + Sets if the column separator should be drawn. The column separator + is a thin verticle line (1 or 2 pixels) that is used to separate the + columns in the list view. The separator is just for esthetics and it + does not serve a functional purpose. + */ + void setDrawColSeparators( bool enabled ); + + /** + @return True if column separators are drawn, false otherwise. + */ + bool drawColSeparators() const; + + /** + Sets if the field labels should be drawn. The field labels are the + unique strings used to identify the fields. Sometimes drawing these + labels makes sense as a source of clarity for the user, othertimes they + waste too much space and do not assist the user. + */ + void setDrawFieldLabels( bool enabled ); + + /** + @return True if the field labels are drawn, false otherwise. + */ + bool drawFieldLabels() const; + + /** + Sets if fields with no value should be drawn (of cause the label only, + but it allows for embedded editing sometimes...) + */ + void setShowEmptyFields( bool show ); + + /** + @return Wheather empty fields should be shown + */ + bool showEmptyFields() const; + + /** + @return the advisory internal margin in items. Setting a value above 1 means + a space between the item contents and the focus recttangle drawn around + the current item. The default value is 0. + The value should be used by CardViewItem and derived classes. + Note that this should not be greater than half of the minimal item width, + which is 80. It is currently not checked, so setting a value greater than 40 + will probably mean a crash in the items painting routine. + */ + // Note: I looked for a value in QStyle::PixelMetric to use, but I could + // not see a useful one. One may turn up in a future version of Qt. + uint itemMargin() const; + + /** + Sets the internal item margin. See itemMargin(). + */ + void setItemMargin( uint margin ); + + /** + @return the item spacing. + The item spacing is the space (in pixels) between each item in a + column, between the items and column separators if drawn, and between + the items and the borders of the widget. The default value is set to 10. + */ + // Note: There is no useful QStyle::PixelMetric to use for this atm. + // An option would be using KDialog::spacingHint(). + uint itemSpacing() const; + + /** + Sets the item spacing. + @see itemSpacing() + */ + void setItemSpacing( uint spacing ); + + /** + @return the width made available to the card items. + */ + int itemWidth() const; + + /** + Sets the width made available to card items. + */ + void setItemWidth( int width ); + + /** + Sets the header font + */ + void setHeaderFont( const QFont &fnt ); + + /** + @return the header font + */ + QFont headerFont() const; + + /** + Reimplementation from QWidget + */ + void setFont( const QFont &fnt ); + + /** + Sets the column separator width + */ + void setSeparatorWidth( int width ); + + /** + @return the column separator width + */ + int separatorWidth() const; + + /** + Sets the maximum number of lines to display pr field. + If set to 0 (the default) all lines will be displayed. + */ + void setMaxFieldLines( int howmany ); + + /** + @return the maximum number of lines pr field + */ + int maxFieldLines() const; + + signals: + /** + Emitted whenever the selection changes. This means a user highlighted + a new item or unhighlighted a currently selected item. + */ + void selectionChanged(); + + /** + Same as above method, only it carries the item that was selected. This + method will only be emitted in single select mode, since it defineds + which item was selected. + */ + void selectionChanged( CardViewItem* ); + + /** + This method is emitted whenever an item is clicked. + */ + void clicked( CardViewItem* ); + + /** + Emitted whenever the user 'executes' an item. This is dependant on + the KDE global config. This could be a single click or a doubleclick. + Also emitted when the return key is pressed on an item. + */ + void executed( CardViewItem* ); + + /** + Emitted whenever the user double clicks on an item. + */ + void doubleClicked( CardViewItem* ); + + /** + Emitted when the current item changes + */ + void currentChanged( CardViewItem* ); + + /** + Emitted when the return key is pressed in an item. + */ + void returnPressed( CardViewItem* ); + + /** + Emitted when the context menu is requested in some way. + */ + void contextMenuRequested( CardViewItem*, const QPoint& ); + + protected: + /** + Determines which cards intersect that region and tells them to paint + themselves. + */ + void drawContents( QPainter *p, int clipx, int clipy, int clipw, int cliph ); + + /** + Sets the layout to dirty and repaints. + */ + void resizeEvent( QResizeEvent* ); + + /** + Changes the direction the canvas scolls. + */ + void contentsWheelEvent( QWheelEvent* ); + + /** + Sets the layout to dirty and calls for a repaint. + */ + void setLayoutDirty( bool dirty ); + + /** + Does the math based on the bounding rect of the cards to properly + lay the cards out on the screen. This is only done if the layout is + marked as dirty. + */ + void calcLayout(); + + virtual void contentsMousePressEvent( QMouseEvent* ); + virtual void contentsMouseMoveEvent( QMouseEvent* ); + virtual void contentsMouseReleaseEvent( QMouseEvent* ); + virtual void contentsMouseDoubleClickEvent( QMouseEvent* ); + + virtual void enterEvent( QEvent* ); + virtual void leaveEvent( QEvent* ); + + virtual void focusInEvent( QFocusEvent* ); + virtual void focusOutEvent( QFocusEvent* ); + + virtual void keyPressEvent( QKeyEvent* ); + + /** + Overload this method to be told when a drag should be started. + In most cases you will want to start a drag event with the currently + selected item. + */ + virtual void startDrag(); + + private slots: + /** + Called by a timer to display a label with truncated text. + Pop up a label, if there is a field with obscured text or + label at the cursor position. + */ + void tryShowFullText(); + + private: + /** + draws and erases the rubber bands while columns are resized. + @p pos is the horizontal position inside the viewport to use as + the anchor. + If pos is 0, only erase is done. + */ + void drawRubberBands( int pos ); + + CardViewPrivate *d; +}; + +#endif diff --git a/kaddressbook/views/colorlistbox.cpp b/kaddressbook/views/colorlistbox.cpp new file mode 100644 index 000000000..37a2ac1f4 --- /dev/null +++ b/kaddressbook/views/colorlistbox.cpp @@ -0,0 +1,193 @@ +/* + * kmail: KDE mail client + * This file: Copyright (C) 2000 Espen Sand, espen@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. + * + */ + +#include <qpainter.h> + +#include <kcolordialog.h> +#include <kcolordrag.h> + +#include "colorlistbox.h" + +ColorListBox::ColorListBox( QWidget *parent, const char *name, WFlags f ) + :KListBox( parent, name, f ), mCurrentOnDragEnter(-1) +{ + connect( this, SIGNAL(selected(int)), this, SLOT(newColor(int)) ); + setAcceptDrops( true); +} + + +void ColorListBox::setEnabled( bool state ) +{ + if( state == isEnabled() ) + { + return; + } + + QListBox::setEnabled( state ); + for( uint i=0; i<count(); i++ ) + { + updateItem( i ); + } +} + + +void ColorListBox::setColor( uint index, const QColor &color ) +{ + if( index < count() ) + { + ColorListItem *colorItem = (ColorListItem*)item(index); + colorItem->setColor(color); + updateItem( colorItem ); + } +} + + +QColor ColorListBox::color( uint index ) const +{ + if( index < count() ) + { + ColorListItem *colorItem = (ColorListItem*)item(index); + return( colorItem->color() ); + } + else + { + return( black ); + } +} + + +void ColorListBox::newColor( int index ) +{ + if( isEnabled() == false ) + { + return; + } + + if( (uint)index < count() ) + { + QColor c = color( index ); + if( KColorDialog::getColor( c, this ) != QDialog::Rejected ) + { + setColor( index, c ); + } + } +} + + +void ColorListBox::dragEnterEvent( QDragEnterEvent *e ) +{ + if( KColorDrag::canDecode(e) && isEnabled() ) + { + mCurrentOnDragEnter = currentItem(); + e->accept( true ); + } + else + { + mCurrentOnDragEnter = -1; + e->accept( false ); + } +} + + +void ColorListBox::dragLeaveEvent( QDragLeaveEvent * ) +{ + if( mCurrentOnDragEnter != -1 ) + { + setCurrentItem( mCurrentOnDragEnter ); + mCurrentOnDragEnter = -1; + } +} + + +void ColorListBox::dragMoveEvent( QDragMoveEvent *e ) +{ + if( KColorDrag::canDecode(e) && isEnabled() ) + { + ColorListItem *item = (ColorListItem*)itemAt( e->pos() ); + if( item != 0 ) + { + setCurrentItem ( item ); + } + } +} + + +void ColorListBox::dropEvent( QDropEvent *e ) +{ + QColor color; + if( KColorDrag::decode( e, color ) ) + { + int index = currentItem(); + if( index != -1 ) + { + ColorListItem *colorItem = (ColorListItem*)item(index); + colorItem->setColor(color); + triggerUpdate( false ); // Redraw item + } + mCurrentOnDragEnter = -1; + } +} + + + +ColorListItem::ColorListItem( const QString &text, const QColor &color ) + : QListBoxItem(), mColor( color ), mBoxWidth( 30 ) +{ + setText( text ); +} + + +const QColor &ColorListItem::color( void ) +{ + return( mColor ); +} + + +void ColorListItem::setColor( const QColor &color ) +{ + mColor = color; +} + + +void ColorListItem::paint( QPainter *p ) +{ + QFontMetrics fm = p->fontMetrics(); + int h = fm.height(); + + p->drawText( mBoxWidth+3*2, fm.ascent() + fm.leading()/2, text() ); + + p->setPen( Qt::black ); + p->drawRect( 3, 1, mBoxWidth, h-1 ); + p->fillRect( 4, 2, mBoxWidth-2, h-3, mColor ); +} + + +int ColorListItem::height(const QListBox *lb ) const +{ + return( lb->fontMetrics().lineSpacing()+1 ); +} + + +int ColorListItem::width(const QListBox *lb ) const +{ + return( mBoxWidth + lb->fontMetrics().width( text() ) + 6 ); +} + +#include "colorlistbox.moc" diff --git a/kaddressbook/views/colorlistbox.h b/kaddressbook/views/colorlistbox.h new file mode 100644 index 000000000..06b2c4627 --- /dev/null +++ b/kaddressbook/views/colorlistbox.h @@ -0,0 +1,71 @@ +/* + * kmail: KDE mail client + * This file: Copyright (C) 2000 Espen Sand, espen@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. + * + */ + +#ifndef _COLOR_LISTBOX_H_ +#define _COLOR_LISTBOX_H_ + +#include <klistbox.h> + +class ColorListBox : public KListBox +{ + Q_OBJECT + + public: + ColorListBox( QWidget *parent=0, const char * name=0, WFlags f=0 ); + void setColor( uint index, const QColor &color ); + QColor color( uint index ) const; + + public slots: + virtual void setEnabled( bool state ); + + protected: + void dragEnterEvent( QDragEnterEvent *e ); + void dragLeaveEvent( QDragLeaveEvent *e ); + void dragMoveEvent( QDragMoveEvent *e ); + void dropEvent( QDropEvent *e ); + + private slots: + void newColor( int index ); + + private: + int mCurrentOnDragEnter; + +}; + + +class ColorListItem : public QListBoxItem +{ + public: + ColorListItem( const QString &text, const QColor &color=Qt::black ); + const QColor &color( void ); + void setColor( const QColor &color ); + + protected: + virtual void paint( QPainter * ); + virtual int height( const QListBox * ) const; + virtual int width( const QListBox * ) const; + + private: + QColor mColor; + int mBoxWidth; +}; + +#endif + diff --git a/kaddressbook/views/configurecardviewdialog.cpp b/kaddressbook/views/configurecardviewdialog.cpp new file mode 100644 index 000000000..8843d3c68 --- /dev/null +++ b/kaddressbook/views/configurecardviewdialog.cpp @@ -0,0 +1,319 @@ +/* + This file is part of KAddressBook. + Copyright (c) 2002 Mike Pilone <mpilone@slac.com> + + 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 <qstring.h> +#include <qlayout.h> +#include <qlabel.h> +#include <qcheckbox.h> +#include <qvbox.h> +#include <qgroupbox.h> +#include <qspinbox.h> +#include <qtabwidget.h> +#include <qwhatsthis.h> + +#include <kdebug.h> +#include <kglobal.h> +#include <kglobalsettings.h> +#include <klocale.h> +#include <kiconloader.h> +#include <kconfig.h> +#include <kfontdialog.h> +#include <kpushbutton.h> + +#include "colorlistbox.h" + +#include "configurecardviewdialog.h" + +///////////////////////////////// +// ConfigureCardViewDialog + +ConfigureCardViewWidget::ConfigureCardViewWidget( KABC::AddressBook *ab, QWidget *parent, + const char *name ) + : ViewConfigureWidget( ab, parent, name ) +{ + QWidget *page = addPage( i18n( "Look & Feel" ), QString::null, + DesktopIcon( "looknfeel" ) ); + mAdvancedPage = new CardViewLookNFeelPage( page ); +} + +ConfigureCardViewWidget::~ConfigureCardViewWidget() +{ +} + +void ConfigureCardViewWidget::restoreSettings( KConfig *config ) +{ + ViewConfigureWidget::restoreSettings( config ); + + mAdvancedPage->restoreSettings( config ); +} + +void ConfigureCardViewWidget::saveSettings( KConfig *config ) +{ + ViewConfigureWidget::saveSettings( config ); + + mAdvancedPage->saveSettings( config ); +} + +//////////////////////// +// CardViewLookNFeelPage +CardViewLookNFeelPage::CardViewLookNFeelPage( QWidget *parent, const char *name ) + : QVBox( parent, name ) +{ + initGUI(); +} + +CardViewLookNFeelPage::~CardViewLookNFeelPage() +{ +} + +void CardViewLookNFeelPage::restoreSettings( KConfig *config ) +{ + // colors + cbEnableCustomColors->setChecked( config->readBoolEntry( "EnableCustomColors", false ) ); + QColor c; + c = KGlobalSettings::baseColor(); + lbColors->insertItem( new ColorListItem( i18n("Background Color"), + config->readColorEntry( "BackgroundColor", &c ) ) ); + c = colorGroup().foreground(); + lbColors->insertItem( new ColorListItem( i18n("Text Color"), + config->readColorEntry( "TextColor", &c ) ) ); + c = colorGroup().button(); + lbColors->insertItem( new ColorListItem( i18n("Header, Border & Separator Color"), + config->readColorEntry( "HeaderColor", &c ) ) ); + c = colorGroup().buttonText(); + lbColors->insertItem( new ColorListItem( i18n("Header Text Color"), + config->readColorEntry( "HeaderTextColor", &c ) ) ); + c = colorGroup().highlight(); + lbColors->insertItem( new ColorListItem( i18n("Highlight Color"), + config->readColorEntry( "HighlightColor", &c ) ) ); + c = colorGroup().highlightedText(); + lbColors->insertItem( new ColorListItem( i18n("Highlighted Text Color"), + config->readColorEntry( "HighlightedTextColor", &c ) ) ); + + enableColors(); + + // fonts + QFont fnt = font(); + updateFontLabel( config->readFontEntry( "TextFont", &fnt ), (QLabel*)lTextFont ); + fnt.setBold( true ); + updateFontLabel( config->readFontEntry( "HeaderFont", &fnt ), (QLabel*)lHeaderFont ); + cbEnableCustomFonts->setChecked( config->readBoolEntry( "EnableCustomFonts", false ) ); + enableFonts(); + + // layout + sbMargin->setValue( config->readNumEntry( "ItemMargin", 0 ) ); + sbSpacing->setValue( config->readNumEntry( "ItemSpacing", 10 ) ); + sbSepWidth->setValue( config->readNumEntry( "SeparatorWidth", 2 ) ); + cbDrawSeps->setChecked( config->readBoolEntry( "DrawSeparators", true ) ); + cbDrawBorders->setChecked( config->readBoolEntry( "DrawBorder", true ) ); + + // behaviour + cbShowFieldLabels->setChecked( config->readBoolEntry( "DrawFieldLabels", false ) ); + cbShowEmptyFields->setChecked( config->readBoolEntry( "ShowEmptyFields", false ) ); +} + +void CardViewLookNFeelPage::saveSettings( KConfig *config ) +{ + // colors + config->writeEntry( "EnableCustomColors", cbEnableCustomColors->isChecked() ); + if ( cbEnableCustomColors->isChecked() ) // ?? - Hmmm. + { + config->writeEntry( "BackgroundColor", lbColors->color( 0 ) ); + config->writeEntry( "TextColor", lbColors->color( 1 ) ); + config->writeEntry( "HeaderColor", lbColors->color( 2 ) ); + config->writeEntry( "HeaderTextColor", lbColors->color( 3 ) ); + config->writeEntry( "HighlightColor", lbColors->color( 4 ) ); + config->writeEntry( "HighlightedTextColor", lbColors->color( 5 ) ); + } + // fonts + config->writeEntry( "EnableCustomFonts", cbEnableCustomFonts->isChecked() ); + if ( cbEnableCustomFonts->isChecked() ) + { + config->writeEntry( "TextFont", lTextFont->font() ); + config->writeEntry( "HeaderFont", lHeaderFont->font() ); + } + // layout + config->writeEntry( "ItemMargin", sbMargin->value() ); + config->writeEntry( "ItemSpacing", sbSpacing->value() ); + config->writeEntry( "SeparatorWidth", sbSepWidth->value() ); + config->writeEntry("DrawBorder", cbDrawBorders->isChecked()); + config->writeEntry("DrawSeparators", cbDrawSeps->isChecked()); + + // behaviour + config->writeEntry("DrawFieldLabels", cbShowFieldLabels->isChecked()); + config->writeEntry("ShowEmptyFields", cbShowEmptyFields->isChecked()); +} + +void CardViewLookNFeelPage::setTextFont() +{ + QFont f( lTextFont->font() ); + if ( KFontDialog::getFont( f, false, this ) == QDialog::Accepted ) + updateFontLabel( f, lTextFont ); +} + +void CardViewLookNFeelPage::setHeaderFont() +{ + QFont f( lHeaderFont->font() ); + if ( KFontDialog::getFont( f,false, this ) == QDialog::Accepted ) + updateFontLabel( f, lHeaderFont ); +} + +void CardViewLookNFeelPage::enableFonts() +{ + vbFonts->setEnabled( cbEnableCustomFonts->isChecked() ); +} + +void CardViewLookNFeelPage::enableColors() +{ + lbColors->setEnabled( cbEnableCustomColors->isChecked() ); +} + +void CardViewLookNFeelPage::initGUI() +{ + int spacing = KDialog::spacingHint(); + int margin = KDialog::marginHint(); + + QTabWidget *tabs = new QTabWidget( this ); + + // Layout + QVBox *loTab = new QVBox( this, "layouttab" ); + + loTab->setSpacing( spacing ); + loTab->setMargin( margin ); + + QGroupBox *gbGeneral = new QGroupBox( 1, Qt::Horizontal, i18n("General"), loTab ); + + cbDrawSeps = new QCheckBox( i18n("Draw &separators"), gbGeneral ); + + QHBox *hbSW = new QHBox( gbGeneral ); + QLabel *lSW = new QLabel( i18n("Separator &width:"), hbSW ); + sbSepWidth = new QSpinBox( 1, 50, 1, hbSW ); + lSW->setBuddy( sbSepWidth); + + QHBox *hbPadding = new QHBox( gbGeneral ); + QLabel *lSpacing = new QLabel( i18n("&Padding:"), hbPadding ); + sbSpacing = new QSpinBox( 0, 100, 1, hbPadding ); + lSpacing->setBuddy( sbSpacing ); + + QGroupBox *gbCards = new QGroupBox( 1, Qt::Horizontal, i18n("Cards"), loTab ); + + QHBox *hbMargin = new QHBox( gbCards ); + QLabel *lMargin = new QLabel( i18n("&Margin:"), hbMargin ); + sbMargin = new QSpinBox( 0, 100, 1, hbMargin ); + lMargin->setBuddy( sbMargin ); + + cbDrawBorders = new QCheckBox( i18n("Draw &borders"), gbCards ); + + loTab->setStretchFactor( new QWidget( loTab ), 1 ); + + QWhatsThis::add( sbMargin, i18n( + "The item margin is the distance (in pixels) between the item edge and the item data. Most noticeably, " + "incrementing the item margin will add space between the focus rectangle and the item data." + ) ); + QWhatsThis::add( lMargin, QWhatsThis::textFor( sbMargin ) ); + QWhatsThis::add( sbSpacing, i18n( + "The item spacing decides the distance (in pixels) between the items and anything else: the view " + "borders, other items or column separators." + ) ); + QWhatsThis::add( lSpacing, QWhatsThis::textFor( sbSpacing ) ); + QWhatsThis::add( sbSepWidth, i18n("Sets the width of column separators") ); + QWhatsThis::add( lSW, QWhatsThis::textFor( sbSepWidth ) ); + + tabs->addTab( loTab, i18n("&Layout") ); + + // Colors + QVBox *colorTab = new QVBox( this, "colortab" ); + colorTab->setSpacing( spacing ); + colorTab->setMargin( spacing ); + cbEnableCustomColors = new QCheckBox( i18n("&Enable custom colors"), colorTab ); + connect( cbEnableCustomColors, SIGNAL(clicked()), this, SLOT(enableColors()) ); + lbColors = new ColorListBox( colorTab ); + tabs->addTab( colorTab, i18n("&Colors") ); + + QWhatsThis::add( cbEnableCustomColors, i18n( + "If custom colors is enabled, you may choose the colors for the view below. " + "Otherwise colors from your current KDE color scheme are used." + ) ); + QWhatsThis::add( lbColors, i18n( + "Double click or press RETURN on a item to select a color for the related strings in the view." + ) ); + + // Fonts + QVBox *fntTab = new QVBox( this, "fonttab" ); + + fntTab->setSpacing( spacing ); + fntTab->setMargin( spacing ); + + cbEnableCustomFonts = new QCheckBox( i18n("&Enable custom fonts"), fntTab ); + connect( cbEnableCustomFonts, SIGNAL(clicked()), this, SLOT(enableFonts()) ); + + vbFonts = new QWidget( fntTab ); + QGridLayout *gFnts = new QGridLayout( vbFonts, 2, 3 ); + gFnts->setSpacing( spacing ); + gFnts->setAutoAdd( true ); + gFnts->setColStretch( 1, 1 ); + QLabel *lTFnt = new QLabel( i18n("&Text font:"), vbFonts ); + lTextFont = new QLabel( vbFonts ); + lTextFont->setFrameStyle( QFrame::Panel|QFrame::Sunken ); + btnFont = new KPushButton( i18n("Choose..."), vbFonts ); + lTFnt->setBuddy( btnFont ); + connect( btnFont, SIGNAL(clicked()), this, SLOT(setTextFont()) ); + + QLabel *lHFnt = new QLabel( i18n("&Header font:"), vbFonts ); + lHeaderFont = new QLabel( vbFonts ); + lHeaderFont->setFrameStyle( QFrame::Panel|QFrame::Sunken ); + btnHeaderFont = new KPushButton( i18n("Choose..."), vbFonts ); + lHFnt->setBuddy( btnHeaderFont ); + connect( btnHeaderFont, SIGNAL(clicked()), this, SLOT(setHeaderFont()) ); + + fntTab->setStretchFactor( new QWidget( fntTab ), 1 ); + + QWhatsThis::add( cbEnableCustomFonts, i18n( + "If custom fonts are enabled, you may choose which fonts to use for this view below. " + "Otherwise the default KDE font will be used, in bold style for the header and " + "normal style for the data." + ) ); + + tabs->addTab( fntTab, i18n("&Fonts") ); + + // Behaviour + QVBox *behaviourTab = new QVBox( this ); + behaviourTab->setMargin( margin ); + behaviourTab->setSpacing( spacing ); + + cbShowEmptyFields = new QCheckBox( i18n("Show &empty fields"), behaviourTab ); + cbShowFieldLabels = new QCheckBox( i18n("Show field &labels"), behaviourTab ); + + behaviourTab->setStretchFactor( new QWidget( behaviourTab ), 1 ); + + tabs->addTab( behaviourTab, i18n("Be&havior") ); + +} + +void CardViewLookNFeelPage::updateFontLabel( QFont fnt, QLabel *l ) +{ + l->setFont( fnt ); + l->setText( QString( fnt.family() + " %1" ).arg( fnt.pointSize() ) ); +} + +#include "configurecardviewdialog.moc" diff --git a/kaddressbook/views/configurecardviewdialog.h b/kaddressbook/views/configurecardviewdialog.h new file mode 100644 index 000000000..a37db6cb3 --- /dev/null +++ b/kaddressbook/views/configurecardviewdialog.h @@ -0,0 +1,113 @@ +/* + This file is part of KAddressBook. + Copyright (c) 2002 Mike Pilone <mpilone@slac.com> + + 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 CONFIGURECARDVIEWDIALOG_H +#define CONFIGURECARDVIEWDIALOG_H + +#include "viewconfigurewidget.h" + +#include <qvbox.h> +#include <qwidget.h> +#include <qfont.h> + +class QString; +class QWidget; +class QCheckBox; +class QLabel; +class KConfig; + +namespace KABC { class AddressBook; } + +class CardViewLookAndFeelPage; + +/** + Configure dialog for the card view. This dialog inherits from the + standard view dialog in order to add a custom page for the card + view. + */ +class ConfigureCardViewWidget : public ViewConfigureWidget +{ + public: + ConfigureCardViewWidget( KABC::AddressBook *ab, QWidget *parent, const char *name ); + virtual ~ConfigureCardViewWidget(); + + virtual void restoreSettings( KConfig* ); + virtual void saveSettings( KConfig* ); + + private: + class CardViewLookNFeelPage *mAdvancedPage; +}; + +/** + Card View Advanced LookNFeel settings widget: + this is a tabbed widget with 3 tabs: + Fonts + * text font + * header font + + Colors + * background color + * text color + * highlight color + * title/sep text color + * title/sep bg color + + Layout + * item margin + * item spacing +*/ + +class CardViewLookNFeelPage : public QVBox { + + Q_OBJECT + + public: + CardViewLookNFeelPage( QWidget *parent=0, const char *name=0 ); + ~CardViewLookNFeelPage(); + + void restoreSettings( KConfig* ); + void saveSettings( KConfig* ); + + private slots: + void setTextFont(); + void setHeaderFont(); + void enableFonts(); + void enableColors(); + + private: + void initGUI(); + void updateFontLabel( QFont, QLabel * ); + + QCheckBox *cbEnableCustomFonts, + *cbEnableCustomColors, + *cbDrawSeps, *cbDrawBorders, + *cbShowFieldLabels, *cbShowEmptyFields; + class ColorListBox *lbColors; + QLabel *lTextFont, *lHeaderFont; + class KPushButton *btnFont, *btnHeaderFont; + class QSpinBox *sbMargin, *sbSpacing, *sbSepWidth; + + class QWidget *vbFonts; +}; + +#endif diff --git a/kaddressbook/views/configuretableviewdialog.cpp b/kaddressbook/views/configuretableviewdialog.cpp new file mode 100644 index 000000000..d01c4d7df --- /dev/null +++ b/kaddressbook/views/configuretableviewdialog.cpp @@ -0,0 +1,156 @@ +/* + This file is part of KAddressBook. + Copyright (c) 2002 Mike Pilone <mpilone@slac.com> + + 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 <qstring.h> +#include <qwidget.h> +#include <qlayout.h> +#include <qradiobutton.h> +#include <qcheckbox.h> +#include <qvbox.h> +#include <qbuttongroup.h> + +#include <kdeversion.h> +#include <kglobal.h> +#include <klocale.h> +#include <klineedit.h> +#include <kurlrequester.h> +#include <kiconloader.h> +#include <kimageio.h> +#include <kconfig.h> + +#include "configuretableviewdialog.h" + +ConfigureTableViewWidget::ConfigureTableViewWidget( KABC::AddressBook *ab, + QWidget *parent, + const char *name ) + : ViewConfigureWidget( ab, parent, name ) +{ + QWidget *page = addPage( i18n( "Look & Feel" ), QString::null, + KGlobal::iconLoader()->loadIcon( "looknfeel", + KIcon::Panel ) ); + + mPage = new LookAndFeelPage( page ); +} + +ConfigureTableViewWidget::~ConfigureTableViewWidget() +{ +} + +void ConfigureTableViewWidget::restoreSettings( KConfig *config ) +{ + ViewConfigureWidget::restoreSettings( config ); + + mPage->restoreSettings( config ); +} + +void ConfigureTableViewWidget::saveSettings( KConfig *config ) +{ + ViewConfigureWidget::saveSettings( config ); + + mPage->saveSettings( config ); +} + + + +LookAndFeelPage::LookAndFeelPage(QWidget *parent, const char *name) + : QWidget(parent, name) +{ + initGUI(); + + // Set initial state + enableBackgroundToggled(mBackgroundBox->isChecked()); +} + +void LookAndFeelPage::restoreSettings( KConfig *config ) +{ + mAlternateButton->setChecked(config->readBoolEntry("ABackground", true)); + mLineButton->setChecked(config->readBoolEntry("SingleLine", false)); + mToolTipBox->setChecked(config->readBoolEntry("ToolTips", true)); + + if (!mAlternateButton->isChecked() && !mLineButton->isChecked()) + mNoneButton->setChecked(true); + + mBackgroundBox->setChecked(config->readBoolEntry("Background", false)); + mBackgroundName->lineEdit()->setText(config->readPathEntry("BackgroundName")); +#if KDE_IS_VERSION(3,2,90) + mIMPresenceBox->setChecked( config->readBoolEntry( "InstantMessagingPresence", false ) ); +#endif +} + +void LookAndFeelPage::saveSettings( KConfig *config ) +{ + config->writeEntry("ABackground", mAlternateButton->isChecked()); + config->writeEntry("SingleLine", mLineButton->isChecked()); + config->writeEntry("ToolTips", mToolTipBox->isChecked()); + config->writeEntry("Background", mBackgroundBox->isChecked()); + config->writePathEntry("BackgroundName", mBackgroundName->lineEdit()->text()); +#if KDE_IS_VERSION(3,2,90) + config->writeEntry( "InstantMessagingPresence", mIMPresenceBox->isChecked() ); +#endif +} + +void LookAndFeelPage::initGUI() +{ + QVBoxLayout *layout = new QVBoxLayout(this, 0, KDialogBase::spacingHint()); + + QButtonGroup *group = new QButtonGroup(1, Qt::Horizontal, + i18n("Row Separator"), this); + layout->addWidget(group); + + mAlternateButton = new QRadioButton(i18n("Alternating backgrounds"), + group, "mAlternateButton"); + mLineButton = new QRadioButton(i18n("Single line"), group, "mLineButton"); + mNoneButton = new QRadioButton(i18n("None"), group, "mNoneButton"); + + // Background Checkbox/Selector + QHBoxLayout *backgroundLayout = new QHBoxLayout(); + layout->addLayout(backgroundLayout); + + mBackgroundBox = new QCheckBox(i18n("Enable background image:"), this, + "mBackgroundBox"); + connect(mBackgroundBox, SIGNAL(toggled(bool)), + SLOT(enableBackgroundToggled(bool))); + backgroundLayout->addWidget(mBackgroundBox); + + mBackgroundName = new KURLRequester(this, "mBackgroundName"); + mBackgroundName->setMode(KFile::File | KFile::ExistingOnly | + KFile::LocalOnly); + mBackgroundName->setFilter(KImageIO::pattern(KImageIO::Reading)); + backgroundLayout->addWidget(mBackgroundName); + + // ToolTip Checkbox + mToolTipBox = new QCheckBox(i18n("Enable contact tooltips"), this, + "mToolTipBox"); + layout->addWidget(mToolTipBox); +#if KDE_IS_VERSION(3,2,90) + mIMPresenceBox = new QCheckBox( i18n( "Show instant messaging presence" ), this, "mIMPresenceBox" ); + layout->addWidget( mIMPresenceBox ); +#endif +} + +void LookAndFeelPage::enableBackgroundToggled(bool enabled) +{ + mBackgroundName->setEnabled(enabled); +} + +#include "configuretableviewdialog.moc" diff --git a/kaddressbook/views/configuretableviewdialog.h b/kaddressbook/views/configuretableviewdialog.h new file mode 100644 index 000000000..1260971c2 --- /dev/null +++ b/kaddressbook/views/configuretableviewdialog.h @@ -0,0 +1,89 @@ +/* + This file is part of KAddressBook. + Copyright (c) 2002 Mike Pilone <mpilone@slac.com> + + 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 CONFIGURETABLEVIEWDIALOG_H +#define CONFIGURETABLEVIEWDIALOG_H + +#include "viewconfigurewidget.h" + +class QString; +class QWidget; +class QRadioButton; +class QCheckBox; +class KURLRequester; +class KConfig; + +namespace KABC { class AddressBook; } + +class LookAndFeelPage; + +/** + Configure dialog for the table view. This dialog inherits from the + standard view dialog in order to add a custom page for the table + view. + */ +class ConfigureTableViewWidget : public ViewConfigureWidget +{ + public: + ConfigureTableViewWidget( KABC::AddressBook *ab, QWidget *parent, const char *name ); + virtual ~ConfigureTableViewWidget(); + + virtual void restoreSettings( KConfig* ); + virtual void saveSettings( KConfig* ); + + private: + void initGUI(); + + LookAndFeelPage *mPage; +}; + +/** + Internal class. It is only defined here for moc +*/ +class LookAndFeelPage : public QWidget +{ + Q_OBJECT + + public: + LookAndFeelPage( QWidget *parent, const char *name = 0 ); + ~LookAndFeelPage() {} + + void restoreSettings( KConfig* ); + void saveSettings( KConfig* ); + + protected slots: + void enableBackgroundToggled( bool ); + + private: + void initGUI(); + + QRadioButton *mAlternateButton; + QRadioButton *mLineButton; + QRadioButton *mNoneButton; + QCheckBox *mToolTipBox; + KURLRequester *mBackgroundName; + QCheckBox *mBackgroundBox; + QCheckBox *mIMPresenceBox; +}; + +#endif diff --git a/kaddressbook/views/contactlistview.cpp b/kaddressbook/views/contactlistview.cpp new file mode 100644 index 000000000..1deadc190 --- /dev/null +++ b/kaddressbook/views/contactlistview.cpp @@ -0,0 +1,380 @@ +/* + This file is part of KAddressBook. + Copyright (c) 2002 Mike Pilone <mpilone@slac.com> + + 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 <qheader.h> +#include <qiconset.h> +#include <qimage.h> +#include <qdragobject.h> +#include <qcombobox.h> +#include <qpainter.h> +#include <qbrush.h> +#include <qevent.h> + +#include <klocale.h> +#include <kglobalsettings.h> +#include <kdebug.h> +#include <kconfig.h> +#include <kapplication.h> +#include <kurl.h> +#include <kabc/addressbook.h> +#include <kabc/addressee.h> +#include <kimproxy.h> + +#include "kaddressbooktableview.h" + +#include "contactlistview.h" + +///////////////////////////////// +// DynamicTip Methods + +DynamicTip::DynamicTip( ContactListView *parent) + : QToolTip( parent ) +{ +} + +void DynamicTip::maybeTip( const QPoint &pos ) +{ + if (!parentWidget()->inherits( "ContactListView" )) + return; + + ContactListView *plv = (ContactListView*)parentWidget(); + if (!plv->tooltips()) + return; + + QPoint posVp = plv->viewport()->pos(); + + QListViewItem *lvi = plv->itemAt( pos - posVp ); + if (!lvi) + return; + + ContactListViewItem *plvi = dynamic_cast< ContactListViewItem* >(lvi); + if (!plvi) + return; + + QString s; + QRect r = plv->itemRect( lvi ); + r.moveBy( posVp.x(), posVp.y() ); + + //kdDebug(5720) << "Tip rec: " << r.x() << "," << r.y() << "," << r.width() + // << "," << r.height() << endl; + + KABC::Addressee a = plvi->addressee(); + if (a.isEmpty()) + return; + + s += i18n("label: value", "%1: %2").arg(a.formattedNameLabel()) + .arg(a.formattedName()); + + s += '\n'; + s += i18n("label: value", "%1: %2").arg(a.organizationLabel()) + .arg(a.organization()); + + QString notes = a.note().stripWhiteSpace(); + if ( !notes.isEmpty() ) { + notes += '\n'; + s += '\n' + i18n("label: value", "%1: \n").arg(a.noteLabel()); + QFontMetrics fm( font() ); + + // Begin word wrap code based on QMultiLineEdit code + int i = 0; + bool doBreak = false; + int linew = 0; + int lastSpace = -1; + int a = 0; + int lastw = 0; + + while ( i < int(notes.length()) ) { + doBreak = false; + if ( notes[i] != '\n' ) + linew += fm.width( notes[i] ); + + if ( lastSpace >= a && notes[i] != '\n' ) + if (linew >= parentWidget()->width()) { + doBreak = true; + if ( lastSpace > a ) { + i = lastSpace; + linew = lastw; + } + else + i = QMAX( a, i-1 ); + } + + if ( notes[i] == '\n' || doBreak ) { + s += notes.mid( a, i - a + (doBreak?1:0) ) +"\n"; + + a = i + 1; + lastSpace = a; + linew = 0; + } + + if ( notes[i].isSpace() ) { + lastSpace = i; + lastw = linew; + } + + if ( lastSpace <= a ) { + lastw = linew; + } + + ++i; + } + } + + tip( r, s ); +} + +/////////////////////////// +// ContactListViewItem Methods + +ContactListViewItem::ContactListViewItem(const KABC::Addressee &a, + ContactListView *parent, + KABC::AddressBook *doc, + const KABC::Field::List &fields, + KIMProxy *proxy ) + : KListViewItem(parent), mAddressee(a), mFields( fields ), + parentListView( parent ), mDocument(doc), mIMProxy( proxy ) +{ + if ( mIMProxy ) + mHasIM = mIMProxy->isPresent( mAddressee.uid() ); + else + mHasIM = false; + refresh(); +} + +QString ContactListViewItem::key(int column, bool ascending) const +{ + // Preserve behaviour of QListViewItem::key(), otherwise we cause a crash if the column does not exist + if ( column >= parentListView->columns() ) + return QString::null; + +#if KDE_VERSION >= 319 + Q_UNUSED( ascending ) + if ( parentListView->showIM() ) { + // in this case, one column is reserved for IM presence + // so we have to process it differently + if ( column == parentListView->imColumn() ) { + // increment by one before converting to string so that -1 is not greater than 1 + // create the sort key by taking the numeric status 0 low, 5 high, and subtracting it from 5 + // so that the default ascending gives online before offline, etc. + QString key = QString::number( 5 - ( mIMProxy->presenceNumeric( mAddressee.uid() ) + 1 ) ); + return key; + } + else { + return mFields[ column ]->sortKey( mAddressee ); + } + } + else + return mFields[ column ]->sortKey( mAddressee ); +#else + return QListViewItem::key( column, ascending ).lower(); +#endif +} + +void ContactListViewItem::paintCell(QPainter * p, + const QColorGroup & cg, + int column, + int width, + int align) +{ + KListViewItem::paintCell(p, cg, column, width, align); + + if ( !p ) + return; + + if (parentListView->singleLine()) { + p->setPen( parentListView->alternateColor() ); + p->drawLine( 0, height() - 1, width, height() - 1 ); + } +} + + +ContactListView *ContactListViewItem::parent() +{ + return parentListView; +} + + +void ContactListViewItem::refresh() +{ + // Update our addressee, since it may have changed else were + mAddressee = mDocument->findByUid(mAddressee.uid()); + if (mAddressee.isEmpty()) + return; + + int i = 0; + // don't show unknown presence, it's not interesting + if ( mHasIM ) { + if ( mIMProxy->presenceNumeric( mAddressee.uid() ) > 0 ) + setPixmap( parentListView->imColumn(), mIMProxy->presenceIcon( mAddressee.uid() ) ); + else + setPixmap( parentListView->imColumn(), QPixmap() ); + } + + KABC::Field::List::ConstIterator it; + for ( it = mFields.begin(); it != mFields.end(); ++it ) { + if ( (*it)->label() == KABC::Addressee::birthdayLabel() ) { + QDate date = mAddressee.birthday().date(); + if ( date.isValid() ) + setText( i++, KGlobal::locale()->formatDate( date, true ) ); + else + setText( i++, "" ); + } else + setText( i++, (*it)->value( mAddressee ) ); + } +} + +void ContactListViewItem::setHasIM( bool hasIM ) +{ + mHasIM = hasIM; +} + +/////////////////////////////// +// ContactListView + +ContactListView::ContactListView(KAddressBookTableView *view, + KABC::AddressBook* /* doc */, + QWidget *parent, + const char *name ) + : KListView( parent, name ), + pabWidget( view ), + oldColumn( 0 ) +{ + mABackground = true; + mSingleLine = false; + mToolTips = true; + mShowIM = true; + mAlternateColor = KGlobalSettings::alternateBackgroundColor(); + + setAlternateBackgroundEnabled(mABackground); + setAcceptDrops( true ); + viewport()->setAcceptDrops( true ); + setAllColumnsShowFocus( true ); + setShowSortIndicator(true); + setSelectionModeExt( KListView::Extended ); + setDropVisualizer(false); + + connect(this, SIGNAL(dropped(QDropEvent*)), + this, SLOT(itemDropped(QDropEvent*))); + + new DynamicTip( this ); +} + +void ContactListView::paintEmptyArea( QPainter * p, const QRect & rect ) +{ + QBrush b = palette().brush(QPalette::Active, QColorGroup::Base); + + // Get the brush, which will have the background pixmap if there is one. + if (b.pixmap()) + { + p->drawTiledPixmap( rect.left(), rect.top(), rect.width(), rect.height(), + *(b.pixmap()), + rect.left() + contentsX(), + rect.top() + contentsY() ); + } + + else + { + // Do a normal paint + KListView::paintEmptyArea(p, rect); + } +} + +void ContactListView::contentsMousePressEvent(QMouseEvent* e) +{ + presspos = e->pos(); + KListView::contentsMousePressEvent(e); +} + + +// To initiate a drag operation +void ContactListView::contentsMouseMoveEvent( QMouseEvent *e ) +{ + if ((e->state() & LeftButton) && (e->pos() - presspos).manhattanLength() > 4 ) { + emit startAddresseeDrag(); + } + else + KListView::contentsMouseMoveEvent( e ); +} + +bool ContactListView::acceptDrag(QDropEvent *e) const +{ + return QTextDrag::canDecode(e); +} + +void ContactListView::itemDropped(QDropEvent *e) +{ + contentsDropEvent(e); +} + +void ContactListView::contentsDropEvent( QDropEvent *e ) +{ + emit addresseeDropped(e); +} + +void ContactListView::setAlternateBackgroundEnabled(bool enabled) +{ + mABackground = enabled; + + if (mABackground) + { + setAlternateBackground(mAlternateColor); + } + else + { + setAlternateBackground(QColor()); + } +} + +void ContactListView::setBackgroundPixmap(const QString &filename) +{ + if (filename.isEmpty()) + { + unsetPalette(); + } + else + { + setPaletteBackgroundPixmap(QPixmap(filename)); + } +} + +void ContactListView::setShowIM( bool enabled ) +{ + mShowIM = enabled; +} + +bool ContactListView::showIM() +{ + return mShowIM; +} + +void ContactListView::setIMColumn( int column ) +{ + mInstantMsgColumn = column; +} + +int ContactListView::imColumn() +{ + return mInstantMsgColumn; +} + +#include "contactlistview.moc" diff --git a/kaddressbook/views/contactlistview.h b/kaddressbook/views/contactlistview.h new file mode 100644 index 000000000..c018e4c2b --- /dev/null +++ b/kaddressbook/views/contactlistview.h @@ -0,0 +1,176 @@ +/* + This file is part of KAddressBook. + Copyright (c) 2002 Mike Pilone <mpilone@slac.com> + + 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 CONTACTLISTVIEW_H +#define CONTACTLISTVIEW_H + +#include <qcolor.h> +#include <qpixmap.h> +#include <qtooltip.h> +#include <qstring.h> + +#include <klistview.h> + +#include <kabc/field.h> + +class QDropEvent; +class KAddressBookTableView; +class ContactListView; +class KIMProxy; + +/** The whole tooltip design needs a lot of work. Currently it is +* hacked together to function. +*/ +class DynamicTip : public QToolTip +{ + public: + DynamicTip( ContactListView * parent ); + + protected: + void maybeTip( const QPoint & ); + + private: +}; + +class ContactListViewItem : public KListViewItem +{ + +public: + ContactListViewItem(const KABC::Addressee &a, ContactListView* parent, + KABC::AddressBook *doc, const KABC::Field::List &fields, KIMProxy *proxy ); + const KABC::Addressee &addressee() const { return mAddressee; } + virtual void refresh(); + virtual ContactListView* parent(); + virtual QString key ( int, bool ) const; + void setHasIM( bool hasIM ); + /** Adds the border around the cell if the user wants it. + * This is how the single line config option is implemented. + */ + virtual void paintCell(QPainter * p, const QColorGroup & cg, + int column, int width, int align ); + +private: + KABC::Addressee mAddressee; + KABC::Field::List mFields; + ContactListView *parentListView; + KABC::AddressBook *mDocument; + KIMProxy *mIMProxy; + bool mHasIM; +}; + + +///////////////////////////////////////////// +// ContactListView + +class ContactListView : public KListView +{ + Q_OBJECT + +public: + ContactListView(KAddressBookTableView *view, + KABC::AddressBook *doc, + QWidget *parent, + const char *name = 0L ); + virtual ~ContactListView() {} + //void resort(); + + /** Returns true if tooltips should be displayed, false otherwise + */ + bool tooltips() const { return mToolTips; } + void setToolTipsEnabled(bool enabled) { mToolTips = enabled; } + + bool alternateBackground() const { return mABackground; } + void setAlternateBackgroundEnabled(bool enabled); + + bool singleLine() const { return mSingleLine; } + void setSingleLineEnabled(bool enabled) { mSingleLine = enabled; } + + const QColor &alternateColor() const { return mAlternateColor; } + + /** Sets the background pixmap to <i>filename</i>. If the + * QString is empty (QString::isEmpty()), then the background + * pixmap will be disabled. + */ + void setBackgroundPixmap(const QString &filename); + + /** + * Sets whether instant messaging presence should be shown in the first column + */ + void setShowIM( bool enabled ); + + /** + * Is presence being shown? + */ + bool showIM(); + + /** + * Set the column index of the column used for instant messaging presence. + * This method is necessary because presence, unlike the other fields, is not + * a KABC::Field, and cannot be handled using their methods. + * TODO: make presence a KABC::Field post 3.3 + */ + void setIMColumn( int column ); + + /** + * get the column used for IM presence + */ + int imColumn(); + +protected: + /** Paints the background pixmap in the empty area. This method is needed + * since Qt::FixedPixmap will not scroll with the list view. + */ + virtual void paintEmptyArea( QPainter * p, const QRect & rect ); + virtual void contentsMousePressEvent(QMouseEvent*); + void contentsMouseMoveEvent( QMouseEvent *e ); + void contentsDropEvent( QDropEvent *e ); + virtual bool acceptDrag(QDropEvent *e) const; + +protected slots: + void itemDropped(QDropEvent *e); + +public slots: + +signals: + void startAddresseeDrag(); + void addresseeDropped(QDropEvent *); + +private: + KAddressBookTableView *pabWidget; + int oldColumn; + int column; + bool ascending; + + bool mABackground; + bool mSingleLine; + bool mToolTips; + bool mShowIM; + + QColor mAlternateColor; + + QPoint presspos; + int mInstantMsgColumn; +}; + + +#endif diff --git a/kaddressbook/views/iconview.desktop b/kaddressbook/views/iconview.desktop new file mode 100644 index 000000000..59853a70e --- /dev/null +++ b/kaddressbook/views/iconview.desktop @@ -0,0 +1,76 @@ +[Desktop Entry] +X-KDE-Library=libkaddrbk_iconview +Name=Icon View +Name[af]=Ikoon Aansig +Name[ar]=عرض الأيقونات +Name[az]=Timsal Görünüşü +Name[be]=У выглядзе піктаграмаў +Name[bg]=Преглед като икони +Name[br]=Gwel Arlun +Name[bs]=Ikone +Name[ca]=Vista d'icona +Name[cs]=Pohled s ikonami +Name[cy]=Gweld Eicon +Name[da]=Ikon-visning +Name[de]=Symbolansicht +Name[el]=Προβολή εικονιδίων +Name[eo]=Piktogramrigardo +Name[es]=Vista de icono +Name[et]=Ikoonivaade +Name[eu]=Ikono ikuspegia +Name[fa]=نمای شمایل +Name[fi]=Kuvakenäkymä +Name[fr]=Icônes +Name[fy]=Byldkaikewerjefte +Name[ga]=Amharc Deilbhíní +Name[gl]=Vista en iconas +Name[he]=תצוגת סמלים +Name[hi]=प्रतीक दृश्य +Name[hr]=Ikonski pogled +Name[hu]=Ikonos nézet +Name[id]=Tampilan Ikon +Name[is]=Táknmyndasýn +Name[it]=Vista a icone +Name[ja]=アイコンビュー +Name[ka]=ხატულების ჩვენება +Name[kk]=Таңбаша +Name[km]=ទិដ្ឋភាពរូបតំណាង +Name[lt]=Rodyti piktogramas +Name[lv]=Ikonu Skatījums +Name[mk]=Преглед со икони +Name[ms]=Pelihat Ikon +Name[mt]=Ikoni +Name[nb]=Ikonvisning +Name[nds]=Lüttbildansicht +Name[ne]=प्रतिमा दृश्य +Name[nl]=Pictogramweergave +Name[nn]=Ikonvising +Name[pa]=ਆਈਕਾਨ ਦਰਿਸ਼ +Name[pl]=Widok ikon +Name[pt]=Vista por Ícones +Name[pt_BR]=Visualização de Ícone +Name[ro]=Vizualizare iconică +Name[ru]=Значки +Name[rw]=Igaragaza ry'Agashushondanga +Name[se]=Govaščájeheapmi +Name[sk]=Prehliadanie ikon +Name[sl]=Ikoniziran prikaz +Name[sr]=Приказ са иконама +Name[sr@Latn]=Prikaz sa ikonama +Name[sv]=Ikonvy +Name[ta]=சின்னத்தின் காட்சி +Name[tg]=Ишоротҳо +Name[th]=มุมมองแบบไอคอน +Name[tr]=Simge Görünümü +Name[uk]=Вигляд піктограмами +Name[uz]=Nishoncha koʻrinishida +Name[uz@cyrillic]=Нишонча кўринишида +Name[ven]=Mbonalelo ya aikhono +Name[vi]=Xem icon +Name[xh]=Imboniselo ye Icon +Name[zh_CN]=图标视图 +Name[zh_TW]=圖示檢視 +Name[zu]=Umboniso we Icon +Type=Service +ServiceTypes=KAddressBook/View +X-KDE-KAddressBook-ViewPluginVersion=1 diff --git a/kaddressbook/views/kaddressbookcardview.cpp b/kaddressbook/views/kaddressbookcardview.cpp new file mode 100644 index 000000000..d65c4d71f --- /dev/null +++ b/kaddressbook/views/kaddressbookcardview.cpp @@ -0,0 +1,370 @@ +/* + This file is part of KAddressBook. + Copyright (c) 2002 Mike Pilone <mpilone@slac.com> + + 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 <qapplication.h> +#include <qdragobject.h> +#include <qevent.h> +#include <qiconview.h> +#include <qlayout.h> +#include <qstringlist.h> + +#include <kabc/addressbook.h> +#include <kabc/addressee.h> +#include <kconfig.h> +#include <kdebug.h> +#include <klocale.h> + +#include "core.h" +#include "configurecardviewdialog.h" +#include "kabprefs.h" + +#include "kaddressbookcardview.h" + +class CardViewFactory : public ViewFactory +{ + public: + KAddressBookView *view( KAB::Core *core, QWidget *parent, const char *name ) + { + return new KAddressBookCardView( core, parent, name ); + } + + QString type() const { return I18N_NOOP("Card"); } + + QString description() const { return i18n( "Rolodex style cards represent contacts." ); } + + ViewConfigureWidget *configureWidget( KABC::AddressBook *ab, QWidget *parent, + const char *name = 0 ) + { + return new ConfigureCardViewWidget( ab, parent, name ); + } +}; + +extern "C" { + void *init_libkaddrbk_cardview() + { + return ( new CardViewFactory ); + } +} + +class AddresseeCardViewItem : public CardViewItem +{ + public: + AddresseeCardViewItem( const KABC::Field::List &fields, + bool showEmptyFields, + KABC::AddressBook *doc, const KABC::Addressee &addr, + CardView *parent ) + : CardViewItem( parent, addr.realName() ), + mFields( fields ), mShowEmptyFields( showEmptyFields ), + mDocument( doc ), mAddressee( addr ) + { + if ( mFields.isEmpty() ) + mFields = KABC::Field::defaultFields(); + + refresh(); + } + + const KABC::Addressee &addressee() const { return mAddressee; } + + void refresh() + { + mAddressee = mDocument->findByUid( mAddressee.uid() ); + + if ( !mAddressee.isEmpty() ) { + clearFields(); + + KABC::Field::List::ConstIterator it( mFields.begin() ); + const KABC::Field::List::ConstIterator endIt( mFields.end() ); + for ( ; it != endIt; ++it ) { + // insert empty fields or not? not doing so saves a bit of memory and CPU + // (during geometry calculations), but prevents having equally + // wide label columns in all cards, unless CardViewItem/CardView search + // globally for the widest label. (anders) + + // if ( mShowEmptyFields || !(*it)->value( mAddressee ).isEmpty() ) + insertField( (*it)->label(), (*it)->value( mAddressee ) ); + } + + setCaption( mAddressee.realName() ); + } + } + + private: + KABC::Field::List mFields; + bool mShowEmptyFields; + KABC::AddressBook *mDocument; + KABC::Addressee mAddressee; +}; + + +AddresseeCardView::AddresseeCardView( QWidget *parent, const char *name ) + : CardView( parent, name ) +{ + setAcceptDrops( true ); +} + +AddresseeCardView::~AddresseeCardView() +{ +} + +void AddresseeCardView::dragEnterEvent( QDragEnterEvent *event ) +{ + if ( QTextDrag::canDecode( event ) ) + event->accept(); +} + +void AddresseeCardView::dropEvent( QDropEvent *event ) +{ + emit addresseeDropped( event ); +} + +void AddresseeCardView::startDrag() +{ + emit startAddresseeDrag(); +} + + +KAddressBookCardView::KAddressBookCardView( KAB::Core *core, + QWidget *parent, const char *name ) + : KAddressBookView( core, parent, name ) +{ + mShowEmptyFields = false; + + QVBoxLayout *layout = new QVBoxLayout( viewWidget() ); + + mCardView = new AddresseeCardView( viewWidget(), "mCardView" ); + mCardView->setSelectionMode( CardView::Extended ); + layout->addWidget( mCardView ); + + // Connect up the signals + connect( mCardView, SIGNAL( executed( CardViewItem* ) ), + this, SLOT( addresseeExecuted( CardViewItem* ) ) ); + connect( mCardView, SIGNAL( selectionChanged() ), + this, SLOT( addresseeSelected() ) ); + connect( mCardView, SIGNAL( addresseeDropped( QDropEvent* ) ), + this, SIGNAL( dropped( QDropEvent* ) ) ); + connect( mCardView, SIGNAL( startAddresseeDrag() ), + this, SIGNAL( startDrag() ) ); + connect( mCardView, SIGNAL( contextMenuRequested( CardViewItem*, const QPoint& ) ), + this, SLOT( rmbClicked( CardViewItem*, const QPoint& ) ) ); +} + +KAddressBookCardView::~KAddressBookCardView() +{ +} + +KABC::Field *KAddressBookCardView::sortField() const +{ + // we have hardcoded sorting, so we have to return a hardcoded field :( + return KABC::Field::allFields()[ 0 ]; +} + +void KAddressBookCardView::readConfig( KConfig *config ) +{ + KAddressBookView::readConfig( config ); + + // costum colors? + if ( config->readBoolEntry( "EnableCustomColors", false ) ) { + QPalette p( mCardView->palette() ); + QColor c = p.color( QPalette::Normal, QColorGroup::Base ); + p.setColor( QPalette::Normal, QColorGroup::Base, config->readColorEntry( "BackgroundColor", &c ) ); + c = p.color( QPalette::Normal, QColorGroup::Text ); + p.setColor( QPalette::Normal, QColorGroup::Text, config->readColorEntry( "TextColor", &c ) ); + c = p.color( QPalette::Normal, QColorGroup::Button ); + p.setColor( QPalette::Normal, QColorGroup::Button, config->readColorEntry( "HeaderColor", &c ) ); + c = p.color( QPalette::Normal, QColorGroup::ButtonText ); + p.setColor( QPalette::Normal, QColorGroup::ButtonText, config->readColorEntry( "HeaderTextColor", &c ) ); + c = p.color( QPalette::Normal, QColorGroup::Highlight ); + p.setColor( QPalette::Normal, QColorGroup::Highlight, config->readColorEntry( "HighlightColor", &c ) ); + c = p.color( QPalette::Normal, QColorGroup::HighlightedText ); + p.setColor( QPalette::Normal, QColorGroup::HighlightedText, config->readColorEntry( "HighlightedTextColor", &c ) ); + mCardView->viewport()->setPalette( p ); + } else { + // needed if turned off during a session. + mCardView->viewport()->setPalette( mCardView->palette() ); + } + + //custom fonts? + QFont f( font() ); + if ( config->readBoolEntry( "EnableCustomFonts", false ) ) { + mCardView->setFont( config->readFontEntry( "TextFont", &f ) ); + f.setBold( true ); + mCardView->setHeaderFont( config->readFontEntry( "HeaderFont", &f ) ); + } else { + mCardView->setFont( f ); + f.setBold( true ); + mCardView->setHeaderFont( f ); + } + + mCardView->setDrawCardBorder( config->readBoolEntry( "DrawBorder", true ) ); + mCardView->setDrawColSeparators( config->readBoolEntry( "DrawSeparators", true ) ); + mCardView->setDrawFieldLabels( config->readBoolEntry( "DrawFieldLabels", false ) ); + mShowEmptyFields = config->readBoolEntry( "ShowEmptyFields", false ); + + mCardView->setShowEmptyFields( mShowEmptyFields ); + + mCardView->setItemWidth( config->readNumEntry( "ItemWidth", 200 ) ); + mCardView->setItemMargin( config->readNumEntry( "ItemMargin", 0 ) ); + mCardView->setItemSpacing( config->readNumEntry( "ItemSpacing", 10 ) ); + mCardView->setSeparatorWidth( config->readNumEntry( "SeparatorWidth", 2 ) ); + + disconnect( mCardView, SIGNAL( executed( CardViewItem* ) ), + this, SLOT( addresseeExecuted( CardViewItem* ) ) ); + + if ( KABPrefs::instance()->honorSingleClick() ) + connect( mCardView, SIGNAL( executed( CardViewItem* ) ), + this, SLOT( addresseeExecuted( CardViewItem* ) ) ); + else + connect( mCardView, SIGNAL( doubleClicked( CardViewItem* ) ), + this, SLOT( addresseeExecuted( CardViewItem* ) ) ); +} + +void KAddressBookCardView::writeConfig( KConfig *config ) +{ + config->writeEntry( "ItemWidth", mCardView->itemWidth() ); + KAddressBookView::writeConfig( config ); +} + +QStringList KAddressBookCardView::selectedUids() +{ + QStringList uidList; + CardViewItem *item; + AddresseeCardViewItem *aItem; + + for ( item = mCardView->firstItem(); item; item = item->nextItem() ) { + if ( item->isSelected() ) { + aItem = dynamic_cast<AddresseeCardViewItem*>( item ); + if ( aItem ) + uidList << aItem->addressee().uid(); + } + } + + return uidList; +} + +void KAddressBookCardView::refresh( const QString &uid ) +{ + CardViewItem *item; + AddresseeCardViewItem *aItem; + + if ( uid.isEmpty() ) { + // Rebuild the view + mCardView->viewport()->setUpdatesEnabled( false ); + mCardView->clear(); + + const KABC::Addressee::List addresseeList( addressees() ); + KABC::Addressee::List::ConstIterator it( addresseeList.begin() ); + const KABC::Addressee::List::ConstIterator endIt( addresseeList.end() ); + for ( ; it != endIt; ++it ) { + aItem = new AddresseeCardViewItem( fields(), mShowEmptyFields, + core()->addressBook(), *it, mCardView ); + } + mCardView->viewport()->setUpdatesEnabled( true ); + mCardView->viewport()->update(); + + // by default nothing is selected + emit selected( QString::null ); + } else { + // Try to find the one to refresh + bool found = false; + for ( item = mCardView->firstItem(); item && !found; item = item->nextItem() ) { + aItem = dynamic_cast<AddresseeCardViewItem*>( item ); + if ( aItem && (aItem->addressee().uid() == uid) ) { + aItem->refresh(); + found = true; + } + } + } +} + +void KAddressBookCardView::setSelected( const QString &uid, bool selected ) +{ + CardViewItem *item; + AddresseeCardViewItem *aItem; + + if ( uid.isEmpty() ) { + mCardView->selectAll( selected ); + } else { + bool found = false; + for ( item = mCardView->firstItem(); item && !found; item = item->nextItem() ) { + aItem = dynamic_cast<AddresseeCardViewItem*>( item ); + + if ( aItem && (aItem->addressee().uid() == uid) ) { + mCardView->setSelected( aItem, selected ); + mCardView->ensureItemVisible( item ); + found = true; + } + } + } +} + +void KAddressBookCardView::setFirstSelected( bool selected ) +{ + if ( mCardView->firstItem() ) { + mCardView->setSelected( mCardView->firstItem(), selected ); + mCardView->ensureItemVisible( mCardView->firstItem() ); + } +} + +void KAddressBookCardView::addresseeExecuted( CardViewItem *item ) +{ + AddresseeCardViewItem *aItem = dynamic_cast<AddresseeCardViewItem*>( item ); + if ( aItem ) + emit executed( aItem->addressee().uid() ); +} + +void KAddressBookCardView::addresseeSelected() +{ + CardViewItem *item; + AddresseeCardViewItem *aItem; + + bool found = false; + for ( item = mCardView->firstItem(); item && !found; item = item->nextItem() ) { + if ( item->isSelected() ) { + aItem = dynamic_cast<AddresseeCardViewItem*>( item ); + if ( aItem ) { + emit selected( aItem->addressee().uid() ); + found = true; + } + } + } + + if ( !found ) + emit selected( QString::null ); +} + +void KAddressBookCardView::rmbClicked( CardViewItem*, const QPoint &point ) +{ + popup( point ); +} + +void KAddressBookCardView::scrollUp() +{ + QApplication::postEvent( mCardView, new QKeyEvent( QEvent::KeyPress, Qt::Key_Up, 0, 0 ) ); +} + +void KAddressBookCardView::scrollDown() +{ + QApplication::postEvent( mCardView, new QKeyEvent( QEvent::KeyPress, Qt::Key_Down, 0, 0 ) ); +} + +#include "kaddressbookcardview.moc" diff --git a/kaddressbook/views/kaddressbookcardview.h b/kaddressbook/views/kaddressbookcardview.h new file mode 100644 index 000000000..68e2a13f3 --- /dev/null +++ b/kaddressbook/views/kaddressbookcardview.h @@ -0,0 +1,94 @@ +#ifndef KADDRESSBOOKCARDVIEW_H +#define KADDRESSBOOKCARDVIEW_H + +/* + This file is part of KAddressBook. + Copyright (c) 2002 Mike Pilone <mpilone@slac.com> + + 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 <qstring.h> +#include <kiconview.h> + +#include "cardview.h" +#include "kaddressbookview.h" + +class QDragEntryEvent; +class QDropEvent; +class KConfig; +class AddresseeCardView; + +/** + This view uses the CardView class to create a card view. At some + point in the future I think this will be the default view of + KAddressBook. + */ +class KAddressBookCardView : public KAddressBookView +{ + Q_OBJECT + + public: + KAddressBookCardView( KAB::Core *core, QWidget *parent, + const char *name = 0 ); + virtual ~KAddressBookCardView(); + + virtual QStringList selectedUids(); + virtual QString type() const { return "Card"; } + virtual KABC::Field *sortField() const; + + virtual void readConfig( KConfig *config ); + virtual void writeConfig( KConfig *config ); + + void scrollUp(); + void scrollDown(); + + public slots: + void refresh( const QString &uid = QString() ); + void setSelected( const QString &uid = QString(), bool selected = true ); + virtual void setFirstSelected( bool selected = true ); + + protected slots: + void addresseeExecuted( CardViewItem* ); + void addresseeSelected(); + void rmbClicked( CardViewItem*, const QPoint& ); + + private: + AddresseeCardView *mCardView; + bool mShowEmptyFields; +}; + +class AddresseeCardView : public CardView +{ + Q_OBJECT + public: + AddresseeCardView( QWidget *parent, const char *name = 0 ); + ~AddresseeCardView(); + + signals: + void startAddresseeDrag(); + void addresseeDropped( QDropEvent* ); + + protected: + virtual void dragEnterEvent( QDragEnterEvent* ); + virtual void dropEvent( QDropEvent* ); + virtual void startDrag(); +}; + +#endif diff --git a/kaddressbook/views/kaddressbookiconview.cpp b/kaddressbook/views/kaddressbookiconview.cpp new file mode 100644 index 000000000..b5d706cad --- /dev/null +++ b/kaddressbook/views/kaddressbookiconview.cpp @@ -0,0 +1,312 @@ +/* + This file is part of KAddressBook. + Copyright (c) 2002 Mike Pilone <mpilone@slac.com> + + 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 <qapplication.h> +#include <qiconview.h> +#include <qlayout.h> +#include <qstringlist.h> + +#include <kabc/addressbook.h> +#include <kabc/addressee.h> +#include <kconfig.h> +#include <kdebug.h> +#include <kglobal.h> +#include <kiconloader.h> +#include <klocale.h> + +#include "core.h" +#include "kabprefs.h" + +#include "kaddressbookiconview.h" + +class IconViewFactory : public ViewFactory +{ + public: + KAddressBookView *view( KAB::Core *core, QWidget *parent, const char *name ) + { + return new KAddressBookIconView( core, parent, name ); + } + + QString type() const { return I18N_NOOP( "Icon" ); } + + QString description() const { return i18n( "Icons represent contacts. Very simple view." ); } +}; + +extern "C" { + void *init_libkaddrbk_iconview() + { + return ( new IconViewFactory ); + } +} + +AddresseeIconView::AddresseeIconView( QWidget *parent, const char *name ) + : KIconView( parent, name ) +{ + setSelectionMode( QIconView::Extended ); + setResizeMode( QIconView::Adjust ); + setWordWrapIconText( true ); + setGridX( 100 ); + setItemsMovable( false ); + setSorting( true, true ); + setMode( KIconView::Select ); + + connect( this, SIGNAL( dropped( QDropEvent*, const QValueList<QIconDragItem>& ) ), + this, SLOT( itemDropped( QDropEvent*, const QValueList<QIconDragItem>& ) ) ); +} + +AddresseeIconView::~AddresseeIconView() +{ +} + +void AddresseeIconView::itemDropped( QDropEvent *event, const QValueList<QIconDragItem>& ) +{ + emit addresseeDropped( event ); +} + +QDragObject *AddresseeIconView::dragObject() +{ + emit startAddresseeDrag(); + + // We never want IconView to start the drag + return 0; +} + + +class AddresseeIconViewItem : public KIconViewItem +{ + public: + AddresseeIconViewItem( const KABC::Field::List&, KABC::AddressBook *doc, + const KABC::Addressee &addr, QIconView *parent ) + : KIconViewItem( parent ), mDocument( doc ), mAddressee( addr ) + { + refresh(); + } + + const KABC::Addressee &addressee() const { return mAddressee; } + + void refresh() + { + mAddressee = mDocument->findByUid( mAddressee.uid() ); + + if ( !mAddressee.isEmpty() ) + setText( mAddressee.givenName() + " " + mAddressee.familyName() ); + + QPixmap icon; + QPixmap defaultIcon( KGlobal::iconLoader()->loadIcon( "vcard", KIcon::Desktop ) ); + KABC::Picture pic = mAddressee.photo(); + if ( pic.data().isNull() ) + pic = mAddressee.logo(); + + if ( pic.isIntern() && !pic.data().isNull() ) { + QImage img = pic.data(); + if ( img.width() > img.height() ) + icon = img.scaleWidth( 32 ); + else + icon = img.scaleHeight( 32 ); + } else + icon = defaultIcon; + + setPixmap( icon ); + } + + private: + KABC::AddressBook *mDocument; + KABC::Addressee mAddressee; +}; + + +KAddressBookIconView::KAddressBookIconView( KAB::Core *core, + QWidget *parent, const char *name) + : KAddressBookView( core, parent, name ) +{ + QVBoxLayout *layout = new QVBoxLayout( viewWidget() ); + + mIconView = new AddresseeIconView( viewWidget(), "mIconView" ); + layout->addWidget( mIconView ); + + // Connect up the signals + connect( mIconView, SIGNAL( executed( QIconViewItem* ) ), + this, SLOT( addresseeExecuted( QIconViewItem* ) ) ); + connect( mIconView, SIGNAL( selectionChanged() ), + this, SLOT( addresseeSelected() ) ); + connect( mIconView, SIGNAL( addresseeDropped( QDropEvent* ) ), + this, SIGNAL( dropped( QDropEvent* ) ) ); + connect( mIconView, SIGNAL( startAddresseeDrag() ), + this, SIGNAL( startDrag() ) ); + connect( mIconView, SIGNAL( contextMenuRequested( QIconViewItem*, const QPoint& ) ), + this, SLOT( rmbClicked( QIconViewItem*, const QPoint& ) ) ); +} + +KAddressBookIconView::~KAddressBookIconView() +{ +} + +KABC::Field *KAddressBookIconView::sortField() const +{ + // we have hardcoded sorting, so we have to return a hardcoded field :( + return KABC::Field::allFields()[ 2 ]; +} + +void KAddressBookIconView::readConfig( KConfig *config ) +{ + KAddressBookView::readConfig( config ); + + disconnect( mIconView, SIGNAL( executed( QIconViewItem* ) ), + this, SLOT( addresseeExecuted( QIconViewItem* ) ) ); + + if ( KABPrefs::instance()->honorSingleClick() ) + connect( mIconView, SIGNAL( executed( QIconViewItem* ) ), + this, SLOT( addresseeExecuted( QIconViewItem* ) ) ); + else + connect( mIconView, SIGNAL( doubleClicked( QIconViewItem* ) ), + this, SLOT( addresseeExecuted( QIconViewItem* ) ) ); +} + +QStringList KAddressBookIconView::selectedUids() +{ + QStringList uidList; + QIconViewItem *item; + AddresseeIconViewItem *aItem; + + for ( item = mIconView->firstItem(); item; item = item->nextItem() ) { + if ( item->isSelected() ) { + aItem = dynamic_cast<AddresseeIconViewItem*>( item ); + if ( aItem ) + uidList << aItem->addressee().uid(); + } + } + + return uidList; +} + +void KAddressBookIconView::refresh( const QString &uid ) +{ + QIconViewItem *item; + AddresseeIconViewItem *aItem; + + if ( uid.isEmpty() ) { + // Rebuild the view + mIconView->clear(); + mIconList.clear(); + + const KABC::Addressee::List addresseeList( addressees() ); + KABC::Addressee::List::ConstIterator it( addresseeList.begin() ); + const KABC::Addressee::List::ConstIterator endIt( addresseeList.end() ); + for ( ; it != endIt; ++it ) + aItem = new AddresseeIconViewItem( fields(), core()->addressBook(), *it, mIconView ); + + mIconView->arrangeItemsInGrid( true ); + + for ( item = mIconView->firstItem(); item; item = item->nextItem() ) { + AddresseeIconViewItem* aivi = dynamic_cast<AddresseeIconViewItem*>( item ); + mIconList.append( aivi ); + } + + } else { + // Try to find the one to refresh + for ( item = mIconView->firstItem(); item; item = item->nextItem() ) { + aItem = dynamic_cast<AddresseeIconViewItem*>( item ); + if ( aItem && (aItem->addressee().uid() == uid) ) { + aItem->refresh(); + mIconView->arrangeItemsInGrid( true ); + return; + } + } + + refresh( QString::null ); + } +} + +void KAddressBookIconView::setSelected( const QString &uid, bool selected ) +{ + QIconViewItem *item; + AddresseeIconViewItem *aItem; + + if ( uid.isEmpty() ) { + mIconView->selectAll( selected ); + } else { + bool found = false; + for ( item = mIconView->firstItem(); item && !found; item = item->nextItem() ) { + + aItem = dynamic_cast<AddresseeIconViewItem*>( item ); + if ( aItem && (aItem->addressee().uid() == uid) ) { + mIconView->setSelected( aItem, selected ); + mIconView->ensureItemVisible( aItem ); + found = true; + } + } + } +} + +void KAddressBookIconView::setFirstSelected( bool selected ) +{ + if ( mIconView->firstItem() ) { + mIconView->setSelected( mIconView->firstItem(), selected ); + mIconView->ensureItemVisible( mIconView->firstItem() ); + } +} + +void KAddressBookIconView::addresseeExecuted( QIconViewItem *item ) +{ + AddresseeIconViewItem *aItem = dynamic_cast<AddresseeIconViewItem*>( item ); + + if ( aItem ) + emit executed( aItem->addressee().uid() ); +} + +void KAddressBookIconView::addresseeSelected() +{ + QIconViewItem *item; + AddresseeIconViewItem *aItem; + + bool found = false; + for ( item = mIconView->firstItem(); item && !found; item = item->nextItem() ) { + if ( item->isSelected() ) { + aItem = dynamic_cast<AddresseeIconViewItem*>( item ); + if ( aItem ) { + emit selected( aItem->addressee().uid() ); + found = true; + } + } + } + + if ( !found ) + emit selected( QString::null ); +} + +void KAddressBookIconView::rmbClicked( QIconViewItem*, const QPoint &point ) +{ + popup( point ); +} + +void KAddressBookIconView::scrollUp() +{ + QApplication::postEvent( mIconView, new QKeyEvent( QEvent::KeyPress, Qt::Key_Up, 0, 0 ) ); +} + +void KAddressBookIconView::scrollDown() +{ + QApplication::postEvent( mIconView, new QKeyEvent( QEvent::KeyPress, Qt::Key_Down, 0, 0 ) ); +} + +#include "kaddressbookiconview.moc" diff --git a/kaddressbook/views/kaddressbookiconview.h b/kaddressbook/views/kaddressbookiconview.h new file mode 100644 index 000000000..f11e7b8a1 --- /dev/null +++ b/kaddressbook/views/kaddressbookiconview.h @@ -0,0 +1,93 @@ +/* + This file is part of KAddressBook. + Copyright (c) 2002 Mike Pilone <mpilone@slac.com> + + 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 KADDRESSBOOKICONVIEW_H +#define KADDRESSBOOKICONVIEW_H + +#include <qstring.h> +#include <kiconview.h> +#include "kaddressbookview.h" + +class QIconViewItem; +class KConfig; +class AddresseeIconView; +class AddresseeIconViewItem; + +namespace KABC { class AddressBook; } + +/** This is an example kaddressbook view that is implemented using +* KIconView. This view is not the most useful view, but it displays +* how simple implementing a new view can be. +*/ +class KAddressBookIconView : public KAddressBookView +{ + Q_OBJECT + + public: + KAddressBookIconView( KAB::Core *core, QWidget *parent, + const char *name = 0 ); + virtual ~KAddressBookIconView(); + + virtual QStringList selectedUids(); + virtual QString type() const { return "Icon"; } + virtual KABC::Field *sortField() const; + virtual void readConfig( KConfig *config ); + + void scrollUp(); + void scrollDown(); + + public slots: + void refresh( const QString &uid = QString() ); + void setSelected( const QString &uid = QString(), bool selected = true ); + virtual void setFirstSelected( bool selected = true ); + + protected slots: + void addresseeExecuted( QIconViewItem *item ); + void addresseeSelected(); + void rmbClicked( QIconViewItem*, const QPoint& ); + + private: + AddresseeIconView *mIconView; + QPtrList<AddresseeIconViewItem> mIconList; +}; + + +class AddresseeIconView : public KIconView +{ + Q_OBJECT + + public: + AddresseeIconView( QWidget *parent, const char *name = 0 ); + ~AddresseeIconView(); + + signals: + void addresseeDropped( QDropEvent* ); + void startAddresseeDrag(); + + protected: + virtual QDragObject *dragObject(); + + protected slots: + void itemDropped( QDropEvent*, const QValueList<QIconDragItem>& ); +}; +#endif diff --git a/kaddressbook/views/kaddressbooktableview.cpp b/kaddressbook/views/kaddressbooktableview.cpp new file mode 100644 index 000000000..e0ac61093 --- /dev/null +++ b/kaddressbook/views/kaddressbooktableview.cpp @@ -0,0 +1,384 @@ +/* + This file is part of KAddressBook. + Copyright (c) 2002 Mike Pilone <mpilone@slac.com> + + 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 <qapplication.h> +#include <qlayout.h> +#include <qheader.h> +#include <qvbox.h> +#include <qlistbox.h> +#include <qwidget.h> +#include <qfile.h> +#include <qimage.h> +#include <qcombobox.h> +#include <qapplication.h> +#include <qdragobject.h> +#include <qevent.h> +#include <qurl.h> +#include <qpixmap.h> + +#include <kabc/addressbook.h> +#include <kapplication.h> +#include <kconfig.h> +#include <kcolorbutton.h> +#include <kdebug.h> +#include <kglobal.h> +#include <kiconloader.h> +#include <klineedit.h> +#include <klocale.h> +#include <kmessagebox.h> +#include <kurl.h> +#include <kurlrequester.h> +#include <kimproxy.h> + +#include "configuretableviewdialog.h" +#include "contactlistview.h" +#include "core.h" +#include "kabprefs.h" +#include "undocmds.h" + +#include "kaddressbooktableview.h" + +class TableViewFactory : public ViewFactory +{ + public: + KAddressBookView *view( KAB::Core *core, QWidget *parent, const char *name ) + { + return new KAddressBookTableView( core, parent, name ); + } + + QString type() const { return I18N_NOOP( "Table" ); } + + QString description() const { return i18n( "A listing of contacts in a table. Each cell of " + "the table holds a field of the contact." ); } + + ViewConfigureWidget *configureWidget( KABC::AddressBook *ab, QWidget *parent, + const char *name = 0 ) + { + return new ConfigureTableViewWidget( ab, parent, name ); + } +}; + +extern "C" { + void *init_libkaddrbk_tableview() + { + return ( new TableViewFactory ); + } +} + +KAddressBookTableView::KAddressBookTableView( KAB::Core *core, + QWidget *parent, const char *name ) + : KAddressBookView( core, parent, name ) +{ + mMainLayout = new QVBoxLayout( viewWidget(), 2 ); + + // The list view will be created when the config is read. + mListView = 0; + mIMProxy = 0; +} + +KAddressBookTableView::~KAddressBookTableView() +{ +} + +void KAddressBookTableView::reconstructListView() +{ + if ( mListView ) { + disconnect( mListView, SIGNAL( selectionChanged() ), + this, SLOT( addresseeSelected() ) ); + disconnect( mListView, SIGNAL( executed( QListViewItem* ) ), + this, SLOT( addresseeExecuted( QListViewItem* ) ) ); + disconnect( mListView, SIGNAL( doubleClicked( QListViewItem* ) ), + this, SLOT( addresseeExecuted( QListViewItem* ) ) ); + disconnect( mListView, SIGNAL( startAddresseeDrag() ), + this, SIGNAL( startDrag() ) ); + disconnect( mListView, SIGNAL( addresseeDropped( QDropEvent* ) ), + this, SIGNAL( dropped( QDropEvent* ) ) ); + delete mListView; + } + + mListView = new ContactListView( this, core()->addressBook(), viewWidget() ); + + mListView->setShowIM( mIMProxy != 0 ); + + // Add the columns + const KABC::Field::List fieldList( fields() ); + KABC::Field::List::ConstIterator it; + + int c = 0; + for ( it = fieldList.begin(); it != fieldList.end(); ++it ) { + mListView->addColumn( (*it)->label() ); + mListView->setColumnWidthMode( c++, QListView::Manual ); + } + + if ( mListView->showIM() ) { + // IM presence is added separately, because it's not a KABC field. + // If you want to make this appear as the leftmost column by default, move + // this block immediately before the preceding for loop + // after the declaration of c. + mListView->addColumn( i18n( "Presence" ) ); + mListView->setIMColumn( c++ ); + } + + mListView->setFullWidth( true ); + + connect( mListView, SIGNAL( selectionChanged() ), + this, SLOT( addresseeSelected() ) ); + connect( mListView, SIGNAL( startAddresseeDrag() ), + this, SIGNAL( startDrag() ) ); + connect( mListView, SIGNAL( addresseeDropped( QDropEvent* ) ), + this, SIGNAL( dropped( QDropEvent* ) ) ); + connect( mListView, SIGNAL( contextMenu( KListView*, QListViewItem*, const QPoint& ) ), + this, SLOT( rmbClicked( KListView*, QListViewItem*, const QPoint& ) ) ); + connect( mListView->header(), SIGNAL( clicked( int ) ), + this, SIGNAL( sortFieldChanged() ) ); + + if ( KABPrefs::instance()->honorSingleClick() ) + connect( mListView, SIGNAL( executed( QListViewItem* ) ), + this, SLOT( addresseeExecuted( QListViewItem* ) ) ); + else + connect( mListView, SIGNAL( doubleClicked( QListViewItem* ) ), + this, SLOT( addresseeExecuted( QListViewItem* ) ) ); + + refresh(); + + mListView->setSorting( 0, true ); + mMainLayout->addWidget( mListView ); + mMainLayout->activate(); + mListView->show(); +} + +KABC::Field *KAddressBookTableView::sortField() const +{ + // we have hardcoded sorting, so we have to return a hardcoded field :( + return ( mListView->sortColumn() == -1 ? fields()[ 0 ] : fields()[ mListView->sortColumn() ] ); +} + +void KAddressBookTableView::writeConfig( KConfig *config ) +{ + KAddressBookView::writeConfig( config ); + + mListView->saveLayout( config, config->group() ); +} + +void KAddressBookTableView::readConfig( KConfig *config ) +{ + KAddressBookView::readConfig( config ); + + if ( config->readBoolEntry( "InstantMessagingPresence", false ) ) { + if ( !mIMProxy ) { + mIMProxy = KIMProxy::instance( kapp->dcopClient() ); + connect( mIMProxy, SIGNAL( sigContactPresenceChanged( const QString& ) ), + this, SLOT( updatePresence( const QString& ) ) ); + } + } else { + if ( mIMProxy ) { + disconnect( mIMProxy, SIGNAL( sigContactPresenceChanged( const QString& ) ), + this, SLOT( updatePresence( const QString& ) ) ); + mIMProxy = 0; + } + } + + // The config could have changed the fields, so we need to reconstruct + // the listview. + reconstructListView(); + + // Set the list view options + mListView->setAlternateBackgroundEnabled( config->readBoolEntry( "ABackground", true ) ); + mListView->setSingleLineEnabled( config->readBoolEntry( "SingleLine", false ) ); + mListView->setToolTipsEnabled( config->readBoolEntry( "ToolTips", true ) ); + + if ( config->readBoolEntry( "Background", false ) ) + mListView->setBackgroundPixmap( config->readPathEntry( "BackgroundName" ) ); + + // Restore the layout of the listview + mListView->restoreLayout( config, config->group() ); +} + +void KAddressBookTableView::refresh( const QString &uid ) +{ + if ( uid.isEmpty() ) { + // Clear the list view + QString currentUID, nextUID; + ContactListViewItem *currentItem = dynamic_cast<ContactListViewItem*>( mListView->currentItem() ); + if ( currentItem ) { + ContactListViewItem *nextItem = dynamic_cast<ContactListViewItem*>( currentItem->itemBelow() ); + if ( nextItem ) + nextUID = nextItem->addressee().uid(); + currentUID = currentItem->addressee().uid(); + } + + mListView->clear(); + + currentItem = 0; + const KABC::Addressee::List addresseeList( addressees() ); + KABC::Addressee::List::ConstIterator it( addresseeList.begin() ); + const KABC::Addressee::List::ConstIterator endIt( addresseeList.end() ); + for ( ; it != endIt; ++it ) { + ContactListViewItem *item = new ContactListViewItem( *it, mListView, + core()->addressBook(), fields(), mIMProxy ); + if ( (*it).uid() == currentUID ) + currentItem = item; + else if ( (*it).uid() == nextUID && !currentItem ) + currentItem = item; + } + + // Sometimes the background pixmap gets messed up when we add lots + // of items. + mListView->repaint(); + + if ( currentItem ) { + mListView->setCurrentItem( currentItem ); + mListView->ensureItemVisible( currentItem ); + } + } else { + // Only need to update on entry. Iterate through and try to find it + ContactListViewItem *ceItem; + QPtrList<QListViewItem> selectedItems( mListView->selectedItems() ); + QListViewItem *it; + for ( it = selectedItems.first(); it; it = selectedItems.next() ) { + ceItem = dynamic_cast<ContactListViewItem*>( it ); + if ( ceItem && ceItem->addressee().uid() == uid ) { + ceItem->refresh(); + return; + } + } + refresh( QString::null ); + } +} + +QStringList KAddressBookTableView::selectedUids() +{ + QStringList uidList; + ContactListViewItem *item; + + QListViewItemIterator it( mListView, QListViewItemIterator::Selected ); + while ( it.current() ) { + item = dynamic_cast<ContactListViewItem*>( it.current() ); + if ( item ) + uidList << item->addressee().uid(); + + ++it; + } + + return uidList; +} + +void KAddressBookTableView::setSelected( const QString &uid, bool selected ) +{ + if ( uid.isEmpty() ) + mListView->selectAll( selected ); + else { + QListViewItemIterator it( mListView ); + while ( it.current() ) { + ContactListViewItem *item = dynamic_cast<ContactListViewItem*>( it.current() ); + if ( item && (item->addressee().uid() == uid) ) { + mListView->setSelected( item, selected ); + + if ( selected ) + mListView->ensureItemVisible( item ); + } + + ++it; + } + } +} + +void KAddressBookTableView::setFirstSelected( bool selected ) +{ + if ( mListView->firstChild() ) { + mListView->setSelected( mListView->firstChild(), selected ); + mListView->ensureItemVisible( mListView->firstChild() ); + } +} + +void KAddressBookTableView::addresseeSelected() +{ + // We need to try to find the first selected item. This might not be the + // last selected item, but when QListView is in multiselection mode, + // there is no way to figure out which one was + // selected last. + bool found =false; + + QListViewItemIterator it( mListView, QListViewItemIterator::Selected ); + while ( it.current() && !found ) { + found = true; + ContactListViewItem *item = dynamic_cast<ContactListViewItem*>( it.current() ); + if ( item ) + emit selected( item->addressee().uid() ); + + ++it; + } + + if ( !found ) + emit selected( QString::null ); +} + +void KAddressBookTableView::addresseeExecuted( QListViewItem *item ) +{ + if ( item ) { + ContactListViewItem *ceItem = dynamic_cast<ContactListViewItem*>( item ); + + if ( ceItem ) + emit executed( ceItem->addressee().uid() ); + else + emit executed( QString::null ); + } else { + emit executed( QString::null ); + } +} + +void KAddressBookTableView::rmbClicked( KListView*, QListViewItem*, const QPoint &point ) +{ + popup( point ); +} + +void KAddressBookTableView::updatePresence( const QString &uid ) +{ + // find the LVI to update and refresh() it + QListViewItem *item; + ContactListViewItem *ceItem; + for ( item = mListView->firstChild(); item; item = item->itemBelow() ) { + ceItem = dynamic_cast<ContactListViewItem*>( item ); + if ( ( ceItem != 0L ) && ( ceItem->addressee().uid() == uid ) ) { + ceItem->setHasIM( true ); + ceItem->refresh(); + break; + } + } + + if ( mListView->sortColumn() == mListView->imColumn() ) + mListView->sort(); +} + +void KAddressBookTableView::scrollUp() +{ + QApplication::postEvent( mListView, new QKeyEvent( QEvent::KeyPress, Qt::Key_Up, 0, 0 ) ); +} + +void KAddressBookTableView::scrollDown() +{ + QApplication::postEvent( mListView, new QKeyEvent( QEvent::KeyPress, Qt::Key_Down, 0, 0 ) ); +} + + +#include "kaddressbooktableview.moc" diff --git a/kaddressbook/views/kaddressbooktableview.h b/kaddressbook/views/kaddressbooktableview.h new file mode 100644 index 000000000..0d328ce86 --- /dev/null +++ b/kaddressbook/views/kaddressbooktableview.h @@ -0,0 +1,115 @@ +/* + This file is part of KAddressBook. + Copyright (c) 2002 Mike Pilone <mpilone@slac.com> + + 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 KADDRESSBOOKTABLEVIEW_H +#define KADDRESSBOOKTABLEVIEW_H + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include <qwidget.h> +#include <qlistview.h> +#include <qstring.h> +#include <qdialog.h> +#include <qtabdialog.h> +#include <qstringlist.h> +#include <qvaluelist.h> + +#include "kaddressbookview.h" + +class QListViewItem; +class QListBox; +class QVBoxLayout; +class KConfig; +class KIMProxy; + +class ContactListViewItem; +class ContactListView; + +namespace KABC { class AddressBook; } + +/** + * This class is the table view for kaddressbook. This view is a KListView + * with multiple columns for the selected fields. + * + * @short Table View + * @author Don Sanders <dsanders@kde.org> + * @version 0.1 + */ +class KAddressBookTableView : public KAddressBookView +{ +friend class ContactListView; + + Q_OBJECT + + public: + KAddressBookTableView( KAB::Core *core, QWidget *parent, + const char *name = 0 ); + virtual ~KAddressBookTableView(); + + virtual void refresh( const QString &uid = QString() ); + virtual QStringList selectedUids(); + virtual void setSelected( const QString &uid = QString(), bool selected = false ); + virtual void setFirstSelected( bool selected = true ); + virtual KABC::Field *sortField() const; + + virtual void readConfig( KConfig *config ); + virtual void writeConfig( KConfig *config ); + virtual QString type() const { return "Table"; } + + void scrollUp(); + void scrollDown(); + + public slots: + virtual void reconstructListView(); + + protected slots: + /** + Called whenever the user selects an addressee in the list view. + */ + void addresseeSelected(); + + /** + Called whenever the user executes an addressee. In terms of the + list view, this is probably a double click + */ + void addresseeExecuted( QListViewItem* ); + + /** + RBM menu called. + */ + void rmbClicked( KListView*, QListViewItem*, const QPoint& ); + + /** + * Called to update the presence of a single item + */ + void updatePresence( const QString &uid ); + + private: + QVBoxLayout *mMainLayout; + ContactListView *mListView; + KIMProxy *mIMProxy; +}; + +#endif diff --git a/kaddressbook/views/tableview.desktop b/kaddressbook/views/tableview.desktop new file mode 100644 index 000000000..b07b2a19c --- /dev/null +++ b/kaddressbook/views/tableview.desktop @@ -0,0 +1,64 @@ +[Desktop Entry] +X-KDE-Library=libkaddrbk_tableview +Name=Table View +Name[af]=Tabel Aansig +Name[ar]=عرض الجدول +Name[be]=У выглядзе табліцы +Name[bg]=Преглед в таблица +Name[br]=Gwel taolenn +Name[bs]=Pogled tabele +Name[ca]=Vista de taula +Name[cs]=Tabulkový pohled +Name[cy]=Golwg Tabl +Name[da]=Tabel-visning +Name[de]=Tabellenansicht +Name[el]=Προβολή πίνακα +Name[eo]=Tabelrigardo +Name[es]=Vista de tabla +Name[et]=Tabelivaade +Name[eu]=Taula ikupegia +Name[fa]=نمای جدول +Name[fi]=Taulukkonäkymä +Name[fr]=Vue en tableaux +Name[fy]=Tabelwerjefte +Name[gl]=Vista de árbore +Name[he]=תצוגת טבלה +Name[hi]=टेबल दृश्य +Name[hu]=Táblázatos nézet +Name[is]=Töflusýn +Name[it]=Vista tabella +Name[ja]=テーブルビュー +Name[ka]=ცხრილი +Name[kk]=Кесте +Name[km]=ទិដ្ឋភាពតារាង +Name[lt]=Lentelės vaizdas +Name[mk]=Преглед со табела +Name[ms]=Pelihat Jadual +Name[nb]=Tabellvisning +Name[nds]=Tabellansicht +Name[ne]=तालिका दृश्य +Name[nl]=Tabelweergave +Name[nn]=Tabellvising +Name[pa]=ਸਾਰਣੀ ਦਰਿਸ਼ +Name[pl]=Widok tabeli +Name[pt]=Vista em Tabela +Name[pt_BR]=Visualização de Tabela +Name[ro]=Vizualizare tabel +Name[ru]=Таблица +Name[se]=Tabeallačájeheapmi +Name[sk]=Prezeranie tabuľky +Name[sl]=Tabelarični prikaz +Name[sr]=Табеларни приказ +Name[sr@Latn]=Tabelarni prikaz +Name[sv]=Tabellvy +Name[ta]=அட்டவணை காட்சி +Name[tg]=Ҷадвал +Name[tr]=Tablo Görünümü +Name[uk]=Вигляд таблицею +Name[uz]=Jadval koʻrinishida +Name[uz@cyrillic]=Жадвал кўринишида +Name[zh_CN]=表格视图 +Name[zh_TW]=表格檢視 +Type=Service +ServiceTypes=KAddressBook/View +X-KDE-KAddressBook-ViewPluginVersion=1 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>&File</text> + <Menu name="file_export"><text>&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>&File</text> + <Menu name="file_import"><text>&Import</text> + <Action name="file_import_csv"/> + </Menu> + <Menu name="file_export"><text>&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>&File</text> + <Menu name="file_import"><text>&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>&File</text> + <Menu name="file_import"><text>&Import</text> + <Action name="file_import_gnokii"/> + </Menu> + <Menu name="file_export"><text>&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>&File</text> + <Menu name="file_import"><text>&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>&File</text> + <Menu name="file_import"><text>&Import</text> + <Action name="file_import_ldif"/> + </Menu> + <Menu name="file_export"><text>&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>&File</text> + <Menu name="file_import"><text>&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>&File</text> + <Menu name="file_import"><text>&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 Binary files differnew file mode 100644 index 000000000..d94e1ac77 --- /dev/null +++ b/kaddressbook/xxport/samples/PAB_format.pdf 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>&File</text> + <Menu name="file_import"><text>&Import</text> + <Action name="file_import_vcard"/> + </Menu> + <Menu name="file_export"><text>&Export</text> + <Action name="file_export_vcard_v21"/> + <Action name="file_export_vcard_v30"/> + </Menu> + </Menu> +</MenuBar> +</gui> diff --git a/kaddressbook/xxportmanager.cpp b/kaddressbook/xxportmanager.cpp new file mode 100644 index 000000000..3382ac439 --- /dev/null +++ b/kaddressbook/xxportmanager.cpp @@ -0,0 +1,159 @@ +/* + 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 <qlayout.h> + +#include <kabc/addressbook.h> +#include <kabc/resource.h> +#include <kdebug.h> +#include <klocale.h> +#include <kmessagebox.h> +#include <ktrader.h> +#include <kapplication.h> + +#include "core.h" +#include "kablock.h" +#include "undocmds.h" +#include "xxportselectdialog.h" + +#include "xxportmanager.h" + +KURL XXPortManager::importURL = KURL(); +QString XXPortManager::importData = QString::null; + +XXPortManager::XXPortManager( KAB::Core *core, QObject *parent, const char *name ) + : QObject( parent, name ), mCore( core ) +{ + loadPlugins(); +} + +XXPortManager::~XXPortManager() +{ +} + +void XXPortManager::restoreSettings() +{ +} + +void XXPortManager::saveSettings() +{ +} + +void XXPortManager::importVCard( const KURL &url ) +{ + importURL = url; + slotImport( "vcard", "<empty>" ); + importURL = KURL(); +} + +void XXPortManager::importVCardFromData( const QString &vCard ) +{ + importData = vCard; + slotImport( "vcard", "<empty>" ); + importData = ""; +} + +void XXPortManager::slotImport( const QString &identifier, const QString &data ) +{ + KAB::XXPort *obj = mXXPortObjects[ identifier ]; + if ( !obj ) { + KMessageBox::error( mCore->widget(), i18n( "<qt>No import plugin available for <b>%1</b>.</qt>" ).arg( identifier ) ); + return; + } + + KABC::Resource *resource = mCore->requestResource( mCore->widget() ); + if ( !resource ) + return; + + KABC::AddresseeList list = obj->importContacts( data ); + KABC::AddresseeList::Iterator it; + for ( it = list.begin(); it != list.end(); ++it ) + (*it).setResource( resource ); + + if ( !list.isEmpty() ) { + NewCommand *command = new NewCommand( mCore->addressBook(), list ); + mCore->commandHistory()->addCommand( command ); + emit modified(); + } +} + +void XXPortManager::slotExport( const QString &identifier, const QString &data ) +{ + KAB::XXPort *obj = mXXPortObjects[ identifier ]; + if ( !obj ) { + KMessageBox::error( mCore->widget(), i18n( "<qt>No export plugin available for <b>%1</b>.</qt>" ).arg( identifier ) ); + return; + } + + KABC::AddresseeList addrList; + XXPortSelectDialog dlg( mCore, obj->requiresSorting(), mCore->widget() ); + if ( dlg.exec() ) + addrList = dlg.contacts(); + else + return; + + if ( !obj->exportContacts( addrList, data ) ) + KMessageBox::error( mCore->widget(), i18n( "Unable to export contacts." ) ); +} + +void XXPortManager::loadPlugins() +{ + mXXPortObjects.clear(); + + const KTrader::OfferList plugins = KTrader::self()->query( "KAddressBook/XXPort", + QString( "[X-KDE-KAddressBook-XXPortPluginVersion] == %1" ).arg( KAB_XXPORT_PLUGIN_VERSION ) ); + KTrader::OfferList::ConstIterator it; + for ( it = plugins.begin(); it != plugins.end(); ++it ) { + if ( !(*it)->hasServiceType( "KAddressBook/XXPort" ) ) + continue; + + KLibFactory *factory = KLibLoader::self()->factory( (*it)->library().latin1() ); + if ( !factory ) { + kdDebug(5720) << "XXPortManager::loadExtensions(): Factory creation failed" << endl; + continue; + } + + KAB::XXPortFactory *xxportFactory = static_cast<KAB::XXPortFactory*>( factory ); + + if ( !xxportFactory ) { + kdDebug(5720) << "XXPortManager::loadExtensions(): Cast failed" << endl; + continue; + } + + KAB::XXPort *obj = xxportFactory->xxportObject( mCore->addressBook(), mCore->widget() ); + if ( obj ) { + if ( mCore->guiClient() ) + mCore->guiClient()->insertChildClient( obj ); + + mXXPortObjects.insert( obj->identifier(), obj ); + connect( obj, SIGNAL( exportActivated( const QString&, const QString& ) ), + this, SLOT( slotExport( const QString&, const QString& ) ) ); + connect( obj, SIGNAL( importActivated( const QString&, const QString& ) ), + this, SLOT( slotImport( const QString&, const QString& ) ) ); + + obj->setKApplication( kapp ); + } + } +} + +#include "xxportmanager.moc" diff --git a/kaddressbook/xxportmanager.h b/kaddressbook/xxportmanager.h new file mode 100644 index 000000000..4b52c8b5e --- /dev/null +++ b/kaddressbook/xxportmanager.h @@ -0,0 +1,73 @@ +/* + 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 XXPORTMANAGER_H +#define XXPORTMANAGER_H + +#include <qdict.h> +#include <qobject.h> + +#include <kurl.h> + +#include <kdepimmacros.h> + +#include "xxport.h" + +namespace KAB { +class Core; +} + +class KDE_EXPORT XXPortManager : public QObject +{ + Q_OBJECT + + public: + XXPortManager( KAB::Core *core, QObject *parent, const char *name = 0 ); + ~XXPortManager(); + + void restoreSettings(); + void saveSettings(); + + static KURL importURL; + static QString importData; + + public slots: + void importVCard( const KURL &url ); + void importVCardFromData( const QString &vCard ); + + signals: + void modified(); + + protected slots: + void slotImport( const QString&, const QString& ); + void slotExport( const QString&, const QString& ); + + private: + void loadPlugins(); + + QDict<KAB::XXPort> mXXPortObjects; + + KAB::Core *mCore; +}; + +#endif diff --git a/kaddressbook/xxportselectdialog.cpp b/kaddressbook/xxportselectdialog.cpp new file mode 100644 index 000000000..a32c10807 --- /dev/null +++ b/kaddressbook/xxportselectdialog.cpp @@ -0,0 +1,251 @@ +/* + This file is part of KAddressBook. + Copyright (c) 2002 Anders Lund <anders.lund@lund.tdcadsl.dk> + 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 <kabc/addressbook.h> +#include <kapplication.h> +#include <kcombobox.h> +#include <klocale.h> + +#include <qbuttongroup.h> +#include <qcombobox.h> +#include <qheader.h> +#include <qlabel.h> +#include <qlayout.h> +#include <qlistview.h> +#include <qpushbutton.h> +#include <qradiobutton.h> +#include <qstringlist.h> +#include <qwhatsthis.h> + +#include "core.h" +#include "kabprefs.h" + +#include "xxportselectdialog.h" + +XXPortSelectDialog::XXPortSelectDialog( KAB::Core *core, bool sort, + QWidget* parent, const char* name ) + : KDialogBase( Plain, i18n( "Choose Which Contacts to Export" ), Help | Ok | Cancel, + Ok, parent, name, true, true ), mCore( core ), + mUseSorting( sort ) +{ + initGUI(); + + connect( mFiltersCombo, SIGNAL( activated( int ) ), + SLOT( filterChanged( int ) ) ); + connect( mCategoriesView, SIGNAL( clicked( QListViewItem* ) ), + SLOT( categoryClicked( QListViewItem* ) ) ); + + // setup filters + mFilters = Filter::restore( kapp->config(), "Filter" ); + Filter::List::ConstIterator filterIt; + QStringList filters; + for ( filterIt = mFilters.begin(); filterIt != mFilters.end(); ++filterIt ) + filters.append( (*filterIt).name() ); + + mFiltersCombo->insertStringList( filters ); + mUseFilters->setEnabled( filters.count() > 0 ); + + // setup categories + const QStringList categories = KABPrefs::instance()->customCategories(); + QStringList::ConstIterator it; + for ( it = categories.begin(); it != categories.end(); ++it ) + new QCheckListItem( mCategoriesView, *it, QCheckListItem::CheckBox ); + mUseCategories->setEnabled( categories.count() > 0 ); + + int count = mCore->selectedUIDs().count(); + mUseSelection->setEnabled( count != 0 ); + mUseSelection->setChecked( count > 0 ); + + mSortTypeCombo->insertItem( i18n( "Ascending" ) ); + mSortTypeCombo->insertItem( i18n( "Descending" ) ); + + mFields = mCore->addressBook()->fields( KABC::Field::All ); + KABC::Field::List::ConstIterator fieldIt; + for ( fieldIt = mFields.begin(); fieldIt != mFields.end(); ++fieldIt ) + mFieldCombo->insertItem( (*fieldIt)->label() ); +} + +KABC::AddresseeList XXPortSelectDialog::contacts() +{ + const QStringList selection = mCore->selectedUIDs(); + + KABC::AddresseeList list; + if ( mUseSelection->isChecked() ) { + QStringList::ConstIterator it; + for ( it = selection.begin(); it != selection.end(); ++it ) { + KABC::Addressee addr = mCore->addressBook()->findByUid( *it ); + if ( !addr.isEmpty() ) + list.append( addr ); + } + } else if ( mUseFilters->isChecked() ) { + // find contacts that can pass selected filter + Filter::List::ConstIterator filterIt; + for ( filterIt = mFilters.begin(); filterIt != mFilters.end(); ++filterIt ) + if ( (*filterIt).name() == mFiltersCombo->currentText() ) + break; + + KABC::AddressBook::Iterator it; + for ( it = mCore->addressBook()->begin(); it != mCore->addressBook()->end(); ++it ) { + if ( (*filterIt).filterAddressee( *it ) ) + list.append( *it ); + } + } else if ( mUseCategories->isChecked() ) { + const QStringList categorieList = categories(); + + KABC::AddressBook::ConstIterator it; + KABC::AddressBook::ConstIterator addressBookEnd( mCore->addressBook()->end() ); + for ( it = mCore->addressBook()->begin(); it != addressBookEnd; ++it ) { + const QStringList tmp( (*it).categories() ); + QStringList::ConstIterator tmpIt; + for ( tmpIt = tmp.begin(); tmpIt != tmp.end(); ++tmpIt ) + if ( categorieList.contains( *tmpIt ) ) { + list.append( *it ); + break; + } + } + } else { + // create a string list of all entries: + KABC::AddressBook::ConstIterator it; + for ( it = mCore->addressBook()->begin(); it != mCore->addressBook()->end(); ++it ) + list.append( *it ); + } + + if ( mUseSorting ) { + list.setReverseSorting( mSortTypeCombo->currentItem() == 1 ); + uint pos = mFieldCombo->currentItem(); + if ( pos < mFields.count() ) + list.sortByField( mFields[ pos ] ); + } + + return list; +} + +QStringList XXPortSelectDialog::categories() const +{ + QStringList list; + + QListViewItemIterator it( mCategoriesView ); + for ( ; it.current(); ++it ) { + QCheckListItem* qcli = static_cast<QCheckListItem*>(it.current()); + if ( qcli->isOn() ) + list.append( it.current()->text( 0 ) ); + } + + return list; +} + +void XXPortSelectDialog::filterChanged( int ) +{ + mUseFilters->setChecked( true ); +} + +void XXPortSelectDialog::categoryClicked( QListViewItem *i ) +{ + if ( !i ) + return; + + QCheckListItem *qcli = static_cast<QCheckListItem*>( i ); + if ( qcli->isOn() ) + mUseCategories->setChecked( true ); +} + +void XXPortSelectDialog::slotHelp() +{ + kapp->invokeHelp( "import-and-export" ); +} + +void XXPortSelectDialog::initGUI() +{ + QFrame *page = plainPage(); + + QVBoxLayout *topLayout = new QVBoxLayout( page, KDialog::marginHint(), + KDialog::spacingHint() ); + + QLabel *label = new QLabel( i18n( "Which contacts do you want to export?" ), page ); + topLayout->addWidget( label ); + + mButtonGroup = new QButtonGroup( i18n( "Selection" ), page ); + mButtonGroup->setColumnLayout( 0, Qt::Vertical ); + mButtonGroup->layout()->setSpacing( KDialog::spacingHint() ); + mButtonGroup->layout()->setMargin( KDialog::marginHint() ); + + QGridLayout *groupLayout = new QGridLayout( mButtonGroup->layout() ); + groupLayout->setAlignment( Qt::AlignTop ); + + mUseWholeBook = new QRadioButton( i18n( "&All contacts" ), mButtonGroup ); + mUseWholeBook->setChecked( true ); + QWhatsThis::add( mUseWholeBook, i18n( "Export the entire address book" ) ); + groupLayout->addWidget( mUseWholeBook, 0, 0 ); + mUseSelection = new QRadioButton( i18n("&Selected contact", "&Selected contacts (%n selected)", mCore->selectedUIDs().count() ), mButtonGroup ); + QWhatsThis::add( mUseSelection, i18n( "Only export contacts selected in KAddressBook.\n" + "This option is disabled if no contacts are selected." ) ); + groupLayout->addWidget( mUseSelection, 1, 0 ); + + mUseFilters = new QRadioButton( i18n( "Contacts matching &filter" ), mButtonGroup ); + QWhatsThis::add( mUseFilters, i18n( "Only export contacts matching the selected filter.\n" + "This option is disabled if you have not defined any filters" ) ); + groupLayout->addWidget( mUseFilters, 2, 0 ); + + mUseCategories = new QRadioButton( i18n( "Category &members" ), mButtonGroup ); + QWhatsThis::add( mUseCategories, i18n( "Only export contacts who are members of a category that is checked on the list to the left.\n" + "This option is disabled if you have no categories." ) ); + groupLayout->addWidget( mUseCategories, 3, 0, Qt::AlignTop ); + + mFiltersCombo = new QComboBox( false, mButtonGroup ); + QWhatsThis::add( mFiltersCombo, i18n( "Select a filter to decide which contacts to export." ) ); + groupLayout->addWidget( mFiltersCombo, 2, 1 ); + + mCategoriesView = new QListView( mButtonGroup ); + mCategoriesView->addColumn( "" ); + mCategoriesView->header()->hide(); + QWhatsThis::add( mCategoriesView, i18n( "Check the categories whose members you want to export." ) ); + groupLayout->addWidget( mCategoriesView, 3, 1 ); + + topLayout->addWidget( mButtonGroup ); + + QButtonGroup *sortingGroup = new QButtonGroup( i18n( "Sorting" ), page ); + sortingGroup->setColumnLayout( 0, Qt::Vertical ); + QGridLayout *sortLayout = new QGridLayout( sortingGroup->layout(), 2, 2, + KDialog::spacingHint() ); + sortLayout->setAlignment( Qt::AlignTop ); + + label = new QLabel( i18n( "Criterion:" ), sortingGroup ); + sortLayout->addWidget( label, 0, 0 ); + + mFieldCombo = new KComboBox( false, sortingGroup ); + sortLayout->addWidget( mFieldCombo, 0, 1 ); + + label = new QLabel( i18n( "Order:" ), sortingGroup ); + sortLayout->addWidget( label, 1, 0 ); + + mSortTypeCombo = new KComboBox( false, sortingGroup ); + sortLayout->addWidget( mSortTypeCombo, 1, 1 ); + + topLayout->addWidget( sortingGroup ); + + if ( !mUseSorting ) + sortingGroup->hide(); +} + +#include "xxportselectdialog.moc" diff --git a/kaddressbook/xxportselectdialog.h b/kaddressbook/xxportselectdialog.h new file mode 100644 index 000000000..e785ec318 --- /dev/null +++ b/kaddressbook/xxportselectdialog.h @@ -0,0 +1,84 @@ +/* + This file is part of KAddressBook. + Copyright (c) 2002 Anders Lund <anders.lund@lund.tdcadsl.dk> + 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 XXPORTSELECTDIALOG_H +#define XXPORTSELECTDIALOG_H + +#include <kabc/addresseelist.h> +#include <kabc/field.h> +#include <kdialogbase.h> + +#include "filter.h" + +class QButtonGroup; +class QComboBox; +class QListView; +class QListViewItem; +class QRadioButton; + +namespace KAB { +class Core; +} + +class KComboBox; + +class XXPortSelectDialog : public KDialogBase +{ + Q_OBJECT + + public: + XXPortSelectDialog( KAB::Core *core, bool sort, QWidget* parent, + const char* name = 0 ); + + KABC::AddresseeList contacts(); + + private slots: + void filterChanged( int ); + void categoryClicked( QListViewItem * i ); + + protected slots: + void slotHelp(); + + private: + void initGUI(); + QStringList categories() const; + + QButtonGroup* mButtonGroup; + QRadioButton* mUseCategories; + QRadioButton* mUseFilters; + QRadioButton* mUseWholeBook; + QRadioButton* mUseSelection; + QComboBox* mFiltersCombo; + QListView* mCategoriesView; + + KComboBox *mFieldCombo; + KComboBox *mSortTypeCombo; + + KAB::Core *mCore; + KABC::AddresseeList mAddresseeList; + Filter::List mFilters; + KABC::Field::List mFields; + bool mUseSorting; +}; + +#endif diff --git a/kaddressbook/zone.tab b/kaddressbook/zone.tab new file mode 100644 index 000000000..11408e290 --- /dev/null +++ b/kaddressbook/zone.tab @@ -0,0 +1,371 @@ +# TZ zone descriptions +# +# From Paul Eggert <eggert@twinsun.com> (1996-08-05): +# +# This file contains a table with the following columns: +# 1. ISO 3166 2-character country code. See the file `iso3166.tab'. +# 2. Latitude and longitude of the zone's principal location +# in ISO 6709 sign-degrees-minutes-seconds format, +# either +-DDMM+-DDDMM or +-DDMMSS+-DDDMMSS, +# first latitude (+ is north), then longitude (+ is east). +# 3. Zone name used in value of TZ environment variable. +# 4. Comments; present if and only if the country has multiple rows. +# +# Columns are separated by a single tab. +# The table is sorted first by country, then an order within the country that +# (1) makes some geographical sense, and +# (2) puts the most populous zones first, where that does not contradict (1). +# +# Lines beginning with `#' are comments. +# +#country- +#code coordinates TZ comments +AD +4230+00131 Europe/Andorra +AE +2518+05518 Asia/Dubai +AF +3431+06912 Asia/Kabul +AG +1703-06148 America/Antigua +AI +1812-06304 America/Anguilla +AL +4120+01950 Europe/Tirane +AM +4011+04430 Asia/Yerevan +AN +1211-06900 America/Curacao +AO -0848+01314 Africa/Luanda +AQ -7750+16636 Antarctica/McMurdo McMurdo Station, Ross Island +AQ -9000+00000 Antarctica/South_Pole Amundsen-Scott Station, South Pole +AQ -6448-06406 Antarctica/Palmer Palmer Station, Anvers Island +AQ -6736+06253 Antarctica/Mawson Mawson Station, Holme Bay +AQ -6835+07758 Antarctica/Davis Davis Station, Vestfold Hills +AQ -6617+11031 Antarctica/Casey Casey Station, Bailey Peninsula +AQ -6640+14001 Antarctica/DumontDUrville Dumont-d'Urville Base, Terre Adelie +AR -3436-05827 America/Buenos_Aires E Argentina (BA, DF, SC, TF) +AR -3257-06040 America/Rosario NE Argentina (SF, ER, CN, MN, CC, FM, LP, CH) +AR -3124-06411 America/Cordoba W Argentina (CB, SA, TM, LR, SJ, SL, NQ, RN) +AR -2411-06518 America/Jujuy Jujuy (JY) +AR -2828-06547 America/Catamarca Catamarca (CT) +AR -3253-06849 America/Mendoza Mendoza (MZ) +AS -1416-17042 Pacific/Pago_Pago +AT +4813+01620 Europe/Vienna +AU -3133+15905 Australia/Lord_Howe Lord Howe Island +AU -4253+14719 Australia/Hobart Tasmania +AU -3749+14458 Australia/Melbourne Victoria +AU -3352+15113 Australia/Sydney New South Wales - most locations +AU -3157+14127 Australia/Broken_Hill New South Wales - Broken Hill +AU -2728+15302 Australia/Brisbane Queensland - most locations +AU -2016+14900 Australia/Lindeman Queensland - Holiday Islands +AU -3455+13835 Australia/Adelaide South Australia +AU -1228+13050 Australia/Darwin Northern Territory +AU -3157+11551 Australia/Perth Western Australia +AW +1230-06858 America/Aruba +AZ +4023+04951 Asia/Baku +BA +4352+01825 Europe/Sarajevo +BB +1306-05937 America/Barbados +BD +2343+09025 Asia/Dacca +BE +5050+00420 Europe/Brussels +BF +1222-00131 Africa/Ouagadougou +BG +4241+02319 Europe/Sofia +BH +2623+05035 Asia/Bahrain +BI -0323+02922 Africa/Bujumbura +BJ +0629+00237 Africa/Porto-Novo +BM +3217-06446 Atlantic/Bermuda +BN +0456+11455 Asia/Brunei +BO -1630-06809 America/La_Paz +BR -0351-03225 America/Noronha Fernando de Noronha +BR -0343-03830 America/Fortaleza NE Brazil (AP, east PA, MA, PI, CE, RN, PR, PE) +BR -0940-03543 America/Maceio ENE Brazil (AL, SE, TO) +BR -2332-04637 America/Sao_Paulo S & SE Brazil (BA, GO, DF, MG, ES, RJ, SP, PR, SC, RS) +BR -1535-05605 America/Cuiaba SW Brazil (MT, MS) +BR -0308-06001 America/Manaus NW Brazil (RR, west PA, AM, RO) +BR -0934-06731 America/Porto_Acre Acre +BS +2505-07721 America/Nassau +BT +2728+08939 Asia/Thimbu +BW -2545+02555 Africa/Gaborone +BY +5354+02734 Europe/Minsk +BZ +1730-08812 America/Belize +CA +4734-05243 America/St_Johns Newfoundland Island +CA +4439-06336 America/Halifax Atlantic Time - Nova Scotia (most places), NB, W Labrador, E Quebec & PEI +CA +4612-05957 America/Glace_Bay Atlantic Time - Nova Scotia - places that did not observe DST 1966-1971 +CA +5320-06025 America/Goose_Bay Atlantic Time - E Labrador +CA +6608-06544 America/Pangnirtung Atlantic Time - Northwest Territories +CA +4531-07334 America/Montreal Eastern Time - Ontario & Quebec - most locations +CA +4901-08816 America/Nipigon Eastern Time - Ontario & Quebec - places that did not observe DST 1967-1973 +CA +4823-08915 America/Thunder_Bay Eastern Time - Thunder Bay, Ontario +CA +6344-06828 America/Iqaluit Eastern Time - Northwest Territories +CA +4953-09709 America/Winnipeg Central Time - Manitoba & west Ontario +CA +4843-09429 America/Rainy_River Central Time - Rainy River & Fort Frances, Ontario +CA +6245-09210 America/Rankin_Inlet Central Time - Northwest Territories +CA +5024-10439 America/Regina Central Standard Time - Saskatchewan - most locations +CA +5017-10750 America/Swift_Current Central Standard Time - Saskatchewan - midwest +CA +5333-11328 America/Edmonton Mountain Time - Alberta, east British Columbia & west Saskatchewan +CA +6227-11421 America/Yellowknife Mountain Time - central Northwest Territories +CA +6825-11330 America/Inuvik Mountain Time - west Northwest Territories +CA +5946-12014 America/Dawson_Creek Mountain Standard Time - Dawson Creek & Fort Saint John, British Columbia +CA +4916-12307 America/Vancouver Pacific Time - west British Columbia +CA +6043-13503 America/Whitehorse Pacific Time - south Yukon +CA +6404-13925 America/Dawson Pacific Time - north Yukon +CC -1210+09655 Indian/Cocos +CD -0418+01518 Africa/Kinshasa west Dem. Rep. of Congo +CD -1140+02728 Africa/Lubumbashi east Dem. Rep. of Congo +CF +0422+01835 Africa/Bangui +CG -0416+01517 Africa/Brazzaville +CH +4723+00832 Europe/Zurich +CI +0519-00402 Africa/Abidjan +CK -2114-15946 Pacific/Rarotonga +CL -3327-07040 America/Santiago mainland +CL -2710-10927 Pacific/Easter Easter Island +CM +0403+00942 Africa/Douala +CN +4545+12641 Asia/Harbin north Manchuria +CN +3114+12128 Asia/Shanghai China coast +CN +2217+11409 Asia/Hong_Kong Hong Kong +CN +2934+10635 Asia/Chungking China mountains +CN +4348+08735 Asia/Urumqi Tibet & Xinjiang +CN +3929+07559 Asia/Kashgar Eastern Turkestan +CO +0436-07405 America/Bogota +CR +0956-08405 America/Costa_Rica +CU +2308-08222 America/Havana +CV +1455-02331 Atlantic/Cape_Verde +CX -1025+10543 Indian/Christmas +CY +3510+03322 Asia/Nicosia +CZ +5005+01426 Europe/Prague +DE +5230+01322 Europe/Berlin +DJ +1136+04309 Africa/Djibouti +DK +5540+01235 Europe/Copenhagen +DM +1518-06124 America/Dominica +DO +1828-06954 America/Santo_Domingo +DZ +3647+00303 Africa/Algiers +EC -0210-07950 America/Guayaquil mainland +EC -0054-08936 Pacific/Galapagos Galapagos Islands +EE +5925+02445 Europe/Tallinn +EG +3003+03115 Africa/Cairo +EH +2709-01312 Africa/El_Aaiun +ER +1520+03853 Africa/Asmera +ES +4024-00341 Europe/Madrid mainland +ES +3553-00519 Africa/Ceuta Ceuta & Melilla +ES +2806-01524 Atlantic/Canary Canary Islands +ET +0902+03842 Africa/Addis_Ababa +FI +6010+02458 Europe/Helsinki +FJ -1808+17825 Pacific/Fiji +FK -5142-05751 Atlantic/Stanley +FM +0931+13808 Pacific/Yap Yap +FM +0725+15147 Pacific/Truk Truk (Chuuk) +FM +0658+15813 Pacific/Ponape Ponape (Pohnpei) +FM +0519+16259 Pacific/Kosrae Kosrae +FO +6201-00646 Atlantic/Faeroe +FR +4852+00220 Europe/Paris +GA +0023+00927 Africa/Libreville +GB +512830-0001845 Europe/London Great Britain +GB +5435-00555 Europe/Belfast Northern Ireland +GD +1203-06145 America/Grenada +GE +4143+04449 Asia/Tbilisi +GF +0456-05220 America/Cayenne +GH +0533-00013 Africa/Accra +GI +3608-00521 Europe/Gibraltar +GL +7030-02215 America/Scoresbysund east Greenland +GL +6411-05144 America/Godthab southwest Greenland +GL +7634-06847 America/Thule northwest Greenland +GM +1328-01639 Africa/Banjul +GN +0931-01343 Africa/Conakry +GP +1614-06132 America/Guadeloupe +GQ +0345+00847 Africa/Malabo +GR +3758+02343 Europe/Athens +GS -5416-03632 Atlantic/South_Georgia +GT +1438-09031 America/Guatemala +GU +1328+14445 Pacific/Guam +GW +1151-01535 Africa/Bissau +GY +0648-05810 America/Guyana +HN +1406-08713 America/Tegucigalpa +HR +4548+01558 Europe/Zagreb +HT +1832-07220 America/Port-au-Prince +HU +4730+01905 Europe/Budapest +ID -0610+10648 Asia/Jakarta Java & Sumatra +ID -0507+11924 Asia/Ujung_Pandang Borneo & Celebes +ID -0232+14042 Asia/Jayapura Irian Jaya & the Moluccas +IE +5320-00615 Europe/Dublin +IL +3146+03514 Asia/Jerusalem +IN +2232+08822 Asia/Calcutta +IO -0720+07225 Indian/Chagos +IQ +3321+04425 Asia/Baghdad +IR +3540+05126 Asia/Tehran +IS +6409-02151 Atlantic/Reykjavik +IT +4154+01229 Europe/Rome +JM +1800-07648 America/Jamaica +JO +3157+03556 Asia/Amman +JP +3542+13946 Asia/Tokyo most locations +KE -0117+03649 Africa/Nairobi +KG +4254+07436 Asia/Bishkek +KH +1133+10455 Asia/Phnom_Penh +KI +0125+17300 Pacific/Tarawa Gilbert Islands +KI -0308-17105 Pacific/Enderbury Phoenix Islands +KI +0152-15720 Pacific/Kiritimati Line Islands +KM -1141+04316 Indian/Comoro +KN +1718-06243 America/St_Kitts +KP +3901+12545 Asia/Pyongyang +KR +3733+12658 Asia/Seoul +KW +2920+04759 Asia/Kuwait +KY +1918-08123 America/Cayman +KZ +4315+07657 Asia/Alma-Ata east Kazakhstan +KZ +5017+05710 Asia/Aqtobe central Kazakhstan +KZ +4431+05016 Asia/Aqtau west Kazakhstan +LA +1758+10236 Asia/Vientiane +LB +3353+03530 Asia/Beirut +LC +1401-06100 America/St_Lucia +LI +4709+00931 Europe/Vaduz +LK +0656+07951 Asia/Colombo +LR +0618-01047 Africa/Monrovia +LS -2928+02730 Africa/Maseru +LT +5441+02519 Europe/Vilnius +LU +4936+00609 Europe/Luxembourg +LV +5657+02406 Europe/Riga +LY +3254+01311 Africa/Tripoli +MA +3339-00735 Africa/Casablanca +MC +4342+00723 Europe/Monaco +MD +4700+02850 Europe/Chisinau +MG -1855+04731 Indian/Antananarivo +MH +0709+17112 Pacific/Majuro most locations +MH +0905+16720 Pacific/Kwajalein Kwajalein +MK +4159+02126 Europe/Skopje +ML +1239-00800 Africa/Bamako southwest Mali +ML +1446-00301 Africa/Timbuktu northeast Mali +MM +1647+09610 Asia/Rangoon +MN +4755+10653 Asia/Ulan_Bator +MO +2214+11335 Asia/Macao +MP +1512+14545 Pacific/Saipan +MQ +1436-06105 America/Martinique +MR +1806-01557 Africa/Nouakchott +MS +1644-06213 America/Montserrat +MT +3554+01431 Europe/Malta +MU -2010+05730 Indian/Mauritius +MV +0410+07330 Indian/Maldives +MW -1547+03500 Africa/Blantyre +MX +1924-09909 America/Mexico_City Central Time +MX +2313-10625 America/Mazatlan Mountain Time +MX +3152-11637 America/Ensenada Pacific Time - most locations +MX +3232-11701 America/Tijuana Pacific Time - north Baja California +MY +0310+10142 Asia/Kuala_Lumpur peninsular Malaysia +MY +0133+11020 Asia/Kuching Sabah & Sarawak +MZ -2558+03235 Africa/Maputo +NA -2234+01706 Africa/Windhoek +NC -2216+16530 Pacific/Noumea +NE +1331+00207 Africa/Niamey +NF -2903+16758 Pacific/Norfolk +NG +0627+00324 Africa/Lagos +NI +1209-08617 America/Managua +NL +5222+00454 Europe/Amsterdam +NO +5955+01045 Europe/Oslo +NP +2743+08519 Asia/Katmandu +NR -0031+16655 Pacific/Nauru +NU -1901+16955 Pacific/Niue +NZ -3652+17446 Pacific/Auckland most locations +NZ -4355-17630 Pacific/Chatham Chatham Islands +OM +2336+05835 Asia/Muscat +PA +0858-07932 America/Panama +PE -1203-07703 America/Lima +PF -1732-14934 Pacific/Tahiti Society Islands +PF -0900-13930 Pacific/Marquesas Marquesas Islands +PF -2308-13457 Pacific/Gambier Gambier Islands +PG -0930+14710 Pacific/Port_Moresby +PH +1435+12100 Asia/Manila +PK +2452+06703 Asia/Karachi +PL +5215+02100 Europe/Warsaw +PM +4703-05620 America/Miquelon +PN -2504-13005 Pacific/Pitcairn +PR +182806-0660622 America/Puerto_Rico +PS +3130+03428 Asia/Gaza +PT +3843-00908 Europe/Lisbon mainland +PT +3238-01654 Atlantic/Madeira Madeira Islands +PT +3744-02540 Atlantic/Azores Azores +PW +0720+13429 Pacific/Palau +PY -2516-05740 America/Asuncion +QA +2517+05132 Asia/Qatar +RE -2052+05528 Indian/Reunion +RO +4426+02606 Europe/Bucharest +RU +5443+02030 Europe/Kaliningrad Moscow-01 - Kaliningrad +RU +5545+03735 Europe/Moscow Moscow+00 - west Russia +RU +5312+05009 Europe/Samara Moscow+01 - Caspian Sea +RU +5651+06036 Asia/Yekaterinburg Moscow+02 - Urals +RU +5500+07324 Asia/Omsk Moscow+03 - west Siberia +RU +5502+08255 Asia/Novosibirsk Moscow+03 - Novosibirsk +RU +5601+09250 Asia/Krasnoyarsk Moscow+04 - Yenisei River +RU +5216+10420 Asia/Irkutsk Moscow+05 - Lake Baikal +RU +6200+12940 Asia/Yakutsk Moscow+06 - Lena River +RU +4310+13156 Asia/Vladivostok Moscow+07 - Amur River +RU +5934+15048 Asia/Magadan Moscow+08 - Magadan & Sakhalin +RU +5301+15839 Asia/Kamchatka Moscow+09 - Kamchatka +RU +6445+17729 Asia/Anadyr Moscow+10 - Bering Sea +RW -0157+03004 Africa/Kigali +SA +2438+04643 Asia/Riyadh +SB -0932+16012 Pacific/Guadalcanal +SC -0440+05528 Indian/Mahe +SD +1536+03232 Africa/Khartoum +SE +5920+01803 Europe/Stockholm +SG +0117+10351 Asia/Singapore +SH -1555-00542 Atlantic/St_Helena +SI +4603+01431 Europe/Ljubljana +SJ +7800+01600 Arctic/Longyearbyen Svalbard +SJ +7059-00805 Atlantic/Jan_Mayen Jan Mayen +SK +4809+01707 Europe/Bratislava +SL +0830-01315 Africa/Freetown +SM +4355+01228 Europe/San_Marino +SN +1440-01726 Africa/Dakar +SO +0204+04522 Africa/Mogadishu +SR +0550-05510 America/Paramaribo +ST +0020+00644 Africa/Sao_Tome +SV +1342-08912 America/El_Salvador +SY +3330+03618 Asia/Damascus +SZ -2618+03106 Africa/Mbabane +TC +2128-07108 America/Grand_Turk +TD +1207+01503 Africa/Ndjamena +TF -492110+0701303 Indian/Kerguelen +TG +0608+00113 Africa/Lome +TH +1345+10031 Asia/Bangkok +TJ +3835+06848 Asia/Dushanbe +TK -0922-17114 Pacific/Fakaofo +TM +3757+05823 Asia/Ashkhabad +TN +3648+01011 Africa/Tunis +TO -2110+17510 Pacific/Tongatapu +TR +4101+02858 Europe/Istanbul +TT +1039-06131 America/Port_of_Spain +TV -0831+17913 Pacific/Funafuti +TW +2503+12130 Asia/Taipei +TZ -0648+03917 Africa/Dar_es_Salaam +UA +5026+03031 Europe/Kiev most locations +UA +4457+03406 Europe/Simferopol Crimea +UG +0019+03225 Africa/Kampala +UM +1700-16830 Pacific/Johnston Johnston Atoll +UM +2813-17722 Pacific/Midway Midway Islands +UM +1917+16637 Pacific/Wake Wake Island +US +404251-0740023 America/New_York Eastern Time +US +421953-0830245 America/Detroit Eastern Time - Michigan - most locations +US +381515-0854534 America/Louisville Eastern Time - Louisville, Kentucky +US +394606-0860929 America/Indianapolis Eastern Standard Time - Indiana - most locations +US +382232-0862041 America/Indiana/Marengo Eastern Standard Time - Indiana - Crawford County +US +411745-0863730 America/Indiana/Knox Eastern Standard Time - Indiana - Starke County +US +384452-0850402 America/Indiana/Vevay Eastern Standard Time - Indiana - Switzerland County +US +415100-0873900 America/Chicago Central Time +US +450628-0873651 America/Menominee Central Time - Michigan - Wisconsin border +US +394421-1045903 America/Denver Mountain Time +US +433649-1161209 America/Boise Mountain Time - south Idaho & east Oregon +US +364708-1084111 America/Shiprock Mountain Time - Navajo +US +332654-1120424 America/Phoenix Mountain Standard Time - Arizona +US +340308-1181434 America/Los_Angeles Pacific Time +US +611305-1495401 America/Anchorage Alaska Time +US +581807-1342511 America/Juneau Alaska Time - Alaska panhandle +US +593249-1394338 America/Yakutat Alaska Time - Alaska panhandle neck +US +643004-1652423 America/Nome Alaska Time - west Alaska +US +515248-1763929 America/Adak Aleutian Islands +US +211825-1575130 Pacific/Honolulu Hawaii +UY -3453-05611 America/Montevideo +UZ +4120+06918 Asia/Tashkent +VA +4154+01227 Europe/Vatican +VC +1309-06114 America/St_Vincent +VE +1030-06656 America/Caracas +VG +1827-06437 America/Tortola +VI +1821-06456 America/St_Thomas +VN +1045+10640 Asia/Saigon +VU -1740+16825 Pacific/Efate +WF -1318-17610 Pacific/Wallis +WS -1350-17144 Pacific/Apia +YE +1245+04512 Asia/Aden +YT -1247+04514 Indian/Mayotte +YU +4450+02030 Europe/Belgrade +ZA -2615+02800 Africa/Johannesburg +ZM -1525+02817 Africa/Lusaka +ZW -1750+03103 Africa/Harare |