kaddressbooktableview.cpp
00001 /* 00002 This file is part of KAddressBook. 00003 Copyright (c) 2002 Mike Pilone <mpilone@slac.com> 00004 00005 This program is free software; you can redistribute it and/or modify 00006 it under the terms of the GNU General Public License as published by 00007 the Free Software Foundation; either version 2 of the License, or 00008 (at your option) any later version. 00009 00010 This program is distributed in the hope that it will be useful, 00011 but WITHOUT ANY WARRANTY; without even the implied warranty of 00012 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00013 GNU General Public License for more details. 00014 00015 You should have received a copy of the GNU General Public License 00016 along with this program; if not, write to the Free Software 00017 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 00018 00019 As a special exception, permission is given to link this program 00020 with any edition of TQt, and distribute the resulting executable, 00021 without including the source code for TQt in the source distribution. 00022 */ 00023 00024 #include <tqapplication.h> 00025 #include <tqlayout.h> 00026 #include <tqheader.h> 00027 #include <tqvbox.h> 00028 #include <tqlistbox.h> 00029 #include <tqwidget.h> 00030 #include <tqfile.h> 00031 #include <tqimage.h> 00032 #include <tqcombobox.h> 00033 #include <tqapplication.h> 00034 #include <tqdragobject.h> 00035 #include <tqevent.h> 00036 #include <tqurl.h> 00037 #include <tqpixmap.h> 00038 00039 #include <kabc/addressbook.h> 00040 #include <kapplication.h> 00041 #include <kconfig.h> 00042 #include <kcolorbutton.h> 00043 #include <kdebug.h> 00044 #include <kglobal.h> 00045 #include <kiconloader.h> 00046 #include <klineedit.h> 00047 #include <klocale.h> 00048 #include <kmessagebox.h> 00049 #include <kurl.h> 00050 #include <kurlrequester.h> 00051 #include <kimproxy.h> 00052 00053 #include "configuretableviewdialog.h" 00054 #include "contactlistview.h" 00055 #include "core.h" 00056 #include "kabprefs.h" 00057 #include "undocmds.h" 00058 00059 #include "kaddressbooktableview.h" 00060 00061 class TableViewFactory : public ViewFactory 00062 { 00063 public: 00064 KAddressBookView *view( KAB::Core *core, TQWidget *parent, const char *name ) 00065 { 00066 return new KAddressBookTableView( core, parent, name ); 00067 } 00068 00069 TQString type() const { return I18N_NOOP( "Table" ); } 00070 00071 TQString description() const { return i18n( "A listing of contacts in a table. Each cell of " 00072 "the table holds a field of the contact." ); } 00073 00074 ViewConfigureWidget *configureWidget( KABC::AddressBook *ab, TQWidget *parent, 00075 const char *name = 0 ) 00076 { 00077 return new ConfigureTableViewWidget( ab, parent, name ); 00078 } 00079 }; 00080 00081 extern "C" { 00082 void *init_libkaddrbk_tableview() 00083 { 00084 return ( new TableViewFactory ); 00085 } 00086 } 00087 00088 KAddressBookTableView::KAddressBookTableView( KAB::Core *core, 00089 TQWidget *parent, const char *name ) 00090 : KAddressBookView( core, parent, name ) 00091 { 00092 mMainLayout = new TQVBoxLayout( viewWidget(), 2 ); 00093 00094 // The list view will be created when the config is read. 00095 mListView = 0; 00096 mIMProxy = 0; 00097 } 00098 00099 KAddressBookTableView::~KAddressBookTableView() 00100 { 00101 } 00102 00103 void KAddressBookTableView::reconstructListView() 00104 { 00105 if ( mListView ) { 00106 disconnect( mListView, TQT_SIGNAL( selectionChanged() ), 00107 this, TQT_SLOT( addresseeSelected() ) ); 00108 disconnect( mListView, TQT_SIGNAL( executed( TQListViewItem* ) ), 00109 this, TQT_SLOT( addresseeExecuted( TQListViewItem* ) ) ); 00110 disconnect( mListView, TQT_SIGNAL( doubleClicked( TQListViewItem* ) ), 00111 this, TQT_SLOT( addresseeExecuted( TQListViewItem* ) ) ); 00112 disconnect( mListView, TQT_SIGNAL( startAddresseeDrag() ), 00113 this, TQT_SIGNAL( startDrag() ) ); 00114 disconnect( mListView, TQT_SIGNAL( addresseeDropped( TQDropEvent* ) ), 00115 this, TQT_SIGNAL( dropped( TQDropEvent* ) ) ); 00116 delete mListView; 00117 } 00118 00119 mListView = new ContactListView( this, core()->addressBook(), viewWidget() ); 00120 00121 mListView->setShowIM( mIMProxy != 0 ); 00122 00123 // Add the columns 00124 const KABC::Field::List fieldList( fields() ); 00125 KABC::Field::List::ConstIterator it; 00126 00127 int c = 0; 00128 for ( it = fieldList.begin(); it != fieldList.end(); ++it ) { 00129 mListView->addColumn( (*it)->label() ); 00130 mListView->setColumnWidthMode( c++, TQListView::Manual ); 00131 } 00132 00133 if ( mListView->showIM() ) { 00134 // IM presence is added separately, because it's not a KABC field. 00135 // If you want to make this appear as the leftmost column by default, move 00136 // this block immediately before the preceding for loop 00137 // after the declaration of c. 00138 mListView->addColumn( i18n( "Presence" ) ); 00139 mListView->setIMColumn( c++ ); 00140 } 00141 00142 mListView->setFullWidth( true ); 00143 00144 connect( mListView, TQT_SIGNAL( selectionChanged() ), 00145 this, TQT_SLOT( addresseeSelected() ) ); 00146 connect( mListView, TQT_SIGNAL( startAddresseeDrag() ), 00147 this, TQT_SIGNAL( startDrag() ) ); 00148 connect( mListView, TQT_SIGNAL( addresseeDropped( TQDropEvent* ) ), 00149 this, TQT_SIGNAL( dropped( TQDropEvent* ) ) ); 00150 connect( mListView, TQT_SIGNAL( contextMenu( KListView*, TQListViewItem*, const TQPoint& ) ), 00151 this, TQT_SLOT( rmbClicked( KListView*, TQListViewItem*, const TQPoint& ) ) ); 00152 connect( mListView->header(), TQT_SIGNAL( clicked( int ) ), 00153 this, TQT_SIGNAL( sortFieldChanged() ) ); 00154 00155 if ( KABPrefs::instance()->honorSingleClick() ) 00156 connect( mListView, TQT_SIGNAL( executed( TQListViewItem* ) ), 00157 this, TQT_SLOT( addresseeExecuted( TQListViewItem* ) ) ); 00158 else 00159 connect( mListView, TQT_SIGNAL( doubleClicked( TQListViewItem* ) ), 00160 this, TQT_SLOT( addresseeExecuted( TQListViewItem* ) ) ); 00161 00162 refresh(); 00163 00164 mListView->setSorting( 0, true ); 00165 mMainLayout->addWidget( mListView ); 00166 mMainLayout->activate(); 00167 mListView->show(); 00168 } 00169 00170 KABC::Field *KAddressBookTableView::sortField() const 00171 { 00172 // we have hardcoded sorting, so we have to return a hardcoded field :( 00173 return ( mListView->sortColumn() == -1 ? fields()[ 0 ] : fields()[ mListView->sortColumn() ] ); 00174 } 00175 00176 void KAddressBookTableView::writeConfig( KConfig *config ) 00177 { 00178 KAddressBookView::writeConfig( config ); 00179 00180 mListView->saveLayout( config, config->group() ); 00181 } 00182 00183 void KAddressBookTableView::readConfig( KConfig *config ) 00184 { 00185 KAddressBookView::readConfig( config ); 00186 00187 if ( config->readBoolEntry( "InstantMessagingPresence", false ) ) { 00188 if ( !mIMProxy ) { 00189 mIMProxy = KIMProxy::instance( kapp->dcopClient() ); 00190 connect( mIMProxy, TQT_SIGNAL( sigContactPresenceChanged( const TQString& ) ), 00191 this, TQT_SLOT( updatePresence( const TQString& ) ) ); 00192 } 00193 } else { 00194 if ( mIMProxy ) { 00195 disconnect( mIMProxy, TQT_SIGNAL( sigContactPresenceChanged( const TQString& ) ), 00196 this, TQT_SLOT( updatePresence( const TQString& ) ) ); 00197 mIMProxy = 0; 00198 } 00199 } 00200 00201 // The config could have changed the fields, so we need to reconstruct 00202 // the listview. 00203 reconstructListView(); 00204 00205 // Set the list view options 00206 mListView->setAlternateBackgroundEnabled( config->readBoolEntry( "ABackground", true ) ); 00207 mListView->setSingleLineEnabled( config->readBoolEntry( "SingleLine", false ) ); 00208 mListView->setToolTipsEnabled( config->readBoolEntry( "ToolTips", true ) ); 00209 00210 if ( config->readBoolEntry( "Background", false ) ) 00211 mListView->setBackgroundPixmap( config->readPathEntry( "BackgroundName" ) ); 00212 00213 // Restore the layout of the listview 00214 mListView->restoreLayout( config, config->group() ); 00215 } 00216 00217 void KAddressBookTableView::refresh( const TQString &uid ) 00218 { 00219 if ( uid.isEmpty() ) { 00220 // Clear the list view 00221 TQString currentUID, nextUID; 00222 ContactListViewItem *currentItem = dynamic_cast<ContactListViewItem*>( mListView->currentItem() ); 00223 if ( currentItem ) { 00224 ContactListViewItem *nextItem = dynamic_cast<ContactListViewItem*>( currentItem->itemBelow() ); 00225 if ( nextItem ) 00226 nextUID = nextItem->addressee().uid(); 00227 currentUID = currentItem->addressee().uid(); 00228 } 00229 00230 mListView->clear(); 00231 00232 currentItem = 0; 00233 const KABC::Addressee::List addresseeList( addressees() ); 00234 KABC::Addressee::List::ConstIterator it( addresseeList.begin() ); 00235 const KABC::Addressee::List::ConstIterator endIt( addresseeList.end() ); 00236 for ( ; it != endIt; ++it ) { 00237 ContactListViewItem *item = new ContactListViewItem( *it, mListView, 00238 core()->addressBook(), fields(), mIMProxy ); 00239 if ( (*it).uid() == currentUID ) 00240 currentItem = item; 00241 else if ( (*it).uid() == nextUID && !currentItem ) 00242 currentItem = item; 00243 } 00244 00245 // Sometimes the background pixmap gets messed up when we add lots 00246 // of items. 00247 mListView->repaint(); 00248 00249 if ( currentItem ) { 00250 mListView->setCurrentItem( currentItem ); 00251 mListView->ensureItemVisible( currentItem ); 00252 } 00253 } else { 00254 // Only need to update on entry. Iterate through and try to find it 00255 ContactListViewItem *ceItem; 00256 TQPtrList<TQListViewItem> selectedItems( mListView->selectedItems() ); 00257 TQListViewItem *it; 00258 for ( it = selectedItems.first(); it; it = selectedItems.next() ) { 00259 ceItem = dynamic_cast<ContactListViewItem*>( it ); 00260 if ( ceItem && ceItem->addressee().uid() == uid ) { 00261 ceItem->refresh(); 00262 return; 00263 } 00264 } 00265 refresh( TQString() ); 00266 } 00267 } 00268 00269 TQStringList KAddressBookTableView::selectedUids() 00270 { 00271 TQStringList uidList; 00272 ContactListViewItem *item; 00273 00274 TQListViewItemIterator it( mListView, TQListViewItemIterator::Selected ); 00275 while ( it.current() ) { 00276 item = dynamic_cast<ContactListViewItem*>( it.current() ); 00277 if ( item ) 00278 uidList << item->addressee().uid(); 00279 00280 ++it; 00281 } 00282 00283 return uidList; 00284 } 00285 00286 void KAddressBookTableView::setSelected( const TQString &uid, bool selected ) 00287 { 00288 if ( uid.isEmpty() ) 00289 mListView->selectAll( selected ); 00290 else { 00291 TQListViewItemIterator it( mListView ); 00292 while ( it.current() ) { 00293 ContactListViewItem *item = dynamic_cast<ContactListViewItem*>( it.current() ); 00294 if ( item && (item->addressee().uid() == uid) ) { 00295 mListView->setSelected( item, selected ); 00296 00297 if ( selected ) 00298 mListView->ensureItemVisible( item ); 00299 } 00300 00301 ++it; 00302 } 00303 } 00304 } 00305 00306 void KAddressBookTableView::setFirstSelected( bool selected ) 00307 { 00308 if ( mListView->firstChild() ) { 00309 mListView->setSelected( mListView->firstChild(), selected ); 00310 mListView->ensureItemVisible( mListView->firstChild() ); 00311 } 00312 } 00313 00314 void KAddressBookTableView::addresseeSelected() 00315 { 00316 // We need to try to find the first selected item. This might not be the 00317 // last selected item, but when TQListView is in multiselection mode, 00318 // there is no way to figure out which one was 00319 // selected last. 00320 bool found =false; 00321 00322 TQListViewItemIterator it( mListView, TQListViewItemIterator::Selected ); 00323 while ( it.current() && !found ) { 00324 found = true; 00325 ContactListViewItem *item = dynamic_cast<ContactListViewItem*>( it.current() ); 00326 if ( item ) 00327 emit selected( item->addressee().uid() ); 00328 00329 ++it; 00330 } 00331 00332 if ( !found ) 00333 emit selected( TQString() ); 00334 } 00335 00336 void KAddressBookTableView::addresseeExecuted( TQListViewItem *item ) 00337 { 00338 if ( item ) { 00339 ContactListViewItem *ceItem = dynamic_cast<ContactListViewItem*>( item ); 00340 00341 if ( ceItem ) 00342 emit executed( ceItem->addressee().uid() ); 00343 else 00344 emit executed( TQString() ); 00345 } else { 00346 emit executed( TQString() ); 00347 } 00348 } 00349 00350 void KAddressBookTableView::rmbClicked( KListView*, TQListViewItem*, const TQPoint &point ) 00351 { 00352 popup( point ); 00353 } 00354 00355 void KAddressBookTableView::updatePresence( const TQString &uid ) 00356 { 00357 // find the LVI to update and refresh() it 00358 TQListViewItem *item; 00359 ContactListViewItem *ceItem; 00360 for ( item = mListView->firstChild(); item; item = item->itemBelow() ) { 00361 ceItem = dynamic_cast<ContactListViewItem*>( item ); 00362 if ( ( ceItem != 0L ) && ( ceItem->addressee().uid() == uid ) ) { 00363 ceItem->setHasIM( true ); 00364 ceItem->refresh(); 00365 break; 00366 } 00367 } 00368 00369 if ( mListView->sortColumn() == mListView->imColumn() ) 00370 mListView->sort(); 00371 } 00372 00373 void KAddressBookTableView::scrollUp() 00374 { 00375 TQApplication::postEvent( mListView, new TQKeyEvent( TQEvent::KeyPress, TQt::Key_Up, 0, 0 ) ); 00376 } 00377 00378 void KAddressBookTableView::scrollDown() 00379 { 00380 TQApplication::postEvent( mListView, new TQKeyEvent( TQEvent::KeyPress, TQt::Key_Down, 0, 0 ) ); 00381 } 00382 00383 00384 #include "kaddressbooktableview.moc"