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.
koffice/koshell/iconsidepane.cpp

596 lines
17 KiB

/*
This file is part of KDE KOffice project.
Copyright (C) 2003 Cornelius Schumacher <schumacher@kde.org>
Copyright (C) 2005 Fredrik Edemar <f_edemar@linux.se>
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; see the file COPYING. If not, write to
the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301, USA.
*/
#include <tqbitmap.h>
#include <tqcursor.h>
#include <tqdrawutil.h>
#include <tqfontmetrics.h>
#include <tqframe.h>
#include <tqlabel.h>
#include <tqobjectlist.h>
#include <tqpainter.h>
#include <tqptrlist.h>
#include <tqstyle.h>
#include <tqtooltip.h>
#include <tqwidgetstack.h>
#include <kapplication.h>
#include <kdebug.h>
#include <kdialog.h>
#include <kiconloader.h>
#include <klocale.h>
#include <kpopupmenu.h>
#include <kpushbutton.h>
#include "iconsidepane.h"
EntryItem::EntryItem( Navigator *parent, int _id, const TQString &_text, const TQString & _pix )
: TQListBoxItem( parent ),
mPixmapName(_pix),
mId(_id),
mHasHover( false ),
mPaintActive( false )
{
reloadPixmap();
setCustomHighlighting( true );
setText( _text );
}
EntryItem::~EntryItem()
{
}
void EntryItem::setNewText(const TQString &_text)
{
setText( _text );
}
void EntryItem::reloadPixmap()
{
int size = (int)navigator()->viewMode();
if ( size != 0 )
mPixmap = TDEGlobal::iconLoader()->loadIcon( mPixmapName, KIcon::Desktop, size );
else
mPixmap = TQPixmap();
}
Navigator* EntryItem::navigator() const
{
return static_cast<Navigator*>( listBox() );
}
int EntryItem::width( const TQListBox *listbox ) const
{
int w = 0;
if( navigator()->showIcons() ) {
w = navigator()->viewMode();
if ( navigator()->viewMode() == SmallIcons )
w += 4;
}
if( navigator()->showText() ) {
if ( navigator()->viewMode() == SmallIcons )
w += listbox->fontMetrics().width( text() );
else
w = TQMAX( w, listbox->fontMetrics().width( text() ) );
}
return w + ( KDialog::marginHint() * 2 );
}
int EntryItem::height( const TQListBox *listbox ) const
{
int h = 0;
if ( navigator()->showIcons() )
h = (int)navigator()->viewMode() + 4;
if ( navigator()->showText() ) {
if ( navigator()->viewMode() == SmallIcons || !navigator()->showIcons() )
h = TQMAX( h, listbox->fontMetrics().lineSpacing() ) + KDialog::spacingHint() * 2;
else
h = (int)navigator()->viewMode() + listbox->fontMetrics().lineSpacing() + 4;
}
return h;
}
void EntryItem::paint( TQPainter *p )
{
reloadPixmap();
TQListBox *box = listBox();
bool iconAboveText = ( navigator()->viewMode() > SmallIcons )
&& navigator()->showIcons();
int w = box->viewport()->width();
int y = 2;
// draw selected
if ( isCurrent() || isSelected() || mHasHover || mPaintActive ) {
int h = height( box );
TQBrush brush;
if ( isCurrent() || isSelected() || mPaintActive )
brush = box->colorGroup().brush( TQColorGroup::Highlight );
else
brush = TQBrush(box->colorGroup().highlight().light( 115 ));
p->fillRect( 1, 0, w - 2, h - 1, brush );
TQPen pen = p->pen();
TQPen oldPen = pen;
pen.setColor( box->colorGroup().mid() );
p->setPen( pen );
p->drawPoint( 1, 0 );
p->drawPoint( 1, h - 2 );
p->drawPoint( w - 2, 0 );
p->drawPoint( w - 2, h - 2 );
p->setPen( oldPen );
}
if ( !mPixmap.isNull() && navigator()->showIcons() ) {
int x = iconAboveText ? ( ( w - mPixmap.width() ) / 2 ) :
KDialog::marginHint();
p->drawPixmap( x, y, mPixmap );
}
TQColor shadowColor = listBox()->colorGroup().background().dark(115);
if ( isCurrent() || isSelected() ) {
p->setPen( box->colorGroup().highlightedText() );
}
if ( !text().isEmpty() && navigator()->showText() ) {
TQFontMetrics fm = p->fontMetrics();
int x = 0;
if ( iconAboveText ) {
x = ( w - fm.width( text() ) ) / 2;
y += fm.height() - fm.descent();
if ( navigator()->showIcons() )
y += mPixmap.height();
} else {
x = KDialog::marginHint() + 4;
if( navigator()->showIcons() ) {
x += mPixmap.width();
}
if ( !navigator()->showIcons() || mPixmap.height() < fm.height() )
y += fm.ascent() + fm.leading()/2;
else
y += mPixmap.height()/2 - fm.height()/2 + fm.ascent();
}
if ( isCurrent() || isSelected() || mHasHover ) {
p->setPen( box->colorGroup().highlight().dark(115) );
p->drawText( x + ( TQApplication::reverseLayout() ? -1 : 1),
y + 1, text() );
p->setPen( box->colorGroup().highlightedText() );
}
else
p->setPen( box->colorGroup().text() );
p->drawText( x, y, text() );
}
// ensure that we don't have a stale flag around
if ( isCurrent() || isSelected() ) mHasHover = false;
}
void EntryItem::setHover( bool hasHover )
{
mHasHover = hasHover;
}
void EntryItem::setPaintActive( bool paintActive )
{
mPaintActive = paintActive;
}
// ************************************************
Navigator::Navigator(bool _selectable, KPopupMenu * menu, IconSidePane *_iconsidepane, TQWidget *parent, const char *name )
: KListBox( parent, name ), mSidePane( _iconsidepane ), mPopupMenu( menu )
{
setSelectionMode( KListBox::Single );
viewport()->setBackgroundMode( PaletteBackground );
setFrameStyle( TQFrame::NoFrame );
setHScrollBarMode( TQScrollView::AlwaysOff );
//setAcceptDrops( true );
mMinWidth = 0;
mSelectable = _selectable;
executedItem = 0;
mMouseOn = 0;
setFocusPolicy( TQ_NoFocus );
connect( this, TQT_SIGNAL( clicked( TQListBoxItem* ) ),
TQT_SLOT( slotExecuted( TQListBoxItem* ) ) );
connect( this, TQT_SIGNAL( onItem( TQListBoxItem * ) ),
TQT_SLOT( slotMouseOn( TQListBoxItem * ) ) );
connect( this, TQT_SIGNAL( onViewport() ), TQT_SLOT( slotMouseOff() ) );
TQToolTip::remove( this );
if ( !mSidePane->showText() )
new EntryItemToolTip( this );
}
IconViewMode Navigator::viewMode()
{
return mSidePane->viewMode();
}
bool Navigator::showText()
{
return mSidePane->showText();
}
bool Navigator::showIcons()
{
return mSidePane->showIcons();
}
void Navigator::mouseReleaseEvent(TQMouseEvent *e)
{
KListBox::mouseReleaseEvent(e);
if ( e->button() != Qt::LeftButton || !mLeftMouseButtonPressed )
return;
if ( itemAt( e->pos() ) && executedItem == selectedItem() )
emit itemSelected( currentItem() );
if ( !mSelectable )
clearSelection();
}
void Navigator::mousePressEvent(TQMouseEvent *e)
{
if ( e->button() != Qt::LeftButton || itemAt( e->pos() ) == 0 )
{
mLeftMouseButtonPressed = false;
if (e->button() == Qt::RightButton)
slotShowRMBMenu( 0,mapToGlobal( e->pos() ) );
return;
}
else
mLeftMouseButtonPressed = true;
KListBox::mousePressEvent(e);
}
void Navigator::enterEvent( TQEvent *event )
{
// work around TQt behaviour: onItem is not emmitted in enterEvent()
KListBox::enterEvent( event );
emit onItem( itemAt( mapFromGlobal( TQCursor::pos() ) ) );
}
void Navigator::slotExecuted( TQListBoxItem *item )
{
if ( !item )
return;
executedItem = item;
}
TQSize Navigator::sizeHint() const
{
return TQSize( mMinWidth, 100 );
}
void Navigator::calculateMinWidth()
{
mMinWidth = mSidePane->minWidth();
for (EntryItem *item = static_cast<EntryItem *>(firstItem()) ; item; item = static_cast<EntryItem *>(item->next()))
{
if (item->width( this ) > mMinWidth)
mMinWidth = item->width( this );
}
//kdDebug() << "minWidth:" << mMinWidth << endl;
parentWidget()->setFixedWidth( mMinWidth );
triggerUpdate(true);
}
int Navigator::insertItem(const TQString &_text, const TQString & _pix)
{
EntryItem *item = new EntryItem( this, count(), _text, _pix );
if (item->width( this ) > mSidePane->minWidth() )
{
mMinWidth = item->width( this );
parentWidget()->setMinimumWidth( mMinWidth );
//kdDebug() << "minWidth:" << mMinWidth << endl;
}
return item->id();
}
void Navigator::setHoverItem( TQListBoxItem* item, bool hover )
{
static_cast<EntryItem*>( item )->setHover( hover );
updateItem( item );
}
void Navigator::setPaintActiveItem( TQListBoxItem* item, bool paintActive )
{
static_cast<EntryItem*>( item )->setPaintActive( paintActive );
updateItem( item );
}
void Navigator::slotMouseOn( TQListBoxItem* newItem )
{
TQListBoxItem* oldItem = mMouseOn;
if ( oldItem == newItem )
return;
if ( oldItem && !oldItem->isCurrent() && !oldItem->isSelected() )
setHoverItem( oldItem, false );
if ( newItem && !newItem->isCurrent() && !newItem->isSelected() )
setHoverItem( newItem, true );
mMouseOn = newItem;
}
void Navigator::slotMouseOff()
{
slotMouseOn( 0 );
}
void Navigator::resizeEvent( TQResizeEvent *event )
{
TQListBox::resizeEvent( event );
triggerUpdate( true );
}
void Navigator::slotShowRMBMenu( TQListBoxItem *, const TQPoint &pos )
{
int choice = mPopupMenu->exec( pos );
if ( choice == -1 )
return;
mSidePane->resetWidth();
if ( choice >= SmallIcons ) {
mSidePane->setViewMode( mSidePane->sizeIntToEnum( choice ) );
mPopupMenu->setItemChecked( (int)SmallIcons, false);
mPopupMenu->setItemChecked( (int)NormalIcons, false);
mPopupMenu->setItemChecked( (int)LargeIcons, false);
mPopupMenu->setItemChecked( mSidePane->viewMode(), true);
KoShellSettings::setSidePaneIconSize( choice );
}
else
{
// either icons or text were toggled
if ( choice == ShowIcons ) {
mSidePane->toogleIcons();
mPopupMenu->setItemChecked( (int)ShowIcons, mSidePane->showIcons() );
mPopupMenu->setItemEnabled( (int)ShowText, mSidePane->showIcons() );
mPopupMenu->setItemEnabled( (int)SmallIcons, mSidePane->showIcons());
mPopupMenu->setItemEnabled( (int)NormalIcons, mSidePane->showIcons());
mPopupMenu->setItemEnabled( (int)LargeIcons, mSidePane->showIcons());
KoShellSettings::setSidePaneShowIcons( mSidePane->showIcons() );
TQToolTip::remove( this );
} else {
mSidePane->toogleText();
mSidePane->resetWidth();
mPopupMenu->setItemChecked( (int)ShowText, mSidePane->showText() );
mPopupMenu->setItemEnabled( (int)ShowIcons, mSidePane->showText() );
mPopupMenu->setItemEnabled( (int)SmallIcons, true);
mPopupMenu->setItemEnabled( (int)NormalIcons, true);
mPopupMenu->setItemEnabled( (int)LargeIcons, true);
KoShellSettings::setSidePaneShowText( mSidePane->showText() );
new EntryItemToolTip( this );
// if ( !mSidePane->showText() )
// mSidePane->buttonGroup()->hide();
// else
// mSidePane->buttonGroup()->show();
}
}
calculateMinWidth();
emit updateAllWidgets();
}
// ************************************************
IconSidePane::IconSidePane(TQWidget *parent, const char *name )
: TQVBox( parent, name )
{
m_buttongroup = new TQButtonGroup(1, Qt::Horizontal, this);
m_buttongroup->setExclusive(true);
m_buttongroup->hide();
mWidgetstack = new TQWidgetStack(this);
mWidgetstack->setSizePolicy(TQSizePolicy(TQSizePolicy::Expanding, TQSizePolicy::Expanding));
// setup the popup menu
mShowIcons = KoShellSettings::sidePaneShowIcons();
mShowText = KoShellSettings::sidePaneShowText();
mViewMode = sizeIntToEnum( KoShellSettings::sidePaneIconSize() );
mPopupMenu = new KPopupMenu(0);
mPopupMenu->insertTitle( i18n( "Icon Size" ) );
mPopupMenu->insertItem( i18n( "Large" ), (int)LargeIcons );
mPopupMenu->setItemEnabled( (int)LargeIcons, mShowIcons );
mPopupMenu->insertItem( i18n( "Normal" ), (int)NormalIcons );
mPopupMenu->setItemEnabled( (int)NormalIcons, mShowIcons );
mPopupMenu->insertItem( i18n( "Small" ), (int)SmallIcons );
mPopupMenu->setItemEnabled( (int)SmallIcons, mShowIcons );
mPopupMenu->setItemChecked( (int)mViewMode, true );
mPopupMenu->insertSeparator();
mPopupMenu->insertItem( i18n( "Show Icons" ), (int)ShowIcons );
mPopupMenu->setItemChecked( (int)ShowIcons, mShowIcons );
mPopupMenu->setItemEnabled( (int)ShowIcons, mShowText );
mPopupMenu->insertItem( i18n( "Show Text" ), (int)ShowText );
mPopupMenu->setItemChecked( (int)ShowText, mShowText );
mPopupMenu->setItemEnabled( (int)ShowText, mShowIcons );
if ( !mShowText )
m_buttongroup->hide();
}
IconSidePane::~IconSidePane()
{
}
int IconSidePane::insertItem(int _grp, const TQString & _pix, const TQString &_text)
{
return static_cast<Navigator*>( mWidgetstack->widget(_grp))->insertItem( _text, _pix );
}
int IconSidePane::insertItem(const TQString & _pix, const TQString &_text)
{
return mCurrentNavigator->insertItem(_text, _pix);
}
void IconSidePane::renameItem( int _grp, int _id, const TQString & _text )
{
Navigator *navigator = static_cast<Navigator*>(mWidgetstack->widget(_grp));
if (!navigator)
return;
EntryItem *item = 0;
for (uint i=0; i< navigator->count(); i++)
{
item = static_cast<EntryItem *>(navigator->item(i));
if (_id == item->id())
{
item->setNewText(_text);
navigator->triggerUpdate(false);
break;
}
}
}
void IconSidePane::removeItem( int _grp, int _id )
{
Navigator *navigator = static_cast<Navigator*>(mWidgetstack->widget(_grp));
if (!navigator)
return;
for (uint i=0; i< navigator->count(); i++)
{
if (_id == static_cast<EntryItem *>(navigator->item(i))->id())
{
navigator->removeItem(i);
break;
}
}
}
int IconSidePane::insertGroup(const TQString &_text, bool _selectable, TQObject *_obj, const char *_slot)
{
mCurrentNavigator = new Navigator(_selectable, mPopupMenu, this, mWidgetstack );
//connect( mCurrentNavigator, TQT_SIGNAL( itemSelected( int ) ), this, TQT_SLOT( itemSelected( int ) ) );
if ( _obj != 0L && _slot != 0L )
connect( mCurrentNavigator, TQT_SIGNAL( itemSelected(int ) ), _obj, _slot );
connect( mCurrentNavigator, TQT_SIGNAL( updateAllWidgets() ), this, TQT_SLOT(updateAllWidgets()) );
int const id = mWidgetstack->addWidget(mCurrentNavigator);
mWidgetStackIds.append( id );
KPushButton *b = new KPushButton( _text, m_buttongroup );
m_buttongroup->insert( b, id );
connect( b, TQT_SIGNAL( clicked() ), this, TQT_SLOT( buttonClicked() ) );
b->setToggleButton( true );
b->setFocusPolicy( TQ_NoFocus );
if (m_buttongroup->count()==1)
{
mCurrentNavigator->calculateMinWidth();
m_buttongroup->setButton(m_buttongroup->id(b));
mWidgetstack->raiseWidget(id);
}
if ( b->width() > minimumWidth() )
setMinimumWidth( b->width() );
return id;
}
void IconSidePane::buttonClicked()
{
mWidgetstack->raiseWidget( m_buttongroup->selectedId() );
}
void IconSidePane::selectGroup(int group_id)
{
mWidgetstack->raiseWidget(group_id);
}
void IconSidePane::itemSelected(int item)
{
kdDebug() << "Item selected:" << item << endl;
}
Navigator * IconSidePane::group(int _grp)
{
return static_cast<Navigator*>(mWidgetstack->widget(_grp));
}
void IconSidePane::updateAllWidgets()
{
TQValueList<int>::iterator it;
for ( it = mWidgetStackIds.begin(); it != mWidgetStackIds.end(); ++it )
static_cast<Navigator*>(mWidgetstack->widget(*it))->triggerUpdate( true );
}
int IconSidePane::minWidth()
{
int width = 0;
TQValueList<int>::iterator it;
Navigator *n;
for ( it = mWidgetStackIds.begin(); it != mWidgetStackIds.end(); ++it )
{
n = static_cast<Navigator*>(mWidgetstack->widget(*it));
if ( n->minWidth() > width )
width = n->minWidth();
}
return width;
}
void IconSidePane::resetWidth()
{
TQValueList<int>::iterator it;
Navigator *n;
for ( it = mWidgetStackIds.begin(); it != mWidgetStackIds.end(); ++it )
{
n = static_cast<Navigator*>(mWidgetstack->widget(*it));
n->resetWidth();
n->triggerUpdate(true);
}
}
IconViewMode IconSidePane::sizeIntToEnum(int size) const
{
switch ( size ) {
case int(LargeIcons):
return LargeIcons;
break;
case int(NormalIcons):
return NormalIcons;
break;
case int(SmallIcons):
return SmallIcons;
break;
default:
// Stick with sane values
return NormalIcons;
kdDebug() << "View mode not implemented!" << endl;
break;
}
}
void IconSidePane::setActionCollection( KActionCollection *actionCollection )
{
mActionCollection = actionCollection;
}
KActionCollection *IconSidePane::actionCollection() const
{
return mActionCollection;
}
#include "iconsidepane.moc"
// vim: sw=2 sts=2 et tw=80