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
61class 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
81extern "C" {
82 void *init_libkaddrbk_tableview()
83 {
84 return ( new TableViewFactory );
85 }
86}
87
88KAddressBookTableView::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
99KAddressBookTableView::~KAddressBookTableView()
100{
101}
102
103void 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
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
176void KAddressBookTableView::writeConfig( TDEConfig *config )
177{
179
180 mListView->saveLayout( config, config->group() );
181}
182
183void KAddressBookTableView::readConfig( TDEConfig *config )
184{
186
187 if ( config->readBoolEntry( "InstantMessagingPresence", false ) ) {
188 if ( !mIMProxy ) {
189 mIMProxy = KIMProxy::instance( tdeApp->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
217void 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
286void 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
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
350void KAddressBookTableView::rmbClicked( TDEListView*, TQListViewItem*, const TQPoint &point )
351{
352 popup( point );
353}
354
355void 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
373void KAddressBookTableView::scrollUp()
374{
375 TQApplication::postEvent( mListView, new TQKeyEvent( TQEvent::KeyPress, TQt::Key_Up, 0, 0 ) );
376}
377
378void 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.