diff options
Diffstat (limited to 'kaddressbook/jumpbuttonbar.cpp')
-rw-r--r-- | kaddressbook/jumpbuttonbar.cpp | 239 |
1 files changed, 239 insertions, 0 deletions
diff --git a/kaddressbook/jumpbuttonbar.cpp b/kaddressbook/jumpbuttonbar.cpp new file mode 100644 index 000000000..1c8eddbad --- /dev/null +++ b/kaddressbook/jumpbuttonbar.cpp @@ -0,0 +1,239 @@ +/* + This file is part of KAddressBook. + Copyright (c) 2002 Mike Pilone <mpilone@slac.com> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + + As a special exception, permission is given to link this program + with any edition of Qt, and distribute the resulting executable, + without including the source code for Qt in the source distribution. +*/ + +#include <qapplication.h> +#include <qbuttongroup.h> +#include <qevent.h> +#include <qlayout.h> +#include <qpushbutton.h> +#include <qstring.h> +#include <qstyle.h> + +#include <kabc/addressbook.h> +#include <kabc/field.h> +#include <kdebug.h> +#include <kdialog.h> +#include <klocale.h> + +#include "core.h" + +#include "jumpbuttonbar.h" + +class JumpButton : public QPushButton +{ + public: + JumpButton( const QString &firstChar, const QString &lastChar, + QWidget *parent ); + + QString firstChar() const { return mChar; } + + private: + QString mChar; +}; + +JumpButton::JumpButton( const QString &firstChar, const QString &lastChar, + QWidget *parent ) + : QPushButton( "", parent ), mChar( firstChar ) +{ + setToggleButton( true ); + if ( !lastChar.isEmpty() ) + setText( QString( "%1 - %2" ).arg( firstChar.upper() ).arg( lastChar.upper() ) ); + else + setText( firstChar.upper() ); +} + +JumpButtonBar::JumpButtonBar( KAB::Core *core, QWidget *parent, const char *name ) + : QWidget( parent, name ), mCore( core ) +{ + setMinimumSize( 1, 1 ); + + QVBoxLayout *layout = new QVBoxLayout( this, 0, 0 ); + layout->setAlignment( Qt::AlignTop ); + layout->setAutoAdd( true ); + layout->setResizeMode( QLayout::FreeResize ); + + mGroupBox = new QButtonGroup( 1, Qt::Horizontal, this ); + mGroupBox->setExclusive( true ); + mGroupBox->layout()->setSpacing( 0 ); + mGroupBox->layout()->setMargin( 0 ); + mGroupBox->setFrameStyle( QFrame::NoFrame ); +} + +JumpButtonBar::~JumpButtonBar() +{ +} + +void JumpButtonBar::updateButtons() +{ + int currentButton = mGroupBox->selectedId(); + + // the easiest way to remove all buttons ;) + mButtons.setAutoDelete( true ); + mButtons.clear(); + mButtons.setAutoDelete( false ); + + QStringList characters; + + // calculate how many buttons are possible + QFontMetrics fm = fontMetrics(); + QPushButton *btn = new QPushButton( "", this ); + btn->hide(); + QSize buttonSize = style().sizeFromContents( QStyle::CT_PushButton, btn, + fm.size( ShowPrefix, "X - X") ). + expandedTo( QApplication::globalStrut() ); + delete btn; + + int buttonHeight = buttonSize.height() + 8; + uint possibleButtons = (height() / buttonHeight) - 1; + + QString character; + KABC::AddressBook *ab = mCore->addressBook(); + KABC::AddressBook::Iterator it; + for ( it = ab->begin(); it != ab->end(); ++it ) { + KABC::Field *field = 0; + field = mCore->currentSortField(); + if ( field ) { + setEnabled( true ); + if ( !field->value( *it ).isEmpty() ) + character = field->value( *it )[ 0 ].lower(); + } else { + setEnabled( false ); + return; + } + + if ( !character.isEmpty() && !characters.contains( character ) ) + characters.append( character ); + } + + sortListLocaleAware( characters ); + + if ( characters.count() <= possibleButtons ) { + // at first the easy case: all buttons fits in window + for ( uint i = 0; i < characters.count(); ++i ) { + JumpButton *button = new JumpButton( characters[ i ], QString::null, + mGroupBox ); + connect( button, SIGNAL( clicked() ), this, SLOT( letterClicked() ) ); + mButtons.append( button ); + button->show(); + } + } else { + if ( possibleButtons == 0 ) // to avoid crashes on startup + return; + int offset = characters.count() / possibleButtons; + int odd = characters.count() % possibleButtons; + if ( odd ) + offset++; + + int current = 0; + for ( uint i = 0; i < possibleButtons; ++i ) { + if ( characters.count() - current == 0 ) + continue; + if ( characters.count() - current <= possibleButtons - i ) { + JumpButton *button = new JumpButton( characters[ current ], + QString::null, mGroupBox ); + connect( button, SIGNAL( clicked() ), this, SLOT( letterClicked() ) ); + mButtons.append( button ); + button->show(); + current++; + } else { + int pos = ( current + offset >= (int)characters.count() ? + characters.count() - 1 : current + offset - 1 ); + QString range; + for ( int j = current; j < pos + 1; ++j ) + range.append( characters[ j ] ); + JumpButton *button = new JumpButton( characters[ current ], + characters[ pos ], mGroupBox ); + connect( button, SIGNAL( clicked() ), this, SLOT( letterClicked() ) ); + mButtons.append( button ); + button->show(); + current = ( i + 1 ) * offset; + } + } + } + + if ( currentButton != -1 ) + mGroupBox->setButton( currentButton ); + else + mGroupBox->setButton( 0 ); + + int maxWidth = 0; + QPushButton *button; + for ( button = mButtons.first(); button; button = mButtons.next() ) + maxWidth = QMAX( maxWidth, button->sizeHint().width() ); + + setFixedWidth( maxWidth ); +} + +void JumpButtonBar::letterClicked() +{ + JumpButton *button = (JumpButton*)sender(); + QString character = button->firstChar(); + + emit jumpToLetter( character ); +} + +void JumpButtonBar::resizeEvent( QResizeEvent* ) +{ + updateButtons(); +} + +class SortContainer +{ + public: + SortContainer() {} + SortContainer( const QString &string ) + : mString( string ) + { + } + + bool operator< ( const SortContainer &cnt ) + { + return ( QString::localeAwareCompare( mString, cnt.mString ) < 0 ); + } + + QString data() const + { + return mString; + } + + private: + QString mString; +}; + +void JumpButtonBar::sortListLocaleAware( QStringList &list ) +{ + QValueList<SortContainer> sortList; + + QStringList::ConstIterator it; + for ( it = list.begin(); it != list.end(); ++it ) + sortList.append( SortContainer( *it ) ); + + qHeapSort( sortList ); + list.clear(); + + QValueList<SortContainer>::ConstIterator sortIt; + for ( sortIt = sortList.begin(); sortIt != sortList.end(); ++sortIt ) + list.append( (*sortIt).data() ); +} + +#include "jumpbuttonbar.moc" |