2 kopetelistviewitem.cpp - Kopete's modular QListViewItems
4 Copyright (c) 2005 by Engin AYDOGAN <engin@bzzzt.biz>
5 Copyright (c) 2004 by Richard Smith <kde@metafoo.co.uk>
7 Kopete (c) 2002-2004 by the Kopete developers <kopete-devel@kde.org>
9 *************************************************************************
11 * This program is free software; you can redistribute it and/or modify *
12 * it under the terms of the GNU General Public License as published by *
13 * the Free Software Foundation; either version 2 of the License, or *
14 * (at your option) any later version. *
16 *************************************************************************
23 #include "kopetecontact.h"
24 #include "kopetelistviewitem.h"
25 #include "kopeteemoticons.h"
26 #include "kopeteonlinestatus.h"
29 #include <kiconloader.h>
30 #include <kstringhandler.h>
32 #include <qapplication.h>
39 #include <qstyleoption.h>
44 # include <X11/Xlib.h>
45 # include <X11/extensions/Xrender.h>
54 // ComponentBase --------
56 class ComponentBase::Private
59 QList
<Component
*> components
;
62 ComponentBase::ComponentBase()
67 ComponentBase::~ComponentBase()
69 foreach( Component
*c
, d
->components
)
74 uint
ComponentBase::components() { return d
->components
.count(); }
76 Component
*ComponentBase::component( uint n
)
78 if( n
< components() )
79 return d
->components
.at( n
);
84 Component
*ComponentBase::componentAt( const QPoint
&pt
)
86 foreach( Component
* n
, d
->components
)
88 if ( n
->rect().contains( pt
) )
90 if ( Component
*comp
= n
->componentAt( pt
) )
98 void ComponentBase::componentAdded( Component
*component
)
100 d
->components
.append( component
);
103 void ComponentBase::componentRemoved( Component
*component
)
105 //TODO: make sure the component is in d->components once and only once.
106 // if not, the situation is best referred to as 'very very broken indeed'.
107 d
->components
.removeAll( component
);
110 void ComponentBase::clear()
112 foreach( Component
*c
, d
->components
)
114 d
->components
.clear();
117 void ComponentBase::componentResized( Component
* )
121 std::pair
<QString
,QRect
> ComponentBase::toolTip( const QPoint
&relativePos
)
123 foreach( Component
* n
, d
->components
)
124 if ( n
->rect().contains( relativePos
) )
125 return n
->toolTip( relativePos
);
127 return std::make_pair( QString::null
, QRect() );
130 void ComponentBase::updateAnimationPosition( int p
, int s
)
132 foreach( Component
* comp
, d
->components
)
134 QRect start
= comp
->startRect();
135 QRect target
= comp
->targetRect();
136 QRect
rc( start
.left() + ((target
.left() - start
.left()) * p
) / s
,
137 start
.top() + ((target
.top() - start
.top()) * p
) / s
,
138 start
.width() + ((target
.width() - start
.width()) * p
) / s
,
139 start
.height() + ((target
.height() - start
.height()) * p
) / s
);
141 comp
->updateAnimationPosition( p
, s
);
145 // Component --------
147 class Component::Private
150 Private( ComponentBase
*parent
)
151 : parent( parent
), minWidth( 0 ), minHeight( 0 )
152 , growHoriz( false ), growVert( false )
156 ComponentBase
*parent
;
158 QRect startRect
, targetRect
;
159 int minWidth
, minHeight
;
160 bool growHoriz
, growVert
;
161 bool show
; /** @since 23-03-2005 */
162 ToolTipSource
*tipSource
;
165 Component::Component( ComponentBase
*parent
)
166 : d( new Private( parent
) )
168 d
->parent
->componentAdded( this );
172 int Component::RTTI
= Rtti_Component
;
174 Component::~Component()
176 d
->parent
->componentRemoved( this );
181 void Component::hide()
186 void Component::show()
191 bool Component::isShown()
196 bool Component::isHidden()
201 void Component::setToolTipSource( ToolTipSource
*source
)
203 d
->tipSource
= source
;
206 std::pair
<QString
,QRect
> Component::toolTip( const QPoint
&relativePos
)
209 return ComponentBase::toolTip( relativePos
);
212 QString result
= (*d
->tipSource
)( this, relativePos
, rc
);
213 return std::make_pair(result
, rc
);
216 QRect
Component::rect() { return d
->rect
; }
217 QRect
Component::startRect() { return d
->startRect
; }
218 QRect
Component::targetRect() { return d
->targetRect
; }
220 int Component::minWidth() { return d
->minWidth
; }
221 int Component::minHeight() { return d
->minHeight
; }
222 int Component::widthForHeight( int ) { return minWidth(); }
223 int Component::heightForWidth( int ) { return minHeight(); }
225 bool Component::setMinWidth( int width
)
227 if ( d
->minWidth
== width
) return false;
230 d
->parent
->componentResized( this );
233 bool Component::setMinHeight( int height
)
235 if ( d
->minHeight
== height
) return false;
236 d
->minHeight
= height
;
238 d
->parent
->componentResized( this );
242 void Component::layout( const QRect
&newRect
)
244 if ( rect().isNull() )
245 d
->startRect
= QRect( newRect
.topLeft(), newRect
.topLeft() );
247 d
->startRect
= rect();
248 d
->targetRect
= newRect
;
249 //kdDebug(14000) << k_funcinfo << "At " << rect << endl;
252 void Component::setRect( const QRect
&rect
)
257 void Component::paint( QPainter
*painter
, const QColorGroup
&cg
)
259 /*painter->setPen( Qt::red );
260 painter->drawRect( rect() );*/
261 for ( uint n
= 0; n
< components(); ++n
)
263 if( component( n
)->isShown() )
264 component( n
)->paint( painter
, cg
);
268 void Component::repaint()
270 d
->parent
->repaint();
273 void Component::relayout()
275 d
->parent
->relayout();
278 void Component::componentAdded( Component
*component
)
280 ComponentBase::componentAdded( component
);
281 //update( Relayout );
284 void Component::componentRemoved( Component
*component
)
286 ComponentBase::componentRemoved( component
);
287 //update( Relayout );
290 // BoxComponent --------
292 class BoxComponent::Private
295 Private( BoxComponent::Direction dir
) : direction( dir
) {}
296 BoxComponent::Direction direction
;
298 static const int padding
= 2;
301 BoxComponent::BoxComponent( ComponentBase
*parent
, Direction dir
)
302 : Component( parent
), d( new Private( dir
) )
306 int BoxComponent::RTTI
= Rtti_BoxComponent
;
308 BoxComponent::~BoxComponent()
313 int BoxComponent::widthForHeight( int height
)
315 if ( d
->direction
!= Horizontal
)
318 for ( uint n
= 0; n
< components(); ++n
)
319 width
= qMax( width
, component( n
)->widthForHeight( height
) );
324 int width
= (components() - 1) * Private::padding
;
325 for ( uint n
= 0; n
< components(); ++n
)
326 width
+= component( n
)->widthForHeight( height
);
331 int BoxComponent::heightForWidth( int width
)
333 if ( d
->direction
== Horizontal
)
336 for ( uint n
= 0; n
< components(); ++n
)
337 height
= qMax( height
, component( n
)->heightForWidth( width
) );
342 int height
= (components() - 1) * Private::padding
;
343 for ( uint n
= 0; n
< components(); ++n
)
344 height
+= component( n
)->heightForWidth( width
);
349 void BoxComponent::calcMinSize()
351 int sum
= (components() - 1) * Private::padding
, max
= 0;
352 for ( uint n
= 0; n
< components(); ++n
)
354 Component
*comp
= component( n
);
355 if ( d
->direction
== Horizontal
)
357 max
= qMax( max
, comp
->minHeight() );
358 sum
+= comp
->minWidth();
362 max
= qMax( max
, comp
->minWidth() );
363 sum
+= comp
->minHeight();
367 bool sizeChanged
= false;
368 if ( d
->direction
== Horizontal
)
370 if ( setMinWidth( sum
) ) sizeChanged
= true;
371 if ( setMinHeight( max
) ) sizeChanged
= true;
375 if ( setMinWidth( max
) ) sizeChanged
= true;
376 if ( setMinHeight( sum
) ) sizeChanged
= true;
385 void BoxComponent::layout( const QRect
&rect
)
387 Component::layout( rect
);
389 bool horiz
= (d
->direction
== Horizontal
);
391 for ( uint n
= 0; n
< components(); ++n
)
393 Component
*comp
= component( n
);
395 fixedSize
+= comp
->minWidth();
397 fixedSize
+= comp
->minHeight();
400 // remaining space after all fixed items have been allocated
401 int padding
= Private::padding
;
403 // ensure total is at least minXXX. the only time the rect
404 // will be smaller than that is when we don't fit, and in
405 // that cases we should pretend that we're wide/high enough.
408 total
= qMax( rect
.width(), minWidth() );
410 total
= qMax( rect
.height(), minHeight() );
412 int remaining
= total
- fixedSize
- padding
* (components() - 1);
414 // finally, lay everything out
416 for ( uint n
= 0; n
< components(); ++n
)
418 Component
*comp
= component( n
);
423 rc
.setLeft( rect
.left() + pos
);
424 rc
.setTop( rect
.top() );
425 rc
.setHeight( rect
.height() );
426 int minWidth
= comp
->minWidth();
427 int desiredWidth
= comp
->widthForHeight( rect
.height() );
428 rc
.setWidth( qMin( remaining
+ minWidth
, desiredWidth
) );
430 remaining
-= rc
.width() - minWidth
;
434 rc
.setLeft( rect
.left() );
435 rc
.setTop( rect
.top() + pos
);
436 rc
.setWidth( rect
.width() );
437 int minHeight
= comp
->minHeight();
438 int desiredHeight
= comp
->heightForWidth( rect
.width() );
439 rc
.setHeight( qMin( remaining
+ minHeight
, desiredHeight
) );
441 remaining
-= rc
.height() - minHeight
;
443 comp
->layout( rc
& rect
);
448 void BoxComponent::componentAdded( Component
*component
)
450 Component::componentAdded( component
);
454 void BoxComponent::componentRemoved( Component
*component
)
456 Component::componentRemoved( component
);
460 void BoxComponent::componentResized( Component
*component
)
462 Component::componentResized( component
);
466 // ImageComponent --------
468 class ImageComponent::Private
474 ImageComponent::ImageComponent( ComponentBase
*parent
)
475 : Component( parent
), d( new Private
)
479 int ImageComponent::RTTI
= Rtti_ImageComponent
;
481 ImageComponent::ImageComponent( ComponentBase
*parent
, int minW
, int minH
)
482 : Component( parent
), d( new Private
)
485 setMinHeight( minH
);
489 ImageComponent::~ImageComponent()
494 QPixmap
ImageComponent::pixmap()
499 void ImageComponent::setPixmap( const QPixmap
&img
, bool adjustSize
)
504 setMinWidth( img
.width() );
505 setMinHeight( img
.height() );
510 static QPoint
operator+( const QPoint
&pt
, const QSize
&sz
)
512 return QPoint( pt
.x() + sz
.width(), pt
.y() + sz
.height() );
515 /*static QPoint operator+( const QSize &sz, const QPoint &pt )
520 void ImageComponent::paint( QPainter
*painter
, const QColorGroup
& )
522 QRect ourRc
= rect();
523 QRect rc
= d
->image
.rect();
524 // center rc within our rect
525 rc
.moveTopLeft( ourRc
.topLeft() + (ourRc
.size() - rc
.size()) / 2 );
526 // paint, shrunk to be within our rect
527 painter
->drawPixmap( rc
& ourRc
, d
->image
);
530 void ImageComponent::scale( int w
, int h
, Qt::AspectRatioMode mode
)
532 QImage im
= d
->image
.convertToImage();
533 setPixmap( QPixmap( im
.smoothScale( w
, h
, mode
) ) );
537 class TextComponent::Private
540 Private() : customColor( false ) {}
547 TextComponent::TextComponent( ComponentBase
*parent
, const QFont
&font
, const QString
&text
)
548 : Component( parent
), d( new Private
)
554 int TextComponent::RTTI
= Rtti_TextComponent
;
556 TextComponent::~TextComponent()
561 QString
TextComponent::text()
566 void TextComponent::setText( const QString
&text
)
568 if ( text
== d
->text
) return;
574 QFont
TextComponent::font()
579 void TextComponent::setFont( const QFont
&font
)
581 if ( font
== d
->font
) return;
586 void TextComponent::calcMinSize()
590 if ( !d
->text
.isEmpty() )
591 setMinHeight( QFontMetrics( font() ).height() );
598 int TextComponent::widthForHeight( int )
600 // add 2 to place an extra gap between the text and things to its right.
601 // allegedly if this is not done the protocol icons overlap the text.
602 // i however have never seen this problem (which would almost certainly
603 // be a bug somewhere else).
604 return QFontMetrics( font() ).width( d
->text
) + 2;
607 QColor
TextComponent::color()
609 return d
->customColor
? d
->color
: QColor();
612 void TextComponent::setColor( const QColor
&color
)
615 d
->customColor
= true;
619 void TextComponent::setDefaultColor()
621 d
->customColor
= false;
625 void TextComponent::paint( QPainter
*painter
, const QColorGroup
&cg
)
627 if ( d
->customColor
)
628 painter
->setPen( d
->color
);
630 painter
->setPen( cg
.text() );
631 QString dispStr
= KStringHandler::rPixelSqueeze( d
->text
, QFontMetrics( font() ), rect().width() );
632 painter
->setFont( font() );
633 painter
->drawText( rect(), Qt::TextSingleLine
, dispStr
);
636 // DisplayNameComponent
638 class DisplayNameComponent::Private
645 DisplayNameComponent::DisplayNameComponent( ComponentBase
*parent
)
646 : BoxComponent( parent
), d( new Private
)
650 int DisplayNameComponent::RTTI
= Rtti_DisplayNameComponent
;
652 DisplayNameComponent::~DisplayNameComponent()
656 void DisplayNameComponent::layout( const QRect
&rect
)
658 Component::layout( rect
);
660 // finally, lay everything out
662 int totalWidth
= rect
.width();
664 bool exceeded
= false;
665 for ( uint n
= 0; n
< components(); ++n
)
667 Component
*comp
= component( n
);
670 if ( ( usedWidth
+ comp
->widthForHeight( rect
.height() ) ) > totalWidth
)
673 // TextComponents can squeeze themselves
674 if ( comp
->rtti() == Rtti_TextComponent
)
677 comp
->layout( QRect( usedWidth
+ rect
.left(), rect
.top(),
678 totalWidth
- usedWidth
,
679 comp
->heightForWidth( totalWidth
- usedWidth
) ) );
687 comp
->layout( QRect( usedWidth
+ rect
.left(), rect
.top(),
688 comp
->widthForHeight( rect
.height() ),
689 comp
->heightForWidth( rect
.width() ) ) );
691 usedWidth
+= comp
->widthForHeight( rect
.height() );
695 // Shall we implement a hide()/show() in Component class ?
701 void DisplayNameComponent::setText( const QString
& text
)
703 if ( d
->text
== text
)
710 void DisplayNameComponent::redraw()
713 for ( uint n
= 0; n
< components(); ++n
)
714 if( component( n
)->rtti() == Rtti_TextComponent
)
716 ((TextComponent
*)component(n
))->color();
719 Q3ValueList
<Kopete::Emoticons::Token
> tokens
;
720 Q3ValueList
<Kopete::Emoticons::Token
>::const_iterator token
;
722 clear(); // clear childs
724 tokens
= Kopete::Emoticons::tokenizeEmoticons( d
->text
);
728 QFontMetrics
fontMetrics( d
->font
);
729 int fontHeight
= fontMetrics
.height();
730 for ( token
= tokens
.begin(); token
!= tokens
.end(); ++token
)
732 switch ( (*token
).type
)
734 case Kopete::Emoticons::Text
:
735 t
= new TextComponent( this, d
->font
, (*token
).text
);
737 case Kopete::Emoticons::Image
:
738 ic
= new ImageComponent( this );
739 ic
->setPixmap( QPixmap( (*token
).picPath
) );
740 ic
->scale( INT_MAX
, fontHeight
, Qt::KeepAspectRatio
);
743 kdDebug( 14010 ) << k_funcinfo
<< "This should have not happened!" << endl
;
751 void DisplayNameComponent::setFont( const QFont
& font
)
753 for ( uint n
= 0; n
< components(); ++n
)
754 if( component( n
)->rtti() == Rtti_TextComponent
)
755 ((TextComponent
*)component(n
))->setFont( font
);
759 void DisplayNameComponent::setColor( const QColor
& color
)
761 for ( uint n
= 0; n
< components(); ++n
)
762 if( component( n
)->rtti() == Rtti_TextComponent
)
763 ((TextComponent
*)component(n
))->setColor( color
);
766 void DisplayNameComponent::setDefaultColor()
768 for ( uint n
= 0; n
< components(); ++n
)
769 if( component( n
)->rtti() == Rtti_TextComponent
)
770 ((TextComponent
*)component(n
))->setDefaultColor();
773 QString
DisplayNameComponent::text()
778 // HSpacerComponent --------
780 HSpacerComponent::HSpacerComponent( ComponentBase
*parent
)
781 : Component( parent
)
787 int HSpacerComponent::RTTI
= Rtti_HSpacerComponent
;
789 int HSpacerComponent::widthForHeight( int )
794 // VSpacerComponent --------
796 VSpacerComponent::VSpacerComponent( ComponentBase
*parent
)
797 : Component( parent
)
803 int VSpacerComponent::RTTI
= Rtti_VSpacerComponent
;
805 int VSpacerComponent::heightForWidth( int )
810 ////////////////// ContactComponent /////////////////////////
812 class ContactComponent::Private
815 Kopete::Contact
*contact
;
819 ContactComponent::ContactComponent( ComponentBase
*parent
, Kopete::Contact
*contact
, int iconSize
) : ImageComponent( parent
) , d( new Private
)
821 d
->contact
= contact
;
822 d
->iconSize
= iconSize
;
826 ContactComponent::~ContactComponent()
831 void ContactComponent::updatePixmap()
833 setPixmap( contact()->onlineStatus().iconFor( contact(), d
->iconSize
) );
835 Kopete::Contact
*ContactComponent::contact()
840 // we don't need to use a tooltip source here - this way is simpler
841 std::pair
<QString
,QRect
> ContactComponent::toolTip( const QPoint
&/*relativePos*/ )
843 return std::make_pair(d
->contact
->toolTip(),rect());
846 ////////////////// SpacerComponent /////////////////////////
848 SpacerComponent::SpacerComponent( ComponentBase
*parent
, int w
, int h
) : Component( parent
)
857 * A periodic timer intended to be shared amongst multiple objects. Will run only
858 * if an object is attached to it.
860 class SharedTimer
: private QTimer
865 SharedTimer( int period
) : period(period
), users(0) {}
866 void attach( QObject
*target
, const char *slot
)
868 connect( this, SIGNAL(timeout()), target
, slot
);
871 //kdDebug(14000) << "SharedTimer::attach: users is now " << users << "\n";
873 void detach( QObject
*target
, const char *slot
)
875 disconnect( this, SIGNAL(timeout()), target
, slot
);
878 //kdDebug(14000) << "SharedTimer::detach: users is now " << users << "\n";
885 QObject
* const object
;
886 const char * const slot
;
889 SharedTimerRef( SharedTimer
&timer
, QObject
*obj
, const char *slot
)
890 : timer(timer
), object(obj
), slot(slot
), attached(false)
895 if( attached
) return;
896 timer
.attach( object
, slot
);
901 if( !attached
) return;
902 timer
.detach( object
, slot
);
914 Private( Item
*item
)
915 : layoutAnimateTimer( theLayoutAnimateTimer(), item
, SLOT( slotLayoutAnimateItems() ) )
916 , animateLayout( true ), opacity( 1.0 )
917 , visibilityTimer( theVisibilityTimer(), item
, SLOT( slotUpdateVisibility() ) )
918 , visibilityLevel( 0 ), visibilityTarget( false ), searchMatch( true )
924 //QTimer layoutAnimateTimer;
925 SharedTimerRef layoutAnimateTimer
;
926 SharedTimer
&theLayoutAnimateTimer()
928 static SharedTimer
timer( 10 );
933 int layoutAnimateSteps
;
934 static const int layoutAnimateStepsTotal
= 10;
938 //QTimer visibilityTimer;
939 SharedTimerRef visibilityTimer
;
940 SharedTimer
&theVisibilityTimer()
942 static SharedTimer
timer( 40 );
948 bool visibilityTarget
;
950 static const int visibilityFoldSteps
= 7;
952 static const int visibilityFadeSteps
= 7;
954 static const int visibilityFadeSteps
= 0;
956 static const int visibilityStepsTotal
= visibilityFoldSteps
+ visibilityFadeSteps
;
960 static bool animateChanges
;
961 static bool fadeVisibility
;
962 static bool foldVisibility
;
965 bool Item::Private::animateChanges
= true;
966 bool Item::Private::fadeVisibility
= true;
967 bool Item::Private::foldVisibility
= true;
969 Item::Item( Q3ListViewItem
*parent
, QObject
*owner
, const char *name
)
970 : QObject( owner
, name
), KListViewItem( parent
), d( new Private(this) )
975 Item::Item( Q3ListView
*parent
, QObject
*owner
, const char *name
)
976 : QObject( owner
, name
), KListViewItem( parent
), d( new Private(this) )
986 void Item::setEffects( bool animation
, bool fading
, bool folding
)
988 Private::animateChanges
= animation
;
989 Private::fadeVisibility
= fading
;
990 Private::foldVisibility
= folding
;
995 connect( listView()->header(), SIGNAL( sizeChange( int, int, int ) ), SLOT( slotColumnResized() ) );
996 connect( &d
->layoutTimer
, SIGNAL( timeout() ), SLOT( slotLayoutItems() ) );
997 //connect( &d->layoutAnimateTimer, SIGNAL( timeout() ), SLOT( slotLayoutAnimateItems() ) );
998 //connect( &d->visibilityTimer, SIGNAL( timeout() ), SLOT( slotUpdateVisibility() ) );
1000 setTargetVisibility( true );
1003 void Item::slotColumnResized()
1006 // if we've been resized, don't animate the layout
1007 d
->animateLayout
= false;
1010 void Item::scheduleLayout()
1012 // perform a delayed layout in order to speed it all up
1013 if ( ! d
->layoutTimer
.isActive() )
1014 d
->layoutTimer
.start( 30, true );
1017 void Item::slotLayoutItems()
1019 d
->layoutTimer
.stop();
1021 for ( uint n
= 0; n
< components(); ++n
)
1023 int width
= listView()->columnWidth(n
);
1026 int d
= depth() + (listView()->rootIsDecorated() ? 1 : 0);
1027 width
-= d
* listView()->treeStepSize();
1030 int height
= component( n
)->heightForWidth( width
);
1031 component( n
)->layout( QRect( 0, 0, width
, height
) );
1032 //kdDebug(14000) << k_funcinfo << "Component " << n << " is " << width << " x " << height << endl;
1035 if ( Private::animateChanges
&& d
->animateLayout
&& !d
->visibilityTimer
.isActive() )
1037 d
->layoutAnimateTimer
.start();
1038 //if ( !d->layoutAnimateTimer.isActive() )
1039 // d->layoutAnimateTimer.start( 10 );
1040 d
->layoutAnimateSteps
= 0;
1044 d
->layoutAnimateSteps
= Private::layoutAnimateStepsTotal
;
1045 d
->animateLayout
= true;
1047 slotLayoutAnimateItems();
1050 void Item::slotLayoutAnimateItems()
1052 if ( ++d
->layoutAnimateSteps
>= Private::layoutAnimateStepsTotal
)
1053 d
->layoutAnimateTimer
.stop();
1055 const int s
= Private::layoutAnimateStepsTotal
;
1056 const int p
= qMin( d
->layoutAnimateSteps
, s
);
1058 updateAnimationPosition( p
, s
);
1063 float Item::opacity()
1068 void Item::setOpacity( float opacity
)
1070 if ( d
->opacity
== opacity
) return;
1071 d
->opacity
= opacity
;
1075 void Item::setSearchMatch( bool match
)
1077 d
->searchMatch
= match
;
1080 setVisible( false );
1083 kdDebug(14000) << k_funcinfo
<< " match: " << match
<< ", vis timer active: " << d
->visibilityTimer
.isActive()
1084 << ", target visibility: " << targetVisibility() << endl
;
1085 if ( d
->visibilityTimer
.isActive() )
1088 setVisible( targetVisibility() );
1092 bool Item::targetVisibility()
1094 return d
->visibilityTarget
;
1097 void Item::setTargetVisibility( bool vis
)
1099 if ( d
->visibilityTarget
== vis
)
1101 // in case we're getting called because our parent was shown and
1102 // we need to be rehidden
1103 if ( !d
->visibilityTimer
.isActive() )
1104 setVisible( vis
&& d
->searchMatch
);
1107 d
->visibilityTarget
= vis
;
1108 d
->visibilityTimer
.start();
1109 //d->visibilityTimer.start( 40 );
1110 if ( targetVisibility() )
1111 setVisible( d
->searchMatch
);
1112 slotUpdateVisibility();
1115 void Item::slotUpdateVisibility()
1117 if ( targetVisibility() )
1118 ++d
->visibilityLevel
;
1120 --d
->visibilityLevel
;
1122 if ( !Private::foldVisibility
&& !Private::fadeVisibility
)
1123 d
->visibilityLevel
= targetVisibility() ? Private::visibilityStepsTotal
: 0;
1124 else if ( !Private::fadeVisibility
&& d
->visibilityLevel
>= Private::visibilityFoldSteps
)
1125 d
->visibilityLevel
= targetVisibility() ? Private::visibilityStepsTotal
: Private::visibilityFoldSteps
- 1;
1126 else if ( !Private::foldVisibility
&& d
->visibilityLevel
<= Private::visibilityFoldSteps
)
1127 d
->visibilityLevel
= targetVisibility() ? Private::visibilityFoldSteps
+ 1 : 0;
1129 if ( d
->visibilityLevel
>= Private::visibilityStepsTotal
)
1131 d
->visibilityLevel
= Private::visibilityStepsTotal
;
1132 d
->visibilityTimer
.stop();
1134 else if ( d
->visibilityLevel
<= 0 )
1136 d
->visibilityLevel
= 0;
1137 d
->visibilityTimer
.stop();
1138 setVisible( false );
1144 void Item::repaint()
1146 // if we're about to relayout, don't bother painting yet.
1147 if ( d
->layoutTimer
.isActive() )
1149 listView()->repaintItem( this );
1152 void Item::relayout()
1159 KListViewItem::setup();
1163 void Item::setHeight( int )
1166 for ( uint n
= 0; n
< components(); ++n
)
1167 minHeight
= qMax( minHeight
, component( n
)->rect().height() );
1168 //kdDebug(14000) << k_funcinfo << "Height is " << minHeight << endl;
1169 if ( Private::foldVisibility
&& d
->visibilityTimer
.isActive() )
1171 int vis
= d
->visibilityLevel
;
1172 if ( vis
> Private::visibilityFoldSteps
)
1173 vis
= Private::visibilityFoldSteps
;
1174 minHeight
= (minHeight
* vis
) / Private::visibilityFoldSteps
;
1176 KListViewItem::setHeight( minHeight
);
1179 int Item::width( const QFontMetrics
&, const Q3ListView
*lv
, int c
) const
1181 // Qt computes the itemRect from this. we want the whole item to be
1182 // clickable, so we return the widest we could possibly be.
1183 return lv
->header()->sectionSize( c
);
1186 void Item::paintCell( QPainter
*p
, const QColorGroup
&cg
, int column
, int width
, int align
)
1188 QPixmap
back( width
, height() );
1189 QPainter
paint( &back
);
1190 //KListViewItem::paintCell( &paint, cg, column, width, align );
1191 // PASTED FROM KLISTVIEWITEM:
1192 // set the alternate cell background colour if necessary
1193 QColorGroup _cg
= cg
;
1195 if (listView()->viewport()->backgroundMode()==Qt::FixedColor
)
1196 _cg
.setColor(QColorGroup::Background
, static_cast< KListView
* >(listView())->alternateBackground());
1198 _cg
.setColor(QColorGroup::Base
, static_cast< KListView
* >(listView())->alternateBackground());
1199 // PASTED FROM QLISTVIEWITEM
1201 QPainter
*p
= &paint
;
1203 Q3ListView
*lv
= listView();
1206 QFontMetrics
fm( p
->fontMetrics() );
1208 // any text we render is done by the Components, not by this class, so make sure we've nothing to write
1211 // removed text truncating code from Qt - we do that differently, further on
1213 int marg
= lv
->itemMargin();
1215 // const QPixmap * icon = pixmap( column );
1216 #warning Item::paintCell needs fixing
1218 const QPalette::ColorRole crole = backgroundRole();
1220 if ( _cg.brush( crole ) != lv->colorGroup().brush( crole ) )
1221 p->fillRect( 0, 0, width, height(), _cg.brush( crole ) );
1224 // all copied from QListView::paintEmptyArea
1226 //lv->paintEmptyArea( p, QRect( 0, 0, width, height() ) );
1227 QStyleOption opt( lv->sortColumn(), 0 ); // ### hack; in 3.1, add a property in QListView and QHeader
1228 QStyle::SFlags how = QStyle::State_Default;
1229 if ( lv->isEnabled() )
1230 how |= QStyle::State_Enabled;
1232 lv->style()->drawComplexControl( QStyle::CC_Q3ListView,
1233 p, lv, QRect( 0, 0, width, height() ), lv->colorGroup(),
1234 how, QStyle::SC_Q3ListView, QStyle::SC_None,
1240 if ( isSelected() &&
1241 (column == 0 || lv->allColumnsShowFocus()) ) {
1242 p->fillRect( r - marg, 0, width - r + marg, height(),
1243 _cg.brush( QColorGroup::Highlight ) );
1244 // removed text pen setting code from Qt
1247 // removed icon drawing code from Qt
1249 // draw the tree gubbins
1250 if ( multiLinesEnabled() && column == 0 && isOpen() && childCount() ) {
1251 int textheight = fm.size( align, t ).height() + 2 * lv->itemMargin();
1252 textheight = qMax( textheight, QApplication::globalStrut().height() );
1253 if ( textheight % 2 > 0 )
1255 if ( textheight < height() ) {
1256 int w = lv->treeStepSize() / 2;
1257 lv->style()->drawComplexControl( QStyle::CC_Q3ListView, p, lv,
1258 QRect( 0, textheight, w + 1, height() - textheight + 1 ), _cg,
1259 lv->isEnabled() ? QStyle::State_Enabled : QStyle::State_Default,
1260 QStyle::SC_Q3ListViewExpand,
1261 (uint)QStyle::SC_All, QStyleOption( this ) );
1269 //do you see a better way to tell the TextComponent we are selected ? - Olivier 2004-09-02
1271 _cg
.setColor(QColorGroup::Text
, _cg
.highlightedText() );
1273 if ( Component
*comp
= component( column
) )
1274 comp
->paint( &paint
, _cg
);
1278 QColor rgb
= cg
.base();//backgroundColor();
1280 if ( d
->visibilityTimer
.isActive() && Private::fadeVisibility
)
1282 int vis
= d
->visibilityLevel
- Private::visibilityFoldSteps
;
1286 opac
= float(vis
) / Private::visibilityFadeSteps
;
1289 const int alpha
= 257 - int(opac
* 257);
1292 XRenderColor clr
= { alpha
* rgb
.red(), alpha
* rgb
.green(), alpha
* rgb
.blue(), alpha
* 0xff };
1293 XRenderFillRectangle( back
.x11Display(), PictOpOver
, back
.x11PictureHandle(),
1294 &clr
, 0, 0, width
, height() );
1298 p
->drawPixmap( 0, 0, back
);
1301 void Item::componentAdded( Component
*component
)
1303 ComponentBase::componentAdded( component
);
1307 void Item::componentRemoved( Component
*component
)
1309 ComponentBase::componentRemoved( component
);
1313 void Item::componentResized( Component
*component
)
1315 ComponentBase::componentResized( component
);
1319 } // END namespace ListView
1320 } // END namespace UI
1321 } // END namespace Kopete
1323 #include "kopetelistviewitem.moc"
1325 // vim: set noet ts=4 sts=4 sw=4: