/*
  Copyright (c) 2000 Caldera Systems

  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., 675 Mass Ave, Cambridge, MA 02139, USA.
*/

#include <qlayout.h>
#include <qlabel.h>
#include <qfocusdata.h>
#include <qstyle.h>
#include <kcursor.h>

#include <kglobal.h>
#include <kdebug.h>
#include <klocale.h>
#include <kiconloader.h>

#include "listview.h"
#include "listview.moc"

ListView::ListView(QWidget* parent, const char* name)
    : QScrollView(parent, name)
{
    items.setAutoDelete(false);

    setFrameStyle(NoFrame);
    setResizePolicy(Manual);
    setHScrollBarMode(QScrollView::AlwaysOff);
    setFocusPolicy( QWidget::StrongFocus );

    viewport()->setBackgroundMode(PaletteBackground);
}

ListView::~ListView()
{
}

ListViewItem *ListView::insertItem(int id, const QString& name, const QString& comment, const QString& icon)
{
    ListViewItem* item = new ListViewItem(id, name, comment, icon, this, viewport());
    connect(item, SIGNAL(selected(int)), SIGNAL(itemSelected(int)));
    connect(item, SIGNAL(selected(ListViewItem*)), SIGNAL(itemSelected(ListViewItem*)));
    items.append(item);

    addChild(item);
    relayout();

    return item;
}

void  ListView::relayout()
{
    int offset = 0;

    int realWidth = width();
    if ( verticalScrollBar()->isVisible() )
        realWidth -= qApp->style().pixelMetric( QStyle::PM_ScrollBarExtent, this );

    for (ListViewItem* item = items.first(); item != 0; item = items.next()) {
        int h = item->heightForWidth( realWidth );
        moveChild(item, 0, offset);
        item->resize( realWidth, h);
        offset += h;
    }
    resizeContents(width(), offset);
}

void ListView::resizeEvent(QResizeEvent*)
{
    relayout();
}

void ListView::keyReleaseEvent( QKeyEvent *ev )
{
    int key = ev->key();

    if ( key == Key_Down )
    {
        ListViewItem *next = items.next();
        if ( next )
            next->setFocus();
        else
            items.first()->setFocus();
    }
    else if ( key == Key_Up )
    {
        ListViewItem *prev = items.prev();
        if ( prev )
            prev->setFocus();
        else
            items.last()->setFocus();
    }
    else
        ev->ignore();

    QScrollView::keyReleaseEvent( ev );
}

void ListView::setCurrentItem( ListViewItem *item )
{
    if ( items.current() )
        items.current()->setHighlighted( false );

    items.find( item ); // sets the current item
}

ListViewItem::ListViewItem(int id, const QString& text, const QString& icon,
                           const QString& comment, ListView *listView,
                           QWidget* parent, const char* name )
    : QFrame(parent, name), _id(id)
{
    setFrameStyle(StyledPanel | Raised);
    setLineWidth(1);
    setCursor(KCursor::handCursor());
    setFocusPolicy( QWidget::StrongFocus );

    QGridLayout* lay = new QGridLayout(this, 2, 2, 4, 4);

    iconl = new QLabel(this);
    iconl->installEventFilter(this);
    iconl->setAlignment(AlignTop | AlignLeft);
    iconl->setPixmap(KGlobal::iconLoader()->loadIcon(icon, KIcon::Desktop, KIcon::SizeLarge));
    iconl->setMouseTracking( true );

    namel = new QLabel(this);
    namel->installEventFilter(this);
    namel->setAlignment(AlignLeft | AlignBottom);
    namel->setText("<strong>" + text + "</strong>");
    namel->setMouseTracking( true );

    commentl = new QLabel(this);
    commentl->installEventFilter(this);
    commentl->setTextFormat(RichText);
    commentl->setText(comment);
    commentl->setMouseTracking( true );

    // filter events of widget areas not covered by the labels.
    installEventFilter(this);

    lay->addMultiCellWidget(iconl, 0, 1, 0, 0);
    lay->addWidget(namel, 0, 1);
    lay->addWidget(commentl, 1, 1);
    lay->setColStretch(1, 10);

    m_text = text;
    m_icon = icon;
    m_comment = comment;
    m_listView = listView;

    m_doubleClicked = false;
}

void ListViewItem::setComment( const QString &comment )
{
    m_comment = comment;
    commentl->setText( m_comment );
}

int ListViewItem::heightForWidth(int w)
{
    return (48 + commentl->heightForWidth(w - 50));
}

void ListViewItem::enterEvent(QEvent*ev)
{
    m_listView->setCurrentItem( this );
    setFocus();
    setHighlighted(true);
    QFrame::enterEvent( ev );
}

void ListViewItem::leaveEvent(QEvent*ev)
{
    setHighlighted(false);
    QFrame::enterEvent( ev );
}

bool ListViewItem::eventFilter(QObject*, QEvent* e)
{
    if ( e->type() == QEvent::MouseButtonDblClick )
    {
        m_doubleClicked = true;
        return false;
    }

    if( e->type() == QEvent::MouseButtonRelease )
    {
        if ( m_doubleClicked )
            m_doubleClicked = false;
        else
        {
            emit selected(_id);
            emit selected(this);
        }
    }
    return false;
}

void ListViewItem::setHighlighted(bool h)
{
    if (h) {
        setLineWidth(2);
        setBackgroundColor(colorGroup().midlight());
        namel->setBackgroundColor(colorGroup().midlight());
        commentl->setBackgroundColor(colorGroup().midlight());
        iconl->setBackgroundColor(colorGroup().midlight());
    }
    else {
        setBackgroundColor(colorGroup().background());
        namel->setBackgroundColor(colorGroup().background());
        commentl->setBackgroundColor(colorGroup().background());
        iconl->setBackgroundColor(colorGroup().background());
        setLineWidth(1);
    }
}

void ListViewItem::focusInEvent( QFocusEvent *ev )
{
    m_listView->setCurrentItem( this );
    setHighlighted( true );
    QFrame::focusInEvent( ev );
}

void ListViewItem::focusOutEvent( QFocusEvent *ev )
{
    setHighlighted( false );
    QFrame::focusOutEvent( ev );
}

void ListViewItem::keyPressEvent( QKeyEvent *ev )
{
    int key = ev->key();
    if ( key == Key_Enter || key == Key_Return )
    {
        emit selected(_id);
        emit selected(this);
    }
    else
        ev->ignore();

    QFrame::keyPressEvent( ev );
}

void ListViewItem::keyReleaseEvent( QKeyEvent *ev )
{
    if ( ev->key() == Key_Space )
    {
        emit selected(_id);
        emit selected(this);
    }
    else
        ev->ignore();

    QFrame::keyReleaseEvent( ev );
}
