kaddressbook

jumpbuttonbar.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 <tqbuttongroup.h>
26 #include <tqevent.h>
27 #include <tqlayout.h>
28 #include <tqpushbutton.h>
29 #include <tqstring.h>
30 #include <tqstyle.h>
31 
32 #include <tdeabc/addressbook.h>
33 #include <tdeabc/field.h>
34 #include <kdebug.h>
35 #include <kdialog.h>
36 #include <tdelocale.h>
37 
38 #include "core.h"
39 
40 #include "jumpbuttonbar.h"
41 
42 class JumpButton : public TQPushButton
43 {
44  public:
45  JumpButton( const TQString &firstChar, const TQString &lastChar,
46  TQWidget *parent );
47 
48  TQString firstChar() const { return mChar; }
49 
50  private:
51  TQString mChar;
52 };
53 
54 JumpButton::JumpButton( const TQString &firstChar, const TQString &lastChar,
55  TQWidget *parent )
56  : TQPushButton( "", parent ), mChar( firstChar )
57 {
58  setToggleButton( true );
59  if ( !lastChar.isEmpty() )
60  setText( TQString( "%1 - %2" ).arg( firstChar.upper() ).arg( lastChar.upper() ) );
61  else
62  setText( firstChar.upper() );
63 }
64 
65 JumpButtonBar::JumpButtonBar( KAB::Core *core, TQWidget *parent, const char *name )
66  : TQWidget( parent, name ), mCore( core )
67 {
68  setMinimumSize( 1, 1 );
69 
70  TQVBoxLayout *layout = new TQVBoxLayout( this, 0, 0 );
71  layout->setAlignment( TQt::AlignTop );
72  layout->setAutoAdd( true );
73  layout->setResizeMode( TQLayout::FreeResize );
74 
75  mGroupBox = new TQButtonGroup( 1, TQt::Horizontal, this );
76  mGroupBox->setExclusive( true );
77  mGroupBox->layout()->setSpacing( 0 );
78  mGroupBox->layout()->setMargin( 0 );
79  mGroupBox->setFrameStyle( TQFrame::NoFrame );
80 }
81 
82 JumpButtonBar::~JumpButtonBar()
83 {
84 }
85 
86 void JumpButtonBar::updateButtons()
87 {
88  int currentButton = mGroupBox->selectedId();
89 
90  // the easiest way to remove all buttons ;)
91  mButtons.setAutoDelete( true );
92  mButtons.clear();
93  mButtons.setAutoDelete( false );
94 
95  TQStringList characters;
96 
97  // calculate how many buttons are possible
98  TQFontMetrics fm = fontMetrics();
99  TQPushButton *btn = new TQPushButton( "", this );
100  btn->hide();
101  TQSize buttonSize = style().sizeFromContents( TQStyle::CT_PushButton, btn,
102  fm.size( ShowPrefix, "X - X") ).
103  expandedTo( TQApplication::globalStrut() );
104  delete btn;
105 
106  int buttonHeight = buttonSize.height() + 8;
107  uint possibleButtons = (height() / buttonHeight) - 1;
108 
109  TQString character;
110  TDEABC::AddressBook *ab = mCore->addressBook();
111  TDEABC::AddressBook::Iterator it;
112  for ( it = ab->begin(); it != ab->end(); ++it ) {
113  TDEABC::Field *field = 0;
114  field = mCore->currentSortField();
115  if ( field ) {
116  setEnabled( true );
117  if ( !field->value( *it ).isEmpty() )
118  character = field->value( *it )[ 0 ].lower();
119  } else {
120  setEnabled( false );
121  return;
122  }
123 
124  if ( !character.isEmpty() && !characters.contains( character ) )
125  characters.append( character );
126  }
127 
128  sortListLocaleAware( characters );
129 
130  if ( characters.count() <= possibleButtons ) {
131  // at first the easy case: all buttons fits in window
132  for ( uint i = 0; i < characters.count(); ++i ) {
133  JumpButton *button = new JumpButton( characters[ i ], TQString(),
134  mGroupBox );
135  connect( button, TQ_SIGNAL( clicked() ), this, TQ_SLOT( letterClicked() ) );
136  mButtons.append( button );
137  button->show();
138  }
139  } else {
140  if ( possibleButtons == 0 ) // to avoid crashes on startup
141  return;
142  int offset = characters.count() / possibleButtons;
143  int odd = characters.count() % possibleButtons;
144  if ( odd )
145  offset++;
146 
147  int current = 0;
148  for ( uint i = 0; i < possibleButtons; ++i ) {
149  if ( characters.count() - current == 0 )
150  continue;
151  if ( characters.count() - current <= possibleButtons - i ) {
152  JumpButton *button = new JumpButton( characters[ current ],
153  TQString(), mGroupBox );
154  connect( button, TQ_SIGNAL( clicked() ), this, TQ_SLOT( letterClicked() ) );
155  mButtons.append( button );
156  button->show();
157  current++;
158  } else {
159  int pos = ( current + offset >= (int)characters.count() ?
160  characters.count() - 1 : current + offset - 1 );
161  TQString range;
162  for ( int j = current; j < pos + 1; ++j )
163  range.append( characters[ j ] );
164  JumpButton *button = new JumpButton( characters[ current ],
165  characters[ pos ], mGroupBox );
166  connect( button, TQ_SIGNAL( clicked() ), this, TQ_SLOT( letterClicked() ) );
167  mButtons.append( button );
168  button->show();
169  current = ( i + 1 ) * offset;
170  }
171  }
172  }
173 
174  if ( currentButton != -1 )
175  mGroupBox->setButton( currentButton );
176  else
177  mGroupBox->setButton( 0 );
178 
179  int maxWidth = 0;
180  TQPushButton *button;
181  for ( button = mButtons.first(); button; button = mButtons.next() )
182  maxWidth = TQMAX( maxWidth, button->sizeHint().width() );
183 
184  setFixedWidth( maxWidth );
185 }
186 
187 void JumpButtonBar::letterClicked()
188 {
189  JumpButton *button = (JumpButton*)sender();
190  TQString character = button->firstChar();
191 
192  emit jumpToLetter( character );
193 }
194 
195 void JumpButtonBar::resizeEvent( TQResizeEvent* )
196 {
197  updateButtons();
198 }
199 
200 class SortContainer
201 {
202  public:
203  SortContainer() {}
204  SortContainer( const TQString &string )
205  : mString( string )
206  {
207  }
208 
209  bool operator< ( const SortContainer &cnt )
210  {
211  return ( TQString::localeAwareCompare( mString, cnt.mString ) < 0 );
212  }
213 
214  TQString data() const
215  {
216  return mString;
217  }
218 
219  private:
220  TQString mString;
221 };
222 
223 void JumpButtonBar::sortListLocaleAware( TQStringList &list )
224 {
225  TQValueList<SortContainer> sortList;
226 
227  TQStringList::ConstIterator it;
228  for ( it = list.begin(); it != list.end(); ++it )
229  sortList.append( SortContainer( *it ) );
230 
231  qHeapSort( sortList );
232  list.clear();
233 
234  TQValueList<SortContainer>::ConstIterator sortIt;
235  for ( sortIt = sortList.begin(); sortIt != sortList.end(); ++sortIt )
236  list.append( (*sortIt).data() );
237 }
238 
239 #include "jumpbuttonbar.moc"
void jumpToLetter(const TQString &character)
Emitted whenever a letter is selected by the user.