Logo Search packages:      
Sourcecode: adept version File versions  Download package

extendablelist.cpp

#include <kdebug.h>
#include <qtimer.h>
#include <qobjectlist.h>
#include <qpainter.h>
#include <qimage.h>
#include <kiconeffect.h>
#include <kiconloader.h>

#include <adept/extendablelist.h>
#include <adept/utils.h>

using namespace adept;

ExtendableList::ExtendableList( QWidget *p, const char *n )
    : KListView( p, n ),
      m_toggleColumn( 0 ), m_inDtor( false ),
      m_extenderUpdateScheduled( false ),
      m_needSort( false ),
      m_extenderHighlight( false )
{
    // kdDebug() << "connecting processClick har har" << endl;
    connect( this, SIGNAL( clicked( QListViewItem *,
                                    const QPoint &, int ) ),
             this, SLOT( processClick( QListViewItem *,
                                       const QPoint &, int ) ) );
    connect( this, SIGNAL( moved() ),
             this, SLOT( delayedUpdateExtenders() ) );
    connect( this, SIGNAL( collapsed( QListViewItem * ) ),
             this, SLOT( delayedUpdateExtenders() ) );
    connect( this, SIGNAL( expanded( QListViewItem * ) ),
             this, SLOT( delayedUpdateExtenders() ) );
    setTreeStepSize( 15 );

    m_baseIcon = SmallIcon( u8( "extender_closed" ) );
    m_extendedIcon = SmallIcon( u8( "extender_opened" ) );
    QImage img;
    img = m_baseIcon;
    KIconEffect::toGray( img, 1.0 );
    m_unextendableIcon = QPixmap( img );
}

void ExtendableList::keyPressEvent( QKeyEvent *e ) {
    ExtendableItem *item = dynamic_cast< ExtendableItem* >( currentItem() );
    if ( item ) {
        if ( item->extendable() ) {
            if ( item->extender() && e->key() == Qt::Key_Left ) {
                return item->hideExtender();
            } else if ( !item->extender() && e->key() == Qt::Key_Right ) {
                return item->showExtender();
            }
        }
        KListView::keyPressEvent( e );
        if ( e->key() == Qt::Key_Left || e->key() == Qt::Key_Right )
            item->updateIcon();
    } else return KListView::keyPressEvent( e );
}

void ExtendableList::openToplevel() {
    QListViewItem *i;
    for ( i = firstChild(); i != 0; i = i->nextSibling() ) {
        i->setOpen( true );
    }
}

int ExtendableList::extenderOffset( ExtendableItem *i )
{
    int c = 0, x = 0;

    while( c < m_toggleColumn ) {
        x += columnWidth( c );
        c ++;
    }

    if ( m_toggleColumn >= 0 ) {
        // *sigh*
        if ( i->pixmap( m_toggleColumn ) )
            x += i->pixmap( m_toggleColumn )->width();
        if ( rootIsDecorated() )
            x += treeStepSize();
        if ( i->parent() )
            x += treeStepSize();
    }

    return x + 2; // + 2 = icon margin, apparently... gnah
}

void ExtendableList::updateExtender( ExtendableItem *i )
{
    // setUpdatesEnabled( false );

    // since updateGeometries is private, we use this dirty trick to
    // get at it (since setContentsPos in QListView calls it
    setContentsPos( contentsX(), contentsY() );

    if ( !i->isVisible() || ( i->parent() && !i->parent()->isOpen() ) ) {
        kdDebug() << "hiding invisible item's extender" << endl;
        i->hideExtender();
        return;
    }

    // QRect rect = itemRect( i );
    addChild( i->extender(), extenderOffset( i ), itemPos( i ) );
    // addChild( i->extender(), x, rect.y() );
    i->extender()->show();
    i->extender()->resize( visibleWidth() - extenderOffset( i ),
                           i->extender()->height() );
    if ( i->height() != i->extender()->frameSize().height() ) {
        i->setHeight( i->extender()->frameSize().height() );
        delayedUpdateExtenders(); // re-update since we broke layout
    }

    i->extender()->setupColors();

    // setUpdatesEnabled( true );
    // addChild( i->extender(), x, itemPos( i ) );
    // QTimer::singleShot( 0, this, SLOT( triggerUpdate() ) );
    // QTimer::singleShot( 0, i->extender(), SLOT( setupColors() ) );
}

void ExtendableList::delayedUpdateExtenders()
{
    if ( m_extenderUpdateScheduled )
        return;
    m_extenderUpdateScheduled = true;
    // kdDebug() << "ExtendableList::delayedUpdateExtenders()" << endl;
    QTimer::singleShot( 0, this, SLOT( updateExtenders() ) );
}

void ExtendableList::clear()
{
    kdDebug() << "ExtendableList::clear()" << endl;
    KListView::clear();
    kdDebug() << "end of ExtendableList::clear()" << endl;
}

void ExtendableList::show()
{
    KListView::show();
    updateExtenders();
}

void ExtendableList::showEvent( QShowEvent *e )
{
    KListView::showEvent( e );
    updateExtenders();
}

void ExtendableList::resizeEvent( QResizeEvent *e )
{
    KListView::resizeEvent( e );
    updateExtenders();
    // delayedUpdateExtenders();
}

void ExtendableList::updateExtenders()
{
    m_extenderUpdateScheduled = false;
    setUpdatesEnabled( false );
    // updateGeometries();
    // since updateGeometries is private, we use this dirty trick to
    // get at it (since setContentsPos in QListView calls it
    setContentsPos( contentsX(), contentsY() );
    extendersChanged();
    kdDebug() << "ExtendableList::updateExtenders(); count = "
              << m_extenders.size() << endl;
    if ( m_needSort ) {
        std::sort( m_extenders.begin(), m_extenders.end(), ExtendableItem::s_less );
        m_needSort = false;
    }

    std::for_each( m_extenders.begin(), m_extenders.end(),
                   std::bind1st( std::mem_fun( &ExtendableList::updateExtender ),
                                 this ) );

    setUpdatesEnabled( true );
    // triggerUpdate();
    if ( !m_extenderUpdateScheduled )
        QTimer::singleShot( 0, this, SLOT( triggerUpdate() ) );
    /* if ( m_extenders.empty() )
       QTimer::singleShot( 0, this, SLOT( triggerUpdate() ) ); */
    // QTimer::singleShot( 0, this, SIGNAL( extendersChanged() ) );
}

void ExtendableList::addExtender( ExtendableItem *item )
{
    m_extenders.push_back( item );
    m_needSort = true;
    // std::sort( m_extenders.begin(), m_extenders.end(), ExtendableItem::s_less );
    // updateExtender( item );
    delayedUpdateExtenders();
}

void ExtendableList::removeExtender( ExtendableItem *i )
{
    kdDebug() << "ExtendableList::removeExtender( " << i << " )" << endl;
    m_extenders.erase( std::remove( m_extenders.begin(),
                                    m_extenders.end(), i ),
                       m_extenders.end() );
    // the above retains ordering so no need to re-sort
    if (!m_inDtor)
        delayedUpdateExtenders();
}

void ExtendableList::processClick( QListViewItem *it,
                                   const QPoint &pt, int c )
{
    // if (! it) return;
    ExtendableItem *item = dynamic_cast< ExtendableItem* >( it );
    if (!item) return;
    kdDebug() << "ExtendableList::processClick (a real item)" << endl;

    if (c == m_toggleColumn)
        item->toggleExtender();
    if ( item->extender() )
        item->extender()->setupColors();
    delayedUpdateExtenders();
    /* if (item->extender()) {
        if (c == m_toggleColumn)
            item->toggleExtender();
    } else
    item->toggleExtender(); */
}

ExtendableList::~ExtendableList() {
}

ExtendableList *ExtendableItem::list()
{
    return dynamic_cast< ExtendableList * >( listView() );
}

bool ExtendableItem::s_less(
    const ExtendableItem *a, const ExtendableItem *b )
{
    return a->less( b );
}

int ExtendableItem::compare( QListViewItem *i, int c, bool asc ) const
{
    ExtendableItem *o = dynamic_cast< ExtendableItem * >( i );
    return int( o->less( this ) ) - int( less( o ) );
}

void ExtendableItem::updateIcon() {
    QPixmap p;
    if ( !extender() ) {
        p = list()->baseIcon();
        if ( !extendable() && !firstChild() ) {
            p = list()->unextendableIcon();
        } else if ( isOpen() ) {
            p = list()->extendedIcon();
        }
    } else {
        p = list()->extendedIcon();
    }
    setPixmap( list()->toggleColumn(), p );

    // umm hack
    if ( dynamic_cast< ExtendableItem * >( parent() ) )
        dynamic_cast< ExtendableItem * >( parent() )->updateIcon();
}


void ExtendableItem::toggleExtender()
{
    if (m_extender) {
        setup();
        if( list() ) // this could as well be 0... bah
            list()->removeExtender( this );
        delete m_extender;
        m_extender = 0;
    } else {
        m_extender = createExtender();
        if (m_extender) {
            m_extender->setItem( this );
            list()->addExtender( this );
        }
        if ( !m_extender && firstChild() ) {
            setOpen( !isOpen() );
        }
    }
    updateIcon();
}

void ExtendableItem::paintBranches( QPainter *p,
                                    const QColorGroup &cg, int w, int y, int h )
{
    /* if (!isAlternate())
        p->setBackgroundColor(
            KGlobalSettings::alternateBackgroundColor() );
            p->eraseRect( 0, y, w, h ); */
    p->eraseRect( 0, 0, w, h );
}

/* void ExtendableItem::paintCell( QPainter *p, const QColorGroup &cg,
                                int column, int width, int alignment )
{
    QPixmap pm( width, height() );
    QPainter _p( &pm );
    KListViewItem::paintCell( &_p, cg, column, width, alignment );
    p->drawPixmap( 0, 0, pm );
    } */


static void setcolor( QWidget *w, ExtendableItem *i ) {
    if ( i->isSelected() && i->list()->extenderHighlight() )
        w->setPaletteBackgroundColor( w->colorGroup().highlight() );
    else if ( i->isAlternate() )
        w->setPaletteBackgroundColor(
            KGlobalSettings::alternateBackgroundColor() );
    else
        w->setPaletteBackgroundColor( w->colorGroup().base() );
    // w->setBackgroundMode( QWidget::PaletteBase );
}
void ItemExtender::setupColors()
{
    if ( !item() ) return;
    setcolor( this, item() );
    QObjectList *chld = queryList( "QWidget" );
    QObjectListIt it( *chld );
    QWidget *o;
    while ((o = dynamic_cast< QWidget * >( it.current() )) != 0) {
        setcolor( o, item() );
        ++it;
    }
}

ExtendableItem::~ExtendableItem()
{
    // kdDebug() << "~ExtendableList; list = " << list() << endl;
    // kdDebug() << "extender() = " << extender() << endl;
    while ( firstChild() )
        delete firstChild(); // har har
    if( extender() && list() ) // list() could be 0...
       list()->removeExtender( this );
    if (extender())
        extender()->deleteLater();
}

Generated by  Doxygen 1.6.0   Back to index