1/*
2 This file is part of libkabc.
3 Copyright (c) 2001 Cornelius Schumacher <schumacher@kde.org>
4
5 This library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Library General Public
7 License as published by the Free Software Foundation; either
8 version 2 of the License, or (at your option) any later version.
9
10 This library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Library General Public License for more details.
14
15 You should have received a copy of the GNU Library General Public License
16 along with this library; see the file COPYING.LIB. If not, write to
17 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18 Boston, MA 02110-1301, USA.
19*/
20
21#include "addresseedialog.h"
22#ifndef KDEPIM_NO_KRESOURCES
23#include "stdaddressbook.h"
24#endif
25
26#include <kdebug.h>
27#include <klocalizedstring.h>
28
29#include <QtCore/QPointer>
30#include <QtCore/QRegExp>
31#include <QGroupBox>
32#include <QLayout>
33#include <QPushButton>
34
35using namespace KABC;
36
37class AddresseeItem::Private
38{
39 public:
40 Addressee mAddressee;
41};
42
43AddresseeItem::AddresseeItem( QTreeWidget *parent, const Addressee &addressee ) :
44 QTreeWidgetItem( parent ), d( new Private )
45{
46 d->mAddressee = addressee;
47
48 setText( Name, addressee.realName() );
49 setText( Email, addressee.preferredEmail() );
50}
51
52AddresseeItem::~AddresseeItem()
53{
54 delete d;
55}
56
57Addressee AddresseeItem::addressee() const
58{
59 return d->mAddressee;
60}
61
62QString AddresseeItem::key( int column, bool ) const
63{
64 if ( column == Email ) {
65 QString value = text( Email );
66 const QRegExp emailRe( QLatin1String( "<\\S*>" ) );
67 int match = emailRe.indexIn( value );
68 if ( match > -1 ) {
69 value = value.mid( match + 1, emailRe.matchedLength() - 2 );
70 }
71
72 return value.toLower();
73 }
74
75 return text( column ).toLower();
76}
77
78class AddresseeDialog::Private
79{
80 public:
81 Private( bool multiple )
82 : mMultiple( multiple )
83 {
84 }
85
86 void addressBookChanged();
87 void selectItem( const QString & );
88 void updateEdit();
89 void addSelected( QTreeWidgetItem *item );
90 void removeSelected();
91
92 void loadAddressBook();
93 void addCompletionItem( const QString &str, QTreeWidgetItem *item );
94
95 bool mMultiple;
96
97 QTreeWidget *mAddresseeList;
98 KLineEdit *mAddresseeEdit;
99
100 QTreeWidget *mSelectedList;
101
102#ifndef KDEPIM_NO_KRESOURCES
103 AddressBook *mAddressBook;
104#endif
105
106 QHash<QString, QTreeWidgetItem*> mItemDict;
107 QHash<QString, QTreeWidgetItem*> mSelectedDict;
108};
109
110AddresseeDialog::AddresseeDialog( QWidget *parent, bool multiple )
111 : KDialog( parent ), d( new Private( multiple ) )
112{
113 setCaption( i18nc( "@title:window", "Select Addressee" ) );
114 setButtons( Ok | Cancel );
115 setDefaultButton( Ok );
116
117 QWidget *topWidget = new QWidget( this );
118 setMainWidget( topWidget );
119
120 QBoxLayout *topLayout = new QHBoxLayout( topWidget );
121 QBoxLayout *listLayout = new QVBoxLayout;
122 topLayout->addLayout( listLayout );
123
124 d->mAddresseeList = new QTreeWidget( topWidget );
125 d->mAddresseeList->setColumnCount( 2 );
126 QStringList headerTitles;
127 headerTitles << i18nc( "@title:column addressee name", "Name" )
128 << i18nc( "@title:column addressee email", "Email" );
129 d->mAddresseeList->setHeaderItem( new QTreeWidgetItem( headerTitles ) );
130 listLayout->addWidget( d->mAddresseeList );
131 connect( d->mAddresseeList, SIGNAL(itemDoubleClicked(QTreeWidgetItem*,int)),
132 SLOT(accept()) );
133 connect( d->mAddresseeList, SIGNAL(itemSelectionChanged()),
134 SLOT(updateEdit()) );
135
136 d->mAddresseeEdit = new KLineEdit( topWidget );
137 d->mAddresseeEdit->setCompletionMode( KGlobalSettings::CompletionAuto );
138 connect( d->mAddresseeEdit->completionObject(), SIGNAL(match(QString)),
139 SLOT(selectItem(QString)) );
140 d->mAddresseeEdit->setFocus();
141 d->mAddresseeEdit->completionObject()->setIgnoreCase( true );
142 listLayout->addWidget( d->mAddresseeEdit );
143
144 setInitialSize( QSize( 450, 300 ) );
145
146 if ( d->mMultiple ) {
147 QBoxLayout *selectedLayout = new QVBoxLayout;
148 topLayout->addLayout( selectedLayout );
149
150 QGroupBox *selectedGroup =
151 new QGroupBox( i18nc( "@title:group selected addressees", "Selected" ), topWidget );
152 QHBoxLayout *groupLayout = new QHBoxLayout;
153 selectedGroup->setLayout( groupLayout );
154 selectedLayout->addWidget( selectedGroup );
155
156 d->mSelectedList = new QTreeWidget( selectedGroup );
157 groupLayout->addWidget( d->mSelectedList );
158 d->mSelectedList->setColumnCount( 2 );
159 QStringList headerTitles;
160 headerTitles << i18nc( "@title:column addressee name", "Name" )
161 << i18nc( "@title:column addressee email", "Email" );
162 d->mSelectedList->setHeaderItem( new QTreeWidgetItem( headerTitles ) );
163
164 connect( d->mSelectedList, SIGNAL(itemDoubleClicked(QTreeWidgetItem*,int)),
165 SLOT(removeSelected()) );
166
167 QPushButton *unselectButton =
168 new QPushButton( i18nc( "@action:button unselect addressee", "Unselect" ), selectedGroup );
169 selectedLayout->addWidget( unselectButton );
170 connect( unselectButton, SIGNAL(clicked()), SLOT(removeSelected()) );
171
172 connect( d->mAddresseeList, SIGNAL(itemClicked(QTreeWidgetItem*,int)),
173 SLOT(addSelected(QTreeWidgetItem*)) );
174
175 setInitialSize( QSize( 650, 350 ) );
176 }
177
178#ifndef KDEPIM_NO_KRESOURCES
179 d->mAddressBook = StdAddressBook::self( true );
180 connect( d->mAddressBook, SIGNAL(addressBookChanged(AddressBook*)),
181 SLOT(addressBookChanged()) );
182 connect( d->mAddressBook, SIGNAL(loadingFinished(Resource*)),
183 SLOT(addressBookChanged()) );
184#endif
185
186 d->loadAddressBook();
187}
188
189AddresseeDialog::~AddresseeDialog()
190{
191 delete d;
192}
193
194Addressee AddresseeDialog::addressee() const
195{
196 AddresseeItem *aItem = 0;
197
198 if ( d->mMultiple ) {
199 aItem = dynamic_cast<AddresseeItem *>( d->mSelectedList->topLevelItem( 0 ) );
200 } else {
201 QList<QTreeWidgetItem*> selected = d->mAddresseeList->selectedItems();
202 if ( !selected.isEmpty() ) {
203 aItem = dynamic_cast<AddresseeItem *>( selected.at( 0 ) );
204 }
205 }
206
207 if ( aItem ) {
208 return aItem->addressee();
209 }
210 return Addressee();
211}
212
213Addressee::List AddresseeDialog::addressees() const
214{
215 Addressee::List al;
216 AddresseeItem *aItem = 0;
217
218 if ( d->mMultiple ) {
219 const int numberOfTopItem( d->mSelectedList->topLevelItemCount() );
220 for ( int i = 0; i < numberOfTopItem; ++i ) {
221 aItem = dynamic_cast<AddresseeItem *>( d->mSelectedList->topLevelItem( i ) );
222 if ( aItem ) {
223 al.append( aItem->addressee() );
224 }
225 }
226 } else {
227 QList<QTreeWidgetItem*> selected = d->mAddresseeList->selectedItems();
228 if ( !selected.isEmpty() ) {
229 aItem = dynamic_cast<AddresseeItem *>( selected.at( 0 ) );
230 }
231 if ( aItem ) {
232 al.append( aItem->addressee() );
233 }
234 }
235
236 return al;
237}
238
239Addressee AddresseeDialog::getAddressee( QWidget *parent )
240{
241 Addressee contact;
242
243 QPointer<AddresseeDialog> dlg = new AddresseeDialog( parent );
244 if ( dlg->exec() && dlg ) {
245 contact = dlg->addressee();
246 }
247
248 delete dlg;
249
250 return contact;
251}
252
253Addressee::List AddresseeDialog::getAddressees( QWidget *parent )
254{
255 Addressee::List contacts;
256
257 QPointer<AddresseeDialog> dlg = new AddresseeDialog( parent, true );
258 if ( dlg->exec() && dlg ) {
259 contacts = dlg->addressees();
260 }
261
262 delete dlg;
263
264 return contacts;
265}
266
267void AddresseeDialog::Private::loadAddressBook()
268{
269 mAddresseeList->clear();
270 mItemDict.clear();
271 mAddresseeEdit->completionObject()->clear();
272
273#ifndef KDEPIM_NO_KRESOURCES
274 AddressBook::Iterator it;
275 for ( it = mAddressBook->begin(); it != mAddressBook->end(); ++it ) {
276 AddresseeItem *item = new AddresseeItem( mAddresseeList, ( *it ) );
277 addCompletionItem( ( *it ).realName(), item );
278 addCompletionItem( ( *it ).preferredEmail(), item );
279 }
280#endif
281}
282
283void AddresseeDialog::Private::addCompletionItem( const QString &str, QTreeWidgetItem *item )
284{
285 if ( str.isEmpty() ) {
286 return;
287 }
288
289 mItemDict.insert( str, item );
290 mAddresseeEdit->completionObject()->addItem( str );
291}
292
293void AddresseeDialog::Private::selectItem( const QString &str )
294{
295 if ( str.isEmpty() ) {
296 return;
297 }
298
299 QTreeWidgetItem *item = mItemDict.value( str, 0 );
300 if ( item ) {
301 mAddresseeList->blockSignals( true );
302 mAddresseeList->setItemSelected( item, true );
303 mAddresseeList->scrollToItem( item );
304 mAddresseeList->blockSignals( false );
305 }
306}
307
308void AddresseeDialog::Private::updateEdit()
309{
310 QList<QTreeWidgetItem*> selected = mAddresseeList->selectedItems();
311 if ( selected.isEmpty() ) {
312 return;
313 }
314 QTreeWidgetItem *item = selected.at( 0 );
315 mAddresseeEdit->setText( item->text( 0 ) );
316 mAddresseeEdit->setSelection( 0, item->text( 0 ).length() );
317}
318
319void AddresseeDialog::Private::addSelected( QTreeWidgetItem *item )
320{
321 AddresseeItem *addrItem = dynamic_cast<AddresseeItem *>( item );
322 if ( !addrItem ) {
323 return;
324 }
325
326 Addressee a = addrItem->addressee();
327
328 QTreeWidgetItem *selectedItem = mSelectedDict.value( a.uid(), 0 );
329 if ( !selectedItem ) {
330 selectedItem = new AddresseeItem( mSelectedList, a );
331 mSelectedDict.insert( a.uid(), selectedItem );
332 }
333}
334
335void AddresseeDialog::Private::removeSelected()
336{
337 QList<QTreeWidgetItem*> selected = mSelectedList->selectedItems();
338 if ( selected.isEmpty() ) {
339 return;
340 }
341 AddresseeItem *addrItem = dynamic_cast<AddresseeItem *>( selected.at( 0 ) );
342 if ( !addrItem ) {
343 return;
344 }
345
346 mSelectedDict.remove( addrItem->addressee().uid() );
347 delete addrItem;
348}
349
350void AddresseeDialog::Private::addressBookChanged()
351{
352 loadAddressBook();
353}
354
355#include "moc_addresseedialog.cpp"
356