You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
tdepim/kaddressbook/jumpbuttonbar.cpp

240 lines
6.8 KiB

/*
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"