00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #include <qapplication.h>
00025 #include <qclipboard.h>
00026 #include <qcombobox.h>
00027 #include <qdragobject.h>
00028 #include <qevent.h>
00029 #include <qhbox.h>
00030 #include <qlabel.h>
00031 #include <qlayout.h>
00032 #include <qlineedit.h>
00033 #include <qsplitter.h>
00034 #include <qtabwidget.h>
00035 #include <qwidgetstack.h>
00036
00037 #include <kabc/addressbook.h>
00038 #include <kabc/field.h>
00039 #include <kabc/vcardconverter.h>
00040 #include <kapplication.h>
00041 #include <kconfig.h>
00042 #include <kdebug.h>
00043 #include <kglobal.h>
00044 #include <kiconloader.h>
00045 #include <klocale.h>
00046 #include <kmessagebox.h>
00047 #include <kmultipledrag.h>
00048 #include <libkdepim/kvcarddrag.h>
00049
00050 #include "undo.h"
00051 #include "undocmds.h"
00052 #include "viewmanager.h"
00053 #include "configureviewdialog.h"
00054 #include "viewwrapper.h"
00055 #include "iconviewwrapper.h"
00056 #include "tableviewwrapper.h"
00057 #include "detailsviewcontainer.h"
00058 #include "cardviewwrapper.h"
00059 #include "addviewdialog.h"
00060 #include "jumpbuttonbar.h"
00061 #include "addresseeutil.h"
00062 #include "addresseeeditorwidget.h"
00063 #include "filterselectionwidget.h"
00064 #include "featuredistributionlist.h"
00065
00067
00068
00069 ViewManager::ViewManager(KABC::AddressBook *doc, KConfig *config,
00070 QWidget *parent, const char *name)
00071 : QWidget(parent, name)
00072 {
00073 mConfig = config;
00074 mDocument = doc;
00075
00076
00077 initGUI();
00078
00079
00080 mViewDict.setAutoDelete(true);
00081 mViewWrapperDict.setAutoDelete(true);
00082
00083
00084 createViewWrappers();
00085
00086 mActiveView = 0;
00087 }
00088
00089 ViewManager::~ViewManager()
00090 {
00091 unloadViews();
00092 mViewWrapperDict.clear();
00093 }
00094
00095 void ViewManager::readConfig()
00096 {
00097
00098 mConfig->setGroup("Views");
00099 mViewNameList = mConfig->readListEntry("Names");
00100
00101 if (mViewNameList.size() == 0)
00102 {
00103
00104 mViewNameList << i18n("Default Table View");
00105 }
00106
00107 mFilterList = Filter::restore(mConfig, "Filter");
00108 filtersChanged(mFilterList);
00109 mConfig->setGroup("Filter");
00110 if (mConfig->hasKey("Active"))
00111 {
00112 emit(setCurrentFilterName(mConfig->readEntry("Active")));
00113 }
00114
00115
00116 QDictIterator<KAddressBookView> iter(mViewDict);
00117 for (iter.toFirst(); iter.current(); ++iter)
00118 {
00119 mConfig->setGroup(iter.currentKey());
00120 iter.current()->readConfig(mConfig);
00121 }
00122
00123 QValueList<int> splitterSize;
00124 mConfig->setGroup( "Splitter" );
00125 splitterSize = mConfig->readIntListEntry( "FeaturesSplitter" );
00126 if ( splitterSize.count() == 0 ) {
00127 splitterSize.append( width() / 2 );
00128 splitterSize.append( width() / 2 );
00129 }
00130 mQSpltFeatures->setSizes( splitterSize );
00131
00132 splitterSize = mConfig->readIntListEntry( "DetailsSplitter" );
00133 if ( splitterSize.count() == 0 ) {
00134 splitterSize.append( height() / 2 );
00135 splitterSize.append( height() / 2 );
00136 }
00137 mQSpltDetails->setSizes( splitterSize );
00138 }
00139
00140 void ViewManager::writeConfig()
00141 {
00142
00143 QDictIterator<KAddressBookView> iter(mViewDict);
00144 for ( iter.toFirst(); iter.current(); ++iter ) {
00145 mConfig->setGroup( iter.currentKey() );
00146 (*iter)->writeConfig( mConfig );
00147 }
00148
00149 Filter::save( mConfig, QString( "Filter" ), mFilterList );
00150 mConfig->setGroup( "Filter" );
00151 mConfig->writeEntry( "Active", mCurrentFilter.name() );
00152
00153
00154 mConfig->setGroup( "Views" );
00155 mConfig->writeEntry( "Names", mViewNameList );
00156
00157 mConfig->setGroup( "Splitter" );
00158 mConfig->writeEntry( "FeaturesSplitter", mQSpltFeatures->sizes() );
00159 mConfig->writeEntry( "DetailsSplitter", mQSpltDetails->sizes() );
00160 }
00161
00162 QStringList ViewManager::selectedUids()
00163 {
00164 return mActiveView->selectedUids();
00165 }
00166
00167 void ViewManager::sendMail()
00168 {
00169 QString emailAddrs = mActiveView->selectedEmails();
00170 kapp->invokeMailer( emailAddrs, "" );
00171 }
00172
00173 void ViewManager::sendMail(const QString& addressee)
00174 {
00175 kapp->invokeMailer(addressee, "");
00176 }
00177
00178 void ViewManager::browse(const QString& url)
00179 {
00180 kapp->invokeBrowser(url);
00181 }
00182
00183 void ViewManager::deleteAddressee()
00184 {
00185 KABC::Addressee a;
00186
00187
00188 QStringList uidList = mActiveView->selectedUids();
00189
00190 if (uidList.size() > 0)
00191 {
00192 PwDeleteCommand *command = new PwDeleteCommand( mDocument, uidList );
00193 UndoStack::instance()->push( command );
00194 RedoStack::instance()->clear();
00195
00196
00197 mActiveView->refresh();
00198 emit selected( QString::null );
00199 addresseeSelected( QString::null );
00200
00201 emit modified();
00202 }
00203 }
00204
00205 void ViewManager::paste()
00206 {
00207 QClipboard *cb = QApplication::clipboard();
00208 PwPasteCommand *command = new PwPasteCommand( mDocument, cb->text() );
00209 UndoStack::instance()->push( command );
00210 RedoStack::instance()->clear();
00211
00212 modified();
00213 mActiveView->refresh();
00214 }
00215
00216 void ViewManager::copy()
00217 {
00218 QStringList uidList = mActiveView->selectedUids();
00219 KABC::Addressee::List aList;
00220 KABC::Addressee a;
00221 QString clipText;
00222
00223 QStringList::Iterator iter;
00224 for ( iter = uidList.begin(); iter != uidList.end(); ++iter ) {
00225 aList.append(mDocument->findByUid(*iter));
00226 }
00227
00228 clipText = AddresseeUtil::addresseesToClipboard(aList);
00229 kdDebug() << "ViewManager::copy: " << clipText << endl;
00230 QClipboard *cb = QApplication::clipboard();
00231 cb->setText( clipText );
00232 }
00233
00234 void ViewManager::cut()
00235 {
00236 QStringList uidList = mActiveView->selectedUids();
00237
00238 if (uidList.size() > 0)
00239 {
00240 PwCutCommand *command = new PwCutCommand(mDocument, uidList);
00241 UndoStack::instance()->push( command );
00242 RedoStack::instance()->clear();
00243
00244 mActiveView->refresh();
00245 emit modified();
00246 }
00247 }
00248
00249 void ViewManager::setSelected(QString uid, bool selected)
00250 {
00251 mActiveView->setSelected(uid, selected);
00252 }
00253
00254 void ViewManager::unloadViews()
00255 {
00256 mViewDict.clear();
00257 mActiveView = 0;
00258 }
00259
00260 void ViewManager::setActiveView(const QString &name)
00261 {
00262
00263 KAddressBookView *view = 0;
00264
00265
00266 if (mActiveView && (mActiveView->name() == name))
00267 return;
00268
00269
00270
00271
00272
00273
00274 view = mViewDict.find(name);
00275
00276
00277 if (view == 0)
00278 {
00279 KConfig *config = kapp->config();
00280 config->setGroup(name);
00281 QString type = config->readEntry("Type", "Table");
00282
00283 kdDebug() << "ViewManager::setActiveView: creating view - "
00284 << name << endl;
00285
00286
00287 ViewWrapper *wrapper = mViewWrapperDict.find(type);
00288 if (wrapper)
00289 view = wrapper->createView(mDocument, mViewWidgetStack,
00290 name.latin1());
00291
00292 if (view)
00293 {
00294 mViewDict.insert(name, view);
00295 mViewWidgetStack->addWidget(view);
00296 view->readConfig(config);
00297
00298
00299 connect(view, SIGNAL(selected(const QString &)),
00300 this, SIGNAL(selected(const QString &)));
00301 connect(view, SIGNAL(selected(const QString &)),
00302 this, SLOT(addresseeSelected(const QString &)));
00303 connect(view, SIGNAL(executed(const QString &)),
00304 this, SIGNAL(executed(const QString &)));
00305 connect(view, SIGNAL(modified()),
00306 this, SIGNAL(modified()));
00307 connect(view, SIGNAL(dropped(QDropEvent*)),
00308 this, SLOT(dropped(QDropEvent*)));
00309 connect(view, SIGNAL(startDrag()), this, SLOT(startDrag()));
00310 }
00311 }
00312
00313
00314 if ( view )
00315 {
00316 mActiveView = view;
00317 mViewWidgetStack->raiseWidget(view);
00318
00319
00320
00321 if (view->defaultFilterType() == KAddressBookView::None)
00322 {
00323 emit(setCurrentFilter(0));
00324 }
00325 else if (view->defaultFilterType() == KAddressBookView::Active)
00326 {
00327 emit(setCurrentFilterName(mCurrentFilter.name()));
00328 }
00329 else
00330 {
00331 QString filterName = view->defaultFilterName();
00332 emit(setCurrentFilterName(filterName));
00333 }
00334
00335
00336
00337 refreshIncrementalSearchCombo();
00338
00339 mActiveView->refresh( QString::null );
00340 }
00341 else
00342 {
00343 kdDebug() << "ViewManager::setActiveView: unable to find view\n";
00344 }
00345 }
00346
00347 void ViewManager::refresh(QString uid)
00348 {
00349 if ( mActiveView )
00350 {
00351 mActiveView->refresh(uid);
00352 addresseeSelected(uid);
00353 }
00354 }
00355
00356 void ViewManager::modifyView()
00357 {
00358 if ( !mActiveView )
00359 return;
00360
00361 ViewWrapper *wrapper;
00362 ConfigureViewDialog *dialog = 0;
00363
00364
00365 wrapper = mViewWrapperDict.find(mActiveView->type());
00366
00367 if (wrapper)
00368 {
00369
00370 Filter::save(mConfig, "Filter", mFilterList);
00371
00372 dialog = wrapper->createConfigureViewDialog(mActiveView->name(),
00373 mDocument,
00374 this, "ConfigureViewDialog");
00375 }
00376
00377
00378 if (dialog)
00379 {
00380
00381 mConfig->setGroup(mActiveView->name());
00382 dialog->readConfig(mConfig);
00383
00384 if (dialog->exec())
00385 {
00386
00387 dialog->writeConfig(mConfig);
00388 mActiveView->readConfig(mConfig);
00389
00390
00391
00392
00393 if (mActiveView->defaultFilterType() == KAddressBookView::None)
00394 {
00395 emit(setCurrentFilter(0));
00396 }
00397 else if (mActiveView->defaultFilterType() == KAddressBookView::Active)
00398 {
00399 emit(setCurrentFilterName(mCurrentFilter.name()));
00400 }
00401 else
00402 {
00403 QString filterName = mActiveView->defaultFilterName();
00404 emit(setCurrentFilterName(filterName));
00405 }
00406
00407 refreshIncrementalSearchCombo();
00408
00409 mActiveView->refresh();
00410
00411
00412 delete dialog;
00413 }
00414 }
00415 }
00416
00417 void ViewManager::deleteView()
00418 {
00419
00420 QString text = i18n("Are you sure that you want to delete the view \"%1\"?").arg( mActiveView->name() );
00421
00422 QString caption = i18n("Confirm Delete");
00423
00424 if (KMessageBox::questionYesNo(this, text, caption) == KMessageBox::Yes)
00425 {
00426 mViewNameList.remove(mActiveView->name());
00427
00428
00429 KConfig *config = kapp->config();
00430 config->deleteGroup( mActiveView->name() );
00431
00432 mViewDict.remove(mActiveView->name());
00433 mActiveView = 0;
00434
00435
00436
00437 emit viewConfigChanged(QString::null);
00438 }
00439 }
00440
00441 void ViewManager::addView()
00442 {
00443
00444 AddViewDialog dialog(&mViewWrapperDict, this, "AddViewDialog");
00445
00446 if (dialog.exec())
00447 {
00448
00449 QString newName = dialog.viewName();
00450 QString type = dialog.viewType();
00451
00452
00453 bool firstConflict = true;
00454 int numTries = 1;
00455 while (mViewNameList.contains(newName) > 0)
00456 {
00457 if (!firstConflict)
00458 {
00459 newName = newName.left(newName.length()-4);
00460 firstConflict = false;
00461 }
00462
00463 newName.sprintf("%s <%d>", newName.latin1(), numTries);
00464 numTries++;
00465 }
00466
00467
00468 mViewNameList << newName;
00469
00470
00471
00472 KConfig *config = kapp->config();
00473 config->deleteGroup(newName);
00474 config->setGroup(newName);
00475 config->writeEntry("Type", type);
00476
00477
00478 emit viewConfigChanged(newName);
00479
00480
00481 modifyView();
00482 }
00483 }
00484
00485 void ViewManager::createViewWrappers()
00486 {
00487 ViewWrapper *wrapper;
00488
00489
00490
00491
00492 wrapper = new IconViewWrapper();
00493 mViewWrapperDict.insert(wrapper->type(), wrapper);
00494
00495 wrapper = new TableViewWrapper();
00496 mViewWrapperDict.insert(wrapper->type(), wrapper);
00497
00498 wrapper = new CardViewWrapper();
00499 mViewWrapperDict.insert(wrapper->type(), wrapper);
00500 }
00501
00502 void ViewManager::initGUI()
00503 {
00504 QHBoxLayout *l = new QHBoxLayout( this );
00505 l->setSpacing( KDialogBase::spacingHint() );
00506
00507 mQSpltFeatures = new QSplitter( this );
00508 mQSpltFeatures->setOrientation( Qt::Vertical );
00509
00510 mQSpltDetails = new QSplitter( mQSpltFeatures );
00511
00512 mViewWidgetStack = new QWidgetStack( mQSpltDetails, "mViewWidgetStack" );
00513
00514 mDetails = new ViewContainer( mQSpltDetails );
00515 connect( mDetails, SIGNAL(addresseeChanged()), SLOT(addresseeModified()) );
00516 connect( mDetails, SIGNAL(sendEmail(const QString&)),
00517 SLOT(sendMail(const QString&)) );
00518 connect( mDetails, SIGNAL(browse(const QString&)),
00519 SLOT(browse(const QString&)) );
00520
00521 mJumpButtonBar = new JumpButtonBar( this, "mJumpButtonBar" );
00522 connect( mJumpButtonBar, SIGNAL(jumpToLetter(const QChar &)),
00523 this, SLOT(jumpToLetter(const QChar &)) );
00524
00525
00526
00527
00528 mFeatureBar = new QHBox( mQSpltFeatures );
00529
00530 mQuickEdit = new AddresseeEditorWidget( mFeatureBar, "mQuickEdit" );
00531 connect( mQuickEdit, SIGNAL(modified()), SLOT(addresseeModified()) );
00532
00533 mFeatDistList = new FeatureDistributionList( mDocument, mFeatureBar );
00534 connect( mFeatDistList, SIGNAL(modified()), SLOT(slotModified()) );
00535
00536 l->addWidget( mQSpltFeatures );
00537 l->setStretchFactor( mQSpltFeatures, 100 );
00538 l->addWidget( mJumpButtonBar );
00539 l->setStretchFactor( mJumpButtonBar, 1 );
00540 }
00541
00542 void ViewManager::refreshIncrementalSearchCombo()
00543 {
00544 QStringList items;
00545
00546
00547
00548
00549
00550
00551 KABC::Field::List fields = mActiveView->fields();
00552
00553 mIncrementalSearchFields.clear();
00554
00555 KABC::Field::List::ConstIterator it;
00556 int i = 0;
00557 for( it = fields.begin(); it != fields.end(); ++it ) {
00558 items.append((*it)->label());
00559 mIncrementalSearchFields.append( *it );
00560 ++i;
00561 }
00562 mCurrentIncSearchField=mIncrementalSearchFields.first();
00563 emit(setIncSearchFields(items));
00564 }
00565
00566 void ViewManager::incSearch(const QString& text, int field)
00567 {
00568 mCurrentIncSearchField=mIncrementalSearchFields[field];
00569 if( mActiveView )
00570 mActiveView->incrementalSearch(text, mCurrentIncSearchField);
00571 }
00572
00573 void ViewManager::jumpToLetter(const QChar &ch)
00574 {
00575
00576 if ( mActiveView )
00577 mActiveView->incrementalSearch(QString(ch), mCurrentIncSearchField);
00578 }
00579
00580 void ViewManager::setJumpButtonBarVisible(bool visible)
00581 {
00582 if (visible)
00583 mJumpButtonBar->show();
00584 else
00585 mJumpButtonBar->hide();
00586 }
00587
00588 void ViewManager::setDetailsVisible(bool visible)
00589 {
00590 if( visible ) {
00591 mDetails->show();
00592 } else {
00593 mDetails->hide();
00594 }
00595 }
00596
00597
00598 bool ViewManager::isQuickEditVisible()
00599 {
00600 return mQuickEdit->isVisible();
00601 }
00602
00603 void ViewManager::dropped(QDropEvent *e)
00604 {
00605 kdDebug() << "ViewManager::dropped: got a drop event" << endl;
00606
00607 QString clipText, vcards;
00608 QStrList urls;
00609
00610
00611 if ( QUriDrag::decode( e, urls) ) {
00612 QPtrListIterator<char> it( urls );
00613 int c = urls.count();
00614 if ( c > 1 ) {
00615 QString questionString = i18n( "Import one contact into your addressbook?", "Import %n contacts into your addressbook?", c );
00616 if ( KMessageBox::questionYesNo( this, questionString, i18n( "Import Contacts?" ) ) == KMessageBox::Yes ) {
00617 for ( ; it.current(); ++it) {
00618 KURL url(*it);
00619 emit importVCard( url.path(), false );
00620 }
00621 }
00622 } else if ( c == 1 ) {
00623 KURL url(*it);
00624 emit importVCard( url.path(), true );
00625 }
00626 } else if ( KVCardDrag::decode( e, vcards ) ) {
00627 KABC::Addressee addr;
00628 KABC::VCardConverter converter;
00629 QStringList list = QStringList::split( "\r\n\r\n", vcards );
00630 QStringList::Iterator it;
00631 for ( it = list.begin(); it != list.end(); ++it ) {
00632 if ( converter.vCardToAddressee( (*it).stripWhiteSpace(), addr ) ) {
00633 KABC::Addressee a = mDocument->findByUid( addr.uid() );
00634 if ( a.isEmpty() ) {
00635 mDocument->insertAddressee( addr );
00636 emit modified();
00637 }
00638 }
00639 }
00640
00641 mActiveView->refresh();
00642 }
00643 }
00644
00645 void ViewManager::startDrag()
00646 {
00647 kdDebug() << "ViewManager::startDrag: starting to drag" << endl;
00648
00649
00650 KABC::Addressee::List aList;
00651 QStringList uidList = selectedUids();
00652 QStringList::Iterator iter;
00653 for (iter = uidList.begin(); iter != uidList.end(); ++iter)
00654 aList.append(mDocument->findByUid(*iter));
00655
00656 KMultipleDrag *drag = new KMultipleDrag( this );
00657 drag->addDragObject( new QTextDrag( AddresseeUtil::addresseesToClipboard(aList), this ) );
00658 KABC::Addressee::List::Iterator it;
00659 QStringList vcards;
00660 for ( it = aList.begin(); it != aList.end(); ++it ) {
00661 QString vcard = QString::null;
00662 KABC::VCardConverter converter;
00663 if ( converter.addresseeToVCard( *it, vcard ) )
00664 vcards.append( vcard );
00665 }
00666 drag->addDragObject( new KVCardDrag( vcards.join( "\r\n" ), this ) );
00667
00668 drag->setPixmap( KGlobal::iconLoader()->loadIcon( "vcard", KIcon::Desktop ) );
00669 drag->dragCopy();
00670 }
00671
00672 void ViewManager::addresseeSelected(const QString &uid)
00673 {
00674 KABC::Addressee a = mDocument->findByUid(uid);
00675 mQuickEdit->setAddressee(a);
00676 mDetails->setAddressee(a);
00677 }
00678
00679 void ViewManager::addresseeModified()
00680 {
00681 KABC::Addressee a;
00682
00683
00684 mQuickEdit->save();
00685 a = mQuickEdit->addressee();
00686
00687
00688
00689
00690
00691 mDocument->insertAddressee( a );
00692 mActiveView->refresh( a.uid() );
00693
00694 emit modified();
00695 }
00696
00697 void ViewManager::filtersChanged(const Filter::List &list)
00698 {
00699 mFilterList = list;
00700
00701 QStringList names;
00702 Filter::List::Iterator iter;
00703 for (iter = mFilterList.begin(); iter != mFilterList.end(); ++iter)
00704 names << (*iter).name();
00705
00706
00707 emit(setFilterNames(names));
00708 mCurrentFilter=Filter();
00709 }
00710
00711 void ViewManager::filterActivated(int index)
00712 {
00713 if (index < 0) {
00714 mCurrentFilter = Filter();
00715 } else {
00716 mCurrentFilter = mFilterList[ index ];
00717 }
00718
00719
00720
00721 if ( mActiveView ) {
00722 mActiveView->setFilter( mCurrentFilter );
00723 mActiveView->refresh();
00724 }
00725 }
00726
00727 void ViewManager::slotModified()
00728 {
00729 modified();
00730 }
00731
00732 void ViewManager::showFeatures( int id )
00733 {
00734 if ( id == 0 ) {
00735 mFeatureBar->hide();
00736 } else {
00737 switch( id ) {
00738 default:
00739 case 1:
00740 mQuickEdit->show();
00741 mFeatDistList->hide();
00742 break;
00743 case 2:
00744 mQuickEdit->hide();
00745 mFeatDistList->show();
00746 break;
00747 }
00748 mFeatureBar->show();
00749 }
00750 }
00751
00752 #include "viewmanager.moc"