kaddressbook

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 Qt, and distribute the resulting executable,
00021     without including the source code for Qt in the source distribution.
00022 */
00023 
00024 #include <qapplication.h>
00025 #include <qbuttongroup.h>
00026 #include <qevent.h>
00027 #include <qlayout.h>
00028 #include <qpushbutton.h>
00029 #include <qstring.h>
00030 #include <qstyle.h>
00031 
00032 #include <kabc/addressbook.h>
00033 #include <kabc/field.h>
00034 #include <kdebug.h>
00035 #include <kdialog.h>
00036 #include <klocale.h>
00037 
00038 #include "core.h"
00039 
00040 #include "jumpbuttonbar.h"
00041 
00042 class JumpButton : public QPushButton
00043 {
00044   public:
00045     JumpButton( const QString &firstChar, const QString &lastChar,
00046                 QWidget *parent );
00047 
00048     QString firstChar() const { return mChar; }
00049 
00050   private:
00051     QString mChar;
00052 };
00053 
00054 JumpButton::JumpButton( const QString &firstChar, const QString &lastChar,
00055                         QWidget *parent )
00056   : QPushButton( "", parent ), mChar( firstChar )
00057 {
00058   setToggleButton( true );
00059   if ( !lastChar.isEmpty() )
00060     setText( QString( "%1 - %2" ).arg( firstChar.upper() ).arg( lastChar.upper() ) );
00061   else
00062     setText( firstChar.upper() );
00063 }
00064 
00065 JumpButtonBar::JumpButtonBar( KAB::Core *core, QWidget *parent, const char *name )
00066   : QWidget( parent, name ), mCore( core )
00067 {
00068   setMinimumSize( 1, 1 );
00069 
00070   QVBoxLayout *layout = new QVBoxLayout( this, 0, 0 );
00071   layout->setAlignment( Qt::AlignTop );
00072   layout->setAutoAdd( true );
00073   layout->setResizeMode( QLayout::FreeResize );
00074 
00075   mGroupBox = new QButtonGroup( 1, Qt::Horizontal, this );
00076   mGroupBox->setExclusive( true );
00077   mGroupBox->layout()->setSpacing( 0 );
00078   mGroupBox->layout()->setMargin( 0 );
00079   mGroupBox->setFrameStyle( QFrame::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   QStringList characters;
00096 
00097   // calculate how many buttons are possible
00098   QFontMetrics fm = fontMetrics();
00099   QPushButton *btn = new QPushButton( "", this );
00100   btn->hide();
00101   QSize buttonSize = style().sizeFromContents( QStyle::CT_PushButton, btn,
00102                      fm.size( ShowPrefix, "X - X") ).
00103                      expandedTo( QApplication::globalStrut() );
00104   delete btn;
00105 
00106   int buttonHeight = buttonSize.height() + 8;
00107   uint possibleButtons = (height() / buttonHeight) - 1;
00108 
00109   QString character;
00110   KABC::AddressBook *ab = mCore->addressBook();
00111   KABC::AddressBook::Iterator it;
00112   for ( it = ab->begin(); it != ab->end(); ++it ) {
00113     KABC::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 ], QString::null,
00134                                            mGroupBox );
00135       connect( button, SIGNAL( clicked() ), this, 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                                              QString::null, mGroupBox );
00154         connect( button, SIGNAL( clicked() ), this, 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         QString 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, SIGNAL( clicked() ), this, 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   QPushButton *button;
00181   for ( button = mButtons.first(); button; button = mButtons.next() )
00182     maxWidth = QMAX( maxWidth, button->sizeHint().width() );
00183 
00184   setFixedWidth( maxWidth );
00185 }
00186 
00187 void JumpButtonBar::letterClicked()
00188 {
00189   JumpButton *button = (JumpButton*)sender();
00190   QString character = button->firstChar();
00191 
00192   emit jumpToLetter( character );
00193 }
00194 
00195 void JumpButtonBar::resizeEvent( QResizeEvent* )
00196 {
00197   updateButtons();
00198 }
00199 
00200 class SortContainer
00201 {
00202   public:
00203     SortContainer() {}
00204     SortContainer( const QString &string )
00205       : mString( string )
00206     {
00207     }
00208 
00209     bool operator< ( const SortContainer &cnt )
00210     {
00211       return ( QString::localeAwareCompare( mString, cnt.mString ) < 0 );
00212     }
00213 
00214     QString data() const
00215     {
00216       return mString;
00217     }
00218 
00219   private:
00220     QString mString;
00221 };
00222 
00223 void JumpButtonBar::sortListLocaleAware( QStringList &list )
00224 {
00225   QValueList<SortContainer> sortList;
00226 
00227   QStringList::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   QValueList<SortContainer>::ConstIterator sortIt;
00235   for ( sortIt = sortList.begin(); sortIt != sortList.end(); ++sortIt )
00236     list.append( (*sortIt).data() );
00237 }
00238 
00239 #include "jumpbuttonbar.moc"
KDE Home | KDE Accessibility Home | Description of Access Keys