jumpbuttonbar.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 <tqbuttongroup.h> 00026 #include <tqevent.h> 00027 #include <tqlayout.h> 00028 #include <tqpushbutton.h> 00029 #include <tqstring.h> 00030 #include <tqstyle.h> 00031 00032 #include <tdeabc/addressbook.h> 00033 #include <tdeabc/field.h> 00034 #include <kdebug.h> 00035 #include <kdialog.h> 00036 #include <tdelocale.h> 00037 00038 #include "core.h" 00039 00040 #include "jumpbuttonbar.h" 00041 00042 class JumpButton : public TQPushButton 00043 { 00044 public: 00045 JumpButton( const TQString &firstChar, const TQString &lastChar, 00046 TQWidget *parent ); 00047 00048 TQString firstChar() const { return mChar; } 00049 00050 private: 00051 TQString mChar; 00052 }; 00053 00054 JumpButton::JumpButton( const TQString &firstChar, const TQString &lastChar, 00055 TQWidget *parent ) 00056 : TQPushButton( "", parent ), mChar( firstChar ) 00057 { 00058 setToggleButton( true ); 00059 if ( !lastChar.isEmpty() ) 00060 setText( TQString( "%1 - %2" ).arg( firstChar.upper() ).arg( lastChar.upper() ) ); 00061 else 00062 setText( firstChar.upper() ); 00063 } 00064 00065 JumpButtonBar::JumpButtonBar( KAB::Core *core, TQWidget *parent, const char *name ) 00066 : TQWidget( parent, name ), mCore( core ) 00067 { 00068 setMinimumSize( 1, 1 ); 00069 00070 TQVBoxLayout *layout = new TQVBoxLayout( this, 0, 0 ); 00071 layout->setAlignment( TQt::AlignTop ); 00072 layout->setAutoAdd( true ); 00073 layout->setResizeMode( TQLayout::FreeResize ); 00074 00075 mGroupBox = new TQButtonGroup( 1, Qt::Horizontal, this ); 00076 mGroupBox->setExclusive( true ); 00077 mGroupBox->layout()->setSpacing( 0 ); 00078 mGroupBox->layout()->setMargin( 0 ); 00079 mGroupBox->setFrameStyle( TQFrame::NoFrame ); 00080 } 00081 00082 JumpButtonBar::~JumpButtonBar() 00083 { 00084 } 00085 00086 void JumpButtonBar::updateButtons() 00087 { 00088 int currentButton = mGroupBox->selectedId(); 00089 00090 // the easiest way to remove all buttons ;) 00091 mButtons.setAutoDelete( true ); 00092 mButtons.clear(); 00093 mButtons.setAutoDelete( false ); 00094 00095 TQStringList characters; 00096 00097 // calculate how many buttons are possible 00098 TQFontMetrics fm = fontMetrics(); 00099 TQPushButton *btn = new TQPushButton( "", this ); 00100 btn->hide(); 00101 TQSize buttonSize = style().tqsizeFromContents( TQStyle::CT_PushButton, btn, 00102 fm.size( ShowPrefix, "X - X") ). 00103 expandedTo( TQApplication::globalStrut() ); 00104 delete btn; 00105 00106 int buttonHeight = buttonSize.height() + 8; 00107 uint possibleButtons = (height() / buttonHeight) - 1; 00108 00109 TQString character; 00110 TDEABC::AddressBook *ab = mCore->addressBook(); 00111 TDEABC::AddressBook::Iterator it; 00112 for ( it = ab->begin(); it != ab->end(); ++it ) { 00113 TDEABC::Field *field = 0; 00114 field = mCore->currentSortField(); 00115 if ( field ) { 00116 setEnabled( true ); 00117 if ( !field->value( *it ).isEmpty() ) 00118 character = field->value( *it )[ 0 ].lower(); 00119 } else { 00120 setEnabled( false ); 00121 return; 00122 } 00123 00124 if ( !character.isEmpty() && !characters.contains( character ) ) 00125 characters.append( character ); 00126 } 00127 00128 sortListLocaleAware( characters ); 00129 00130 if ( characters.count() <= possibleButtons ) { 00131 // at first the easy case: all buttons fits in window 00132 for ( uint i = 0; i < characters.count(); ++i ) { 00133 JumpButton *button = new JumpButton( characters[ i ], TQString(), 00134 mGroupBox ); 00135 connect( button, TQT_SIGNAL( clicked() ), this, TQT_SLOT( letterClicked() ) ); 00136 mButtons.append( button ); 00137 button->show(); 00138 } 00139 } else { 00140 if ( possibleButtons == 0 ) // to avoid crashes on startup 00141 return; 00142 int offset = characters.count() / possibleButtons; 00143 int odd = characters.count() % possibleButtons; 00144 if ( odd ) 00145 offset++; 00146 00147 int current = 0; 00148 for ( uint i = 0; i < possibleButtons; ++i ) { 00149 if ( characters.count() - current == 0 ) 00150 continue; 00151 if ( characters.count() - current <= possibleButtons - i ) { 00152 JumpButton *button = new JumpButton( characters[ current ], 00153 TQString(), mGroupBox ); 00154 connect( button, TQT_SIGNAL( clicked() ), this, TQT_SLOT( letterClicked() ) ); 00155 mButtons.append( button ); 00156 button->show(); 00157 current++; 00158 } else { 00159 int pos = ( current + offset >= (int)characters.count() ? 00160 characters.count() - 1 : current + offset - 1 ); 00161 TQString range; 00162 for ( int j = current; j < pos + 1; ++j ) 00163 range.append( characters[ j ] ); 00164 JumpButton *button = new JumpButton( characters[ current ], 00165 characters[ pos ], mGroupBox ); 00166 connect( button, TQT_SIGNAL( clicked() ), this, TQT_SLOT( letterClicked() ) ); 00167 mButtons.append( button ); 00168 button->show(); 00169 current = ( i + 1 ) * offset; 00170 } 00171 } 00172 } 00173 00174 if ( currentButton != -1 ) 00175 mGroupBox->setButton( currentButton ); 00176 else 00177 mGroupBox->setButton( 0 ); 00178 00179 int maxWidth = 0; 00180 TQPushButton *button; 00181 for ( button = mButtons.first(); button; button = mButtons.next() ) 00182 maxWidth = TQMAX( maxWidth, button->sizeHint().width() ); 00183 00184 setFixedWidth( maxWidth ); 00185 } 00186 00187 void JumpButtonBar::letterClicked() 00188 { 00189 JumpButton *button = (JumpButton*)sender(); 00190 TQString character = button->firstChar(); 00191 00192 emit jumpToLetter( character ); 00193 } 00194 00195 void JumpButtonBar::resizeEvent( TQResizeEvent* ) 00196 { 00197 updateButtons(); 00198 } 00199 00200 class SortContainer 00201 { 00202 public: 00203 SortContainer() {} 00204 SortContainer( const TQString &string ) 00205 : mString( string ) 00206 { 00207 } 00208 00209 bool operator< ( const SortContainer &cnt ) 00210 { 00211 return ( TQString::localeAwareCompare( mString, cnt.mString ) < 0 ); 00212 } 00213 00214 TQString data() const 00215 { 00216 return mString; 00217 } 00218 00219 private: 00220 TQString mString; 00221 }; 00222 00223 void JumpButtonBar::sortListLocaleAware( TQStringList &list ) 00224 { 00225 TQValueList<SortContainer> sortList; 00226 00227 TQStringList::ConstIterator it; 00228 for ( it = list.begin(); it != list.end(); ++it ) 00229 sortList.append( SortContainer( *it ) ); 00230 00231 qHeapSort( sortList ); 00232 list.clear(); 00233 00234 TQValueList<SortContainer>::ConstIterator sortIt; 00235 for ( sortIt = sortList.begin(); sortIt != sortList.end(); ++sortIt ) 00236 list.append( (*sortIt).data() ); 00237 } 00238 00239 #include "jumpbuttonbar.moc"