kaddressbook

kaddressbooktableview.cpp
1 /*
2  This file is part of KAddressBook.
3  Copyright (c) 2002 Mike Pilone <mpilone@slac.com>
4 
5  This program is free software; you can redistribute it and/or modify
6  it under the terms of the GNU General Public License as published by
7  the Free Software Foundation; either version 2 of the License, or
8  (at your option) any later version.
9 
10  This program 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
13  GNU General Public License for more details.
14 
15  You should have received a copy of the GNU General Public License
16  along with this program; if not, write to the Free Software
17  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
18 
19  As a special exception, permission is given to link this program
20  with any edition of TQt, and distribute the resulting executable,
21  without including the source code for TQt in the source distribution.
22 */
23 
24 #include <tqapplication.h>
25 #include <tqlayout.h>
26 #include <tqheader.h>
27 #include <tqvbox.h>
28 #include <tqlistbox.h>
29 #include <tqwidget.h>
30 #include <tqfile.h>
31 #include <tqimage.h>
32 #include <tqcombobox.h>
33 #include <tqapplication.h>
34 #include <tqdragobject.h>
35 #include <tqevent.h>
36 #include <tqurl.h>
37 #include <tqpixmap.h>
38 
39 #include <tdeabc/addressbook.h>
40 #include <tdeapplication.h>
41 #include <tdeconfig.h>
42 #include <kcolorbutton.h>
43 #include <kdebug.h>
44 #include <tdeglobal.h>
45 #include <kiconloader.h>
46 #include <klineedit.h>
47 #include <tdelocale.h>
48 #include <tdemessagebox.h>
49 #include <kurl.h>
50 #include <kurlrequester.h>
51 #include <tdeimproxy.h>
52 
53 #include "configuretableviewdialog.h"
54 #include "contactlistview.h"
55 #include "core.h"
56 #include "kabprefs.h"
57 #include "undocmds.h"
58 
59 #include "kaddressbooktableview.h"
60 
61 class TableViewFactory : public ViewFactory
62 {
63  public:
64  KAddressBookView *view( KAB::Core *core, TQWidget *parent, const char *name )
65  {
66  return new KAddressBookTableView( core, parent, name );
67  }
68 
69  TQString type() const { return I18N_NOOP( "Table" ); }
70 
71  TQString description() const { return i18n( "A listing of contacts in a table. Each cell of "
72  "the table holds a field of the contact." ); }
73 
74  ViewConfigureWidget *configureWidget( TDEABC::AddressBook *ab, TQWidget *parent,
75  const char *name = 0 )
76  {
77  return new ConfigureTableViewWidget( ab, parent, name );
78  }
79 };
80 
81 extern "C" {
82  void *init_libkaddrbk_tableview()
83  {
84  return ( new TableViewFactory );
85  }
86 }
87 
88 KAddressBookTableView::KAddressBookTableView( KAB::Core *core,
89  TQWidget *parent, const char *name )
90  : KAddressBookView( core, parent, name )
91 {
92  mMainLayout = new TQVBoxLayout( viewWidget(), 2 );
93 
94  // The list view will be created when the config is read.
95  mListView = 0;
96  mIMProxy = 0;
97 }
98 
99 KAddressBookTableView::~KAddressBookTableView()
100 {
101 }
102 
103 void KAddressBookTableView::reconstructListView()
104 {
105  if ( mListView ) {
106  disconnect( mListView, TQ_SIGNAL( selectionChanged() ),
107  this, TQ_SLOT( addresseeSelected() ) );
108  disconnect( mListView, TQ_SIGNAL( executed( TQListViewItem* ) ),
109  this, TQ_SLOT( addresseeExecuted( TQListViewItem* ) ) );
110  disconnect( mListView, TQ_SIGNAL( doubleClicked( TQListViewItem* ) ),
111  this, TQ_SLOT( addresseeExecuted( TQListViewItem* ) ) );
112  disconnect( mListView, TQ_SIGNAL( startAddresseeDrag() ),
113  this, TQ_SIGNAL( startDrag() ) );
114  disconnect( mListView, TQ_SIGNAL( addresseeDropped( TQDropEvent* ) ),
115  this, TQ_SIGNAL( dropped( TQDropEvent* ) ) );
116  delete mListView;
117  }
118 
119  mListView = new ContactListView( this, core()->addressBook(), viewWidget() );
120 
121  mListView->setShowIM( mIMProxy != 0 );
122 
123  // Add the columns
124  const TDEABC::Field::List fieldList( fields() );
125  TDEABC::Field::List::ConstIterator it;
126 
127  int c = 0;
128  for ( it = fieldList.begin(); it != fieldList.end(); ++it ) {
129  mListView->addColumn( (*it)->label() );
130  mListView->setColumnWidthMode( c++, TQListView::Manual );
131  }
132 
133  if ( mListView->showIM() ) {
134  // IM presence is added separately, because it's not a KABC field.
135  // If you want to make this appear as the leftmost column by default, move
136  // this block immediately before the preceding for loop
137  // after the declaration of c.
138  mListView->addColumn( i18n( "Presence" ) );
139  mListView->setIMColumn( c++ );
140  }
141 
142  mListView->setFullWidth( true );
143 
144  connect( mListView, TQ_SIGNAL( selectionChanged() ),
145  this, TQ_SLOT( addresseeSelected() ) );
146  connect( mListView, TQ_SIGNAL( startAddresseeDrag() ),
147  this, TQ_SIGNAL( startDrag() ) );
148  connect( mListView, TQ_SIGNAL( addresseeDropped( TQDropEvent* ) ),
149  this, TQ_SIGNAL( dropped( TQDropEvent* ) ) );
150  connect( mListView, TQ_SIGNAL( contextMenu( TDEListView*, TQListViewItem*, const TQPoint& ) ),
151  this, TQ_SLOT( rmbClicked( TDEListView*, TQListViewItem*, const TQPoint& ) ) );
152  connect( mListView->header(), TQ_SIGNAL( clicked( int ) ),
153  this, TQ_SIGNAL( sortFieldChanged() ) );
154 
155  if ( KABPrefs::instance()->honorSingleClick() )
156  connect( mListView, TQ_SIGNAL( executed( TQListViewItem* ) ),
157  this, TQ_SLOT( addresseeExecuted( TQListViewItem* ) ) );
158  else
159  connect( mListView, TQ_SIGNAL( doubleClicked( TQListViewItem* ) ),
160  this, TQ_SLOT( addresseeExecuted( TQListViewItem* ) ) );
161 
162  refresh();
163 
164  mListView->setSorting( 0, true );
165  mMainLayout->addWidget( mListView );
166  mMainLayout->activate();
167  mListView->show();
168 }
169 
170 TDEABC::Field *KAddressBookTableView::sortField() const
171 {
172  // we have hardcoded sorting, so we have to return a hardcoded field :(
173  return ( mListView->sortColumn() == -1 ? fields()[ 0 ] : fields()[ mListView->sortColumn() ] );
174 }
175 
176 void KAddressBookTableView::writeConfig( TDEConfig *config )
177 {
179 
180  mListView->saveLayout( config, config->group() );
181 }
182 
183 void KAddressBookTableView::readConfig( TDEConfig *config )
184 {
186 
187  if ( config->readBoolEntry( "InstantMessagingPresence", false ) ) {
188  if ( !mIMProxy ) {
189  mIMProxy = KIMProxy::instance( kapp->dcopClient() );
190  connect( mIMProxy, TQ_SIGNAL( sigContactPresenceChanged( const TQString& ) ),
191  this, TQ_SLOT( updatePresence( const TQString& ) ) );
192  }
193  } else {
194  if ( mIMProxy ) {
195  disconnect( mIMProxy, TQ_SIGNAL( sigContactPresenceChanged( const TQString& ) ),
196  this, TQ_SLOT( updatePresence( const TQString& ) ) );
197  mIMProxy = 0;
198  }
199  }
200 
201  // The config could have changed the fields, so we need to reconstruct
202  // the listview.
203  reconstructListView();
204 
205  // Set the list view options
206  mListView->setAlternateBackgroundEnabled( config->readBoolEntry( "ABackground", true ) );
207  mListView->setSingleLineEnabled( config->readBoolEntry( "SingleLine", false ) );
208  mListView->setToolTipsEnabled( config->readBoolEntry( "ToolTips", true ) );
209 
210  if ( config->readBoolEntry( "Background", false ) )
211  mListView->setBackgroundPixmap( config->readPathEntry( "BackgroundName" ) );
212 
213  // Restore the layout of the listview
214  mListView->restoreLayout( config, config->group() );
215 }
216 
217 void KAddressBookTableView::refresh( const TQString &uid )
218 {
219  if ( uid.isEmpty() ) {
220  // Clear the list view
221  TQString currentUID, nextUID;
222  ContactListViewItem *currentItem = dynamic_cast<ContactListViewItem*>( mListView->currentItem() );
223  if ( currentItem ) {
224  ContactListViewItem *nextItem = dynamic_cast<ContactListViewItem*>( currentItem->itemBelow() );
225  if ( nextItem )
226  nextUID = nextItem->addressee().uid();
227  currentUID = currentItem->addressee().uid();
228  }
229 
230  mListView->clear();
231 
232  currentItem = 0;
233  const TDEABC::Addressee::List addresseeList( addressees() );
234  TDEABC::Addressee::List::ConstIterator it( addresseeList.begin() );
235  const TDEABC::Addressee::List::ConstIterator endIt( addresseeList.end() );
236  for ( ; it != endIt; ++it ) {
237  ContactListViewItem *item = new ContactListViewItem( *it, mListView,
238  core()->addressBook(), fields(), mIMProxy );
239  if ( (*it).uid() == currentUID )
240  currentItem = item;
241  else if ( (*it).uid() == nextUID && !currentItem )
242  currentItem = item;
243  }
244 
245  // Sometimes the background pixmap gets messed up when we add lots
246  // of items.
247  mListView->repaint();
248 
249  if ( currentItem ) {
250  mListView->setCurrentItem( currentItem );
251  mListView->ensureItemVisible( currentItem );
252  }
253  } else {
254  // Only need to update on entry. Iterate through and try to find it
255  ContactListViewItem *ceItem;
256  TQPtrList<TQListViewItem> selectedItems( mListView->selectedItems() );
257  TQListViewItem *it;
258  for ( it = selectedItems.first(); it; it = selectedItems.next() ) {
259  ceItem = dynamic_cast<ContactListViewItem*>( it );
260  if ( ceItem && ceItem->addressee().uid() == uid ) {
261  ceItem->refresh();
262  return;
263  }
264  }
265  refresh( TQString() );
266  }
267 }
268 
270 {
271  TQStringList uidList;
272  ContactListViewItem *item;
273 
274  TQListViewItemIterator it( mListView, TQListViewItemIterator::Selected );
275  while ( it.current() ) {
276  item = dynamic_cast<ContactListViewItem*>( it.current() );
277  if ( item )
278  uidList << item->addressee().uid();
279 
280  ++it;
281  }
282 
283  return uidList;
284 }
285 
286 void KAddressBookTableView::setSelected( const TQString &uid, bool selected )
287 {
288  if ( uid.isEmpty() )
289  mListView->selectAll( selected );
290  else {
291  TQListViewItemIterator it( mListView );
292  while ( it.current() ) {
293  ContactListViewItem *item = dynamic_cast<ContactListViewItem*>( it.current() );
294  if ( item && (item->addressee().uid() == uid) ) {
295  mListView->setSelected( item, selected );
296 
297  if ( selected )
298  mListView->ensureItemVisible( item );
299  }
300 
301  ++it;
302  }
303  }
304 }
305 
307 {
308  if ( mListView->firstChild() ) {
309  mListView->setSelected( mListView->firstChild(), selected );
310  mListView->ensureItemVisible( mListView->firstChild() );
311  }
312 }
313 
315 {
316  // We need to try to find the first selected item. This might not be the
317  // last selected item, but when TQListView is in multiselection mode,
318  // there is no way to figure out which one was
319  // selected last.
320  bool found =false;
321 
322  TQListViewItemIterator it( mListView, TQListViewItemIterator::Selected );
323  while ( it.current() && !found ) {
324  found = true;
325  ContactListViewItem *item = dynamic_cast<ContactListViewItem*>( it.current() );
326  if ( item )
327  emit selected( item->addressee().uid() );
328 
329  ++it;
330  }
331 
332  if ( !found )
333  emit selected( TQString() );
334 }
335 
336 void KAddressBookTableView::addresseeExecuted( TQListViewItem *item )
337 {
338  if ( item ) {
339  ContactListViewItem *ceItem = dynamic_cast<ContactListViewItem*>( item );
340 
341  if ( ceItem )
342  emit executed( ceItem->addressee().uid() );
343  else
344  emit executed( TQString() );
345  } else {
346  emit executed( TQString() );
347  }
348 }
349 
350 void KAddressBookTableView::rmbClicked( TDEListView*, TQListViewItem*, const TQPoint &point )
351 {
352  popup( point );
353 }
354 
355 void KAddressBookTableView::updatePresence( const TQString &uid )
356 {
357  // find the LVI to update and refresh() it
358  TQListViewItem *item;
359  ContactListViewItem *ceItem;
360  for ( item = mListView->firstChild(); item; item = item->itemBelow() ) {
361  ceItem = dynamic_cast<ContactListViewItem*>( item );
362  if ( ( ceItem != 0L ) && ( ceItem->addressee().uid() == uid ) ) {
363  ceItem->setHasIM( true );
364  ceItem->refresh();
365  break;
366  }
367  }
368 
369  if ( mListView->sortColumn() == mListView->imColumn() )
370  mListView->sort();
371 }
372 
373 void KAddressBookTableView::scrollUp()
374 {
375  TQApplication::postEvent( mListView, new TQKeyEvent( TQEvent::KeyPress, TQt::Key_Up, 0, 0 ) );
376 }
377 
378 void KAddressBookTableView::scrollDown()
379 {
380  TQApplication::postEvent( mListView, new TQKeyEvent( TQEvent::KeyPress, TQt::Key_Down, 0, 0 ) );
381 }
382 
383 
384 #include "kaddressbooktableview.moc"
Configure dialog for the table view.
This class is the table view for kaddressbook.
virtual void readConfig(TDEConfig *config)
Called whenever this view should read the config.
virtual void refresh(const TQString &uid=TQString())
Must be overloaded in subclasses to refresh the view.
virtual void setSelected(const TQString &uid=TQString(), bool selected=false)
This method must be overloaded in subclasses.
void rmbClicked(TDEListView *, TQListViewItem *, const TQPoint &)
RBM menu called.
void addresseeSelected()
Called whenever the user selects an addressee in the list view.
void addresseeExecuted(TQListViewItem *)
Called whenever the user executes an addressee.
virtual void setFirstSelected(bool selected=true)
Selects the first contact in the view.
virtual void writeConfig(TDEConfig *config)
Called whenever this view should write the config.
virtual TDEABC::Field * sortField() const
virtual TQStringList selectedUids()
Must be overloaded in subclasses.
void updatePresence(const TQString &uid)
Called to update the presence of a single item.
Base class for all views in kaddressbook.
void startDrag()
This signal is emitted whenever a user attempts to start a drag in the view.
TQWidget * viewWidget()
This method returns the widget that should be used as the parent for all view components.
void dropped(TQDropEvent *)
This signal is emitted whenever the user drops something on the view.
void popup(const TQPoint &point)
Call this slot to popup a rmb menu.
KAB::Core * core() const
void selected(const TQString &uid)
This signal should be emitted by a subclass whenever an addressee is selected.
virtual void writeConfig(TDEConfig *)
Called whenever this view should write the config.
void executed(const TQString &uid)
This signal should be emitted by a subclass whenever an addressee is executed.
TDEABC::Addressee::List addressees()
Returns a list of the addressees that should be displayed.
virtual void readConfig(TDEConfig *config)
Called whenever this view should read the config.
TDEABC::Field::List fields() const
Returns a list of the fields that should be displayed.
void sortFieldChanged()
This signal is emitted whenever the sort field changed.
This widget is the base class for all view configuration widgets.