kaddressbook Library API Documentation

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., 59 Temple Place - Suite 330, Boston, MA  02111-1307, 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 <qevent.h>
00026 #include <qlayout.h>
00027 #include <qpushbutton.h>
00028 #include <qstring.h>
00029 #include <qstyle.h>
00030 
00031 #include <kabc/addressbook.h>
00032 #include <kabc/field.h>
00033 #include <kdebug.h>
00034 #include <kdialog.h>
00035 #include <klocale.h>
00036 
00037 #include "core.h"
00038 
00039 #include "jumpbuttonbar.h"
00040 
00041 class JumpButton : public QPushButton
00042 {
00043   public:
00044     JumpButton( const QString &firstChar, const QString &lastChar,
00045                 QWidget *parent );
00046 
00047     QString firstCharacter() const;
00048     QString lastCharacter() const;
00049 
00050   private:
00051     QString mFirstCharacter;
00052     QString mLastCharacter;
00053 };
00054 
00055 JumpButton::JumpButton( const QString &firstChar, const QString &lastChar,
00056                         QWidget *parent )
00057   : QPushButton( "", parent ), mFirstCharacter( firstChar ),
00058     mLastCharacter( lastChar )
00059 {
00060   if ( !lastChar.isEmpty() )
00061     setText( QString( "%1 - %2" ).arg( firstChar.upper() ).arg( lastChar.upper() ) );
00062   else
00063     setText( firstChar.upper() );
00064 }
00065 
00066 QString JumpButton::firstCharacter() const
00067 {
00068   return mFirstCharacter;
00069 }
00070 
00071 QString JumpButton::lastCharacter() const
00072 {
00073   return mLastCharacter;
00074 }
00075 
00076 JumpButtonBar::JumpButtonBar( KAB::Core *core, QWidget *parent, const char *name )
00077   : QWidget( parent, name ), mCore( core )
00078 {
00079   setMinimumSize( 1, 1 );
00080 
00081   QVBoxLayout *layout = new QVBoxLayout( this, KDialog::marginHint(), 0 );
00082   layout->setAlignment( Qt::AlignTop );
00083   layout->setAutoAdd( true );
00084   layout->setResizeMode( QLayout::FreeResize );
00085 }
00086 
00087 JumpButtonBar::~JumpButtonBar()
00088 {
00089 }
00090 
00091 QSizePolicy JumpButtonBar::sizePolicy() const
00092 {
00093     return QSizePolicy( QSizePolicy::Maximum, QSizePolicy::Minimum,
00094                       QSizePolicy::Vertically );
00095 }
00096 
00097 void JumpButtonBar::updateButtons()
00098 {
00099   // the easiest way to remove all buttons ;)
00100   mButtons.setAutoDelete( true );
00101   mButtons.clear();
00102   mButtons.setAutoDelete( false );
00103 
00104   QStringList characters;
00105 
00106   // calculate how many buttons are possible
00107   QFontMetrics fm = fontMetrics();
00108   QPushButton *btn = new QPushButton( "", this );
00109   btn->hide();
00110   QSize buttonSize = style().sizeFromContents( QStyle::CT_PushButton, btn,
00111                      fm.size( ShowPrefix, "X - X") ).
00112                      expandedTo( QApplication::globalStrut() );
00113   delete btn;
00114 
00115   uint possibleButtons = height() / buttonSize.height();
00116 
00117   QString character;
00118   KABC::AddressBook *ab = mCore->addressBook();
00119   KABC::AddressBook::Iterator it;
00120   for ( it = ab->begin(); it != ab->end(); ++it ) {
00121     KABC::Field *field = 0;
00122     field = mCore->currentSortField();
00123     if ( field ) {
00124       setEnabled( true );
00125       if ( !field->value( *it ).isEmpty() )
00126         character = field->value( *it )[ 0 ].lower();
00127     } else {
00128       setEnabled( false );
00129       return;
00130     }
00131 
00132     if ( !character.isEmpty() && !characters.contains( character ) )
00133       characters.append( character );
00134   }
00135 
00136   sortListLocaleAware( characters );
00137 
00138   bool state = isUpdatesEnabled();
00139   setUpdatesEnabled( false );
00140 
00141   if ( characters.count() <= possibleButtons ) {
00142     // at first the easy case: all buttons fits in window
00143     for ( uint i = 0; i < characters.count(); ++i ) {
00144       JumpButton *button = new JumpButton( characters[ i ], QString::null, this );
00145       connect( button, SIGNAL( clicked() ), this, SLOT( letterClicked() ) );
00146       mButtons.append( button );
00147       button->show();
00148     }
00149   } else {
00150     if ( possibleButtons == 0 ) // to avoid crashes on startup
00151       return;
00152     int offset = characters.count() / possibleButtons;
00153     int odd = characters.count() % possibleButtons;
00154     if ( odd )
00155       offset++;
00156 
00157     int current = 0;
00158     for ( uint i = 0; i < possibleButtons; ++i ) {
00159       if ( characters.count() - current == 0 )
00160         continue;
00161       if ( characters.count() - current <= possibleButtons - i ) {
00162         JumpButton *button = new JumpButton( characters[ current ],
00163                                  QString::null, this );
00164         connect( button, SIGNAL( clicked() ), this, SLOT( letterClicked() ) );
00165         mButtons.append( button );
00166         button->show();
00167         current++;      
00168       } else {
00169         int pos = ( current + offset >= (int)characters.count() ?
00170                     characters.count() - 1 : current + offset - 1 );
00171         JumpButton *button = new JumpButton( characters[ current ],
00172                                  characters[ pos ], this );
00173         connect( button, SIGNAL( clicked() ), this, SLOT( letterClicked() ) );
00174         mButtons.append( button );
00175         button->show();
00176         current = ( i + 1 ) * offset;
00177       }
00178     }
00179   }
00180 
00181   setUpdatesEnabled( state );
00182   update();
00183 }
00184 
00185 void JumpButtonBar::letterClicked()
00186 {
00187   JumpButton *button = (JumpButton*)sender();
00188   QString character = button->firstCharacter();
00189   if ( !character.isEmpty() )
00190     emit jumpToLetter( character );
00191 }
00192 
00193 void JumpButtonBar::resizeEvent( QResizeEvent* )
00194 {
00195   updateButtons();
00196 }
00197 
00198 class SortContainer
00199 {
00200   public:
00201     SortContainer() {}
00202     SortContainer( const QString &string )
00203       : mString( string )
00204     {
00205     }
00206 
00207     bool operator< ( const SortContainer &cnt )
00208     {
00209       return ( QString::localeAwareCompare( mString, cnt.mString ) < 0 );
00210     }
00211 
00212     QString data() const
00213     {
00214       return mString;
00215   }
00216 
00217   private:
00218     QString mString;
00219 };
00220 
00221 void JumpButtonBar::sortListLocaleAware( QStringList &list )
00222 {
00223   QValueList<SortContainer> sortList;
00224 
00225   QStringList::ConstIterator it;
00226   for ( it = list.begin(); it != list.end(); ++it )
00227     sortList.append( SortContainer( *it ) );
00228 
00229   qHeapSort( sortList );
00230   list.clear();
00231 
00232   QValueList<SortContainer>::Iterator sortIt;
00233   for ( sortIt = sortList.begin(); sortIt != sortList.end(); ++sortIt )
00234     list.append( (*sortIt).data() );
00235 }
00236 
00237 #include "jumpbuttonbar.moc"
KDE Logo
This file is part of the documentation for kaddressbook Library Version 3.2.2.
Documentation copyright © 1996-2004 the KDE developers.
Generated on Sat May 1 11:38:51 2004 by doxygen 1.2.15 written by Dimitri van Heesch, © 1997-2003