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/kontact/src/iconsidepane.cpp

604 lines
15 KiB

/*
This file is part of KDE Kontact.
Copyright (C) 2003 Cornelius Schumacher <schumacher@kde.org>
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 <tqptrlist.h>
#include <tqwidgetstack.h>
#include <tqsignal.h>
#include <tqobjectlist.h>
#include <tqlabel.h>
#include <tqimage.h>
#include <tqpainter.h>
#include <tqbitmap.h>
#include <tqfontmetrics.h>
#include <tqsignalmapper.h>
#include <tqstyle.h>
#include <tqframe.h>
#include <tqdrawutil.h>
#include <tqcursor.h>
#include <tqtimer.h>
#include <tqtooltip.h>
#include <tdepopupmenu.h>
#include <kapplication.h>
#include <kdialog.h>
#include <klocale.h>
#include <kiconloader.h>
#include <sidebarextension.h>
#include <kdebug.h>
#include "mainwindow.h"
#include "plugin.h"
#include "prefs.h"
#include "iconsidepane.h"
namespace Kontact
{
//ugly wrapper class for adding an operator< to the Plugin class
class PluginProxy
{
public:
PluginProxy()
: mPlugin( 0 )
{ }
PluginProxy( Plugin *plugin )
: mPlugin( plugin )
{ }
PluginProxy & operator=( Plugin *plugin )
{
mPlugin = plugin;
return *this;
}
bool operator<( PluginProxy &rhs ) const
{
return mPlugin->weight() < rhs.mPlugin->weight();
}
Plugin *plugin() const
{
return mPlugin;
}
private:
Plugin *mPlugin;
};
} //namespace
using namespace Kontact;
EntryItem::EntryItem( Navigator *parent, Kontact::Plugin *plugin )
: TQListBoxItem( parent ),
mPlugin( plugin ),
mHasHover( false ),
mPaintActive( false )
{
reloadPixmap();
setCustomHighlighting( true );
setText( plugin->title() );
}
EntryItem::~EntryItem()
{
}
void EntryItem::reloadPixmap()
{
int size = (int)navigator()->viewMode();
if ( size != 0 )
mPixmap = TDEGlobal::iconLoader()->loadIcon( mPlugin->icon(),
KIcon::Desktop, size,
mPlugin->disabled() ?
KIcon::DisabledState
: KIcon::DefaultState);
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 = iconAboveText ? 2 :
( ( height( box ) - mPixmap.height() ) / 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 = height( box )/2 - fm.height()/2 + fm.ascent();
else
y += mPixmap.height()/2 - fm.height()/2 + fm.ascent();
}
if ( plugin()->disabled() ) {
p->setPen( box->palette().disabled().text( ) );
} else 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( IconSidePane *parent, const char *name )
: TDEListBox( parent, name ), mSidePane( parent ),
mShowIcons( true ), mShowText( true )
{
mMouseOn = 0;
mHighlightItem = 0;
mViewMode = sizeIntToEnum( Prefs::self()->sidePaneIconSize() );
mShowIcons = Prefs::self()->sidePaneShowIcons();
mShowText = Prefs::self()->sidePaneShowText();
setSelectionMode( TDEListBox::Single );
viewport()->setBackgroundMode( PaletteBackground );
setFrameStyle( TQFrame::NoFrame );
setHScrollBarMode( TQScrollView::AlwaysOff );
setAcceptDrops( true );
setFocusPolicy( TQ_NoFocus );
connect( this, TQT_SIGNAL( selectionChanged( TQListBoxItem* ) ),
TQT_SLOT( slotExecuted( TQListBoxItem* ) ) );
connect( this, TQT_SIGNAL( rightButtonPressed( TQListBoxItem*, const TQPoint& ) ),
TQT_SLOT( slotShowRMBMenu( TQListBoxItem*, const TQPoint& ) ) );
connect( this, TQT_SIGNAL( onItem( TQListBoxItem * ) ),
TQT_SLOT( slotMouseOn( TQListBoxItem * ) ) );
connect( this, TQT_SIGNAL( onViewport() ), TQT_SLOT( slotMouseOff() ) );
mMapper = new TQSignalMapper( TQT_TQOBJECT(this) );
connect( mMapper, TQT_SIGNAL( mapped( int ) ), TQT_SLOT( shortCutSelected( int ) ) );
TQToolTip::remove( this );
if ( !mShowText )
new EntryItemToolTip( this );
}
TQSize Navigator::sizeHint() const
{
return TQSize( 100, 100 );
}
void Navigator::highlightItem( EntryItem * item )
{
mHighlightItem = item;
setPaintActiveItem( mHighlightItem, true );
TQTimer::singleShot( 2000, this, TQT_SLOT( slotStopHighlight() ) );
}
void Navigator::slotStopHighlight()
{
setPaintActiveItem( mHighlightItem, false );
}
void Navigator::setSelected( TQListBoxItem *item, bool selected )
{
// Reimplemented to avoid the immediate activation of
// the item. might turn out it doesn't work, we check that
// an confirm from MainWindow::selectPlugin()
if ( selected ) {
EntryItem *entry = static_cast<EntryItem*>( item );
emit pluginActivated( entry->plugin() );
}
}
void Navigator::updatePlugins( TQValueList<Kontact::Plugin*> plugins_ )
{
TQValueList<Kontact::PluginProxy> plugins;
TQValueList<Kontact::Plugin*>::ConstIterator end_ = plugins_.end();
TQValueList<Kontact::Plugin*>::ConstIterator it_ = plugins_.begin();
for ( ; it_ != end_; ++it_ )
plugins += PluginProxy( *it_ );
clear();
mActions.setAutoDelete( true );
mActions.clear();
mActions.setAutoDelete( false );
int minWidth = 0;
qBubbleSort( plugins );
TQValueList<Kontact::PluginProxy>::ConstIterator end = plugins.end();
TQValueList<Kontact::PluginProxy>::ConstIterator it = plugins.begin();
for ( ; it != end; ++it ) {
Kontact::Plugin *plugin = ( *it ).plugin();
if ( !plugin->showInSideBar() )
continue;
EntryItem *item = new EntryItem( this, plugin );
item->setSelectable( !plugin->disabled() );
if ( item->width( this ) > minWidth )
minWidth = item->width( this );
}
parentWidget()->setFixedWidth( minWidth );
}
void Navigator::dragEnterEvent( TQDragEnterEvent *event )
{
kdDebug(5600) << "Navigator::dragEnterEvent()" << endl;
dragMoveEvent( event );
}
void Navigator::dragMoveEvent( TQDragMoveEvent *event )
{
kdDebug(5600) << "Navigator::dragEnterEvent()" << endl;
kdDebug(5600) << " Format: " << event->format() << endl;
TQListBoxItem *item = itemAt( event->pos() );
if ( !item ) {
event->accept( false );
return;
}
EntryItem *entry = static_cast<EntryItem*>( item );
kdDebug(5600) << " PLUGIN: " << entry->plugin()->identifier() << endl;
event->accept( entry->plugin()->canDecodeDrag( event ) );
}
void Navigator::dropEvent( TQDropEvent *event )
{
kdDebug(5600) << "Navigator::dropEvent()" << endl;
TQListBoxItem *item = itemAt( event->pos() );
if ( !item ) {
return;
}
EntryItem *entry = static_cast<EntryItem*>( item );
kdDebug(5600) << " PLUGIN: " << entry->plugin()->identifier() << endl;
entry->plugin()->processDropEvent( event );
}
void Navigator::resizeEvent( TQResizeEvent *event )
{
TQListBox::resizeEvent( event );
triggerUpdate( true );
}
void Navigator::enterEvent( TQEvent *event )
{
// work around TQt behaviour: onItem is not emmitted in enterEvent()
TDEListBox::enterEvent( event );
emit onItem( itemAt( mapFromGlobal( TQCursor::pos() ) ) );
}
void Navigator::leaveEvent( TQEvent *event )
{
TDEListBox::leaveEvent( event );
slotMouseOn( 0 );
mMouseOn = 0;
}
void Navigator::slotExecuted( TQListBoxItem *item )
{
if ( !item )
return;
EntryItem *entry = static_cast<EntryItem*>( item );
emit pluginActivated( entry->plugin() );
}
IconViewMode Navigator::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 Navigator::slotShowRMBMenu( TQListBoxItem *, const TQPoint &pos )
{
TDEPopupMenu menu;
menu.insertTitle( i18n( "Icon Size" ) );
menu.insertItem( i18n( "Large" ), (int)LargeIcons );
menu.setItemEnabled( (int)LargeIcons, mShowIcons );
menu.insertItem( i18n( "Normal" ), (int)NormalIcons );
menu.setItemEnabled( (int)NormalIcons, mShowIcons );
menu.insertItem( i18n( "Small" ), (int)SmallIcons );
menu.setItemEnabled( (int)SmallIcons, mShowIcons );
menu.setItemChecked( (int)mViewMode, true );
menu.insertSeparator();
menu.insertItem( i18n( "Show Icons" ), (int)ShowIcons );
menu.setItemChecked( (int)ShowIcons, mShowIcons );
menu.setItemEnabled( (int)ShowIcons, mShowText );
menu.insertItem( i18n( "Show Text" ), (int)ShowText );
menu.setItemChecked( (int)ShowText, mShowText );
menu.setItemEnabled( (int)ShowText, mShowIcons );
int choice = menu.exec( pos );
if ( choice == -1 )
return;
if ( choice >= SmallIcons ) {
mViewMode = sizeIntToEnum( choice );
Prefs::self()->setSidePaneIconSize( choice );
} else {
// either icons or text were toggled
if ( choice == ShowIcons ) {
mShowIcons = !mShowIcons;
Prefs::self()->setSidePaneShowIcons( mShowIcons );
TQToolTip::remove( this );
if ( !mShowText )
new EntryItemToolTip( this );
} else {
mShowText = !mShowText;
Prefs::self()->setSidePaneShowText( mShowText );
TQToolTip::remove( this );
}
}
int maxWidth = 0;
TQListBoxItem* it = 0;
for (int i = 0; (it = item(i)) != 0; ++i)
{
int width = it->width(this);
if (width > maxWidth)
maxWidth = width;
}
parentWidget()->setFixedWidth( maxWidth );
triggerUpdate( true );
}
void Navigator::shortCutSelected( int pos )
{
setCurrentItem( pos );
}
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 );
}
IconSidePane::IconSidePane( Core *core, TQWidget *parent, const char *name )
: SidePaneBase( core, parent, name )
{
mNavigator = new Navigator( this );
connect( mNavigator, TQT_SIGNAL( pluginActivated( Kontact::Plugin* ) ),
TQT_SIGNAL( pluginSelected( Kontact::Plugin* ) ) );
setAcceptDrops( true );
}
IconSidePane::~IconSidePane()
{
}
void IconSidePane::updatePlugins()
{
mNavigator->updatePlugins( core()->pluginList() );
}
void IconSidePane::selectPlugin( Kontact::Plugin *plugin )
{
bool blocked = signalsBlocked();
blockSignals( true );
for ( uint i = 0; i < mNavigator->count(); ++i ) {
EntryItem *item = static_cast<EntryItem*>( mNavigator->item( i ) );
if ( item->plugin() == plugin ) {
mNavigator->setCurrentItem( i );
break;
}
}
blockSignals( blocked );
}
void IconSidePane::selectPlugin( const TQString &name )
{
bool blocked = signalsBlocked();
blockSignals( true );
for ( uint i = 0; i < mNavigator->count(); ++i ) {
EntryItem *item = static_cast<EntryItem*>( mNavigator->item( i ) );
if ( item->plugin()->identifier() == name ) {
mNavigator->setCurrentItem( i );
break;
}
}
blockSignals( blocked );
}
void IconSidePane::indicateForegrunding( Kontact::Plugin *plugin )
{
for ( uint i = 0; i < mNavigator->count(); ++i ) {
EntryItem *item = static_cast<EntryItem*>( mNavigator->item( i ) );
if ( item->plugin() == plugin ) {
mNavigator->highlightItem( item );
break;
}
}
}
#include "iconsidepane.moc"
// vim: sw=2 sts=2 et tw=80