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
42class 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
54JumpButton::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
65JumpButtonBar::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
82JumpButtonBar::~JumpButtonBar()
83{
84}
85
86void 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
187void JumpButtonBar::letterClicked()
188{
189 JumpButton *button = (JumpButton*)sender();
190 TQString character = button->firstChar();
191
192 emit jumpToLetter( character );
193}
194
195void JumpButtonBar::resizeEvent( TQResizeEvent* )
196{
197 updateButtons();
198}
199
200class 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
223void 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.