/***************************************************************************
*   Copyright (C) 2004-2009 by Thomas Fischer                             *
*   fischer@unix-ag.uni-kl.de                                             *
*                                                                         *
*   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.,                                       *
*   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
***************************************************************************/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif

#include <tqevent.h>
#include <tqdragobject.h>
#include <tqfile.h>
#include <tqvaluelist.h>
#include <tqcursor.h>
#include <tqbuffer.h>
#include <tqlistview.h>
#include <tqclipboard.h>
#include <tqheader.h>
#include <tqtextstream.h>
#include <tqtimer.h>

#include <tdeapplication.h>
#include <tdeio/netaccess.h>
#include <tdetempfile.h>
#include <tdelocale.h>
#include <kurl.h>
#include <kurldrag.h>
#include <tdeactionclasses.h>
#include <tdeaction.h>
#include <tdepopupmenu.h>
#include <tdemessagebox.h>
#include <kprogress.h>
#include <kiconloader.h>

#include "kbibtex_part.h"
#include "documentlistviewitem.h"
#include "file.h"
#include "fileimporterbibutils.h"
#include "fileimporterris.h"
#include "fileimporterbibtex.h"
#include "fileexporterbibtex.h"
#include "element.h"
#include "entry.h"
#include "macro.h"
#include "comment.h"
#include "preamblewidget.h"
#include "preamble.h"
#include "entrywidget.h"
#include "commentwidget.h"
#include "macrowidget.h"
#include "settings.h"
#include "encoderlatex.h"

#include "documentlistview.h"

namespace KBibTeX
{
    DocumentListView::DocumentListView( KBibTeX::DocumentWidget *docWidget, bool isReadOnly, TQWidget *parent, const char *name )
            : TDEListView( parent, name ), m_docWidget( docWidget ), m_bibtexFile( NULL ), m_contextMenu( NULL ), m_headerMenu( NULL ), m_isReadOnly( isReadOnly ), m_newElementCounter( 1 )
    {
        setAllColumnsShowFocus( true );
        setShowSortIndicator( true );
        setSelectionMode( TQListView::Extended );
        header() ->setClickEnabled( true );
        header() ->setMovingEnabled( true );
        buildColumns();

        setDragEnabled( true );
        //         setDragAutoScroll( true );
        setAcceptDrops( true );
        setDropVisualizer( true );

        connect( header(), TQ_SIGNAL( clicked( int ) ), this, TQ_SLOT( setSortingColumn( int ) ) );
        connect( this, TQ_SIGNAL( contextMenu( TDEListView *, TQListViewItem *, const TQPoint & ) ), this, TQ_SLOT( showBibtexListContextMenu( TDEListView *, TQListViewItem *, const TQPoint & ) ) );
        connect( this, TQ_SIGNAL( doubleClicked( TQListViewItem*, const TQPoint&, int ) ), this, TQ_SLOT( slotDoubleClick( TQListViewItem* ) ) );
        connect( this, TQ_SIGNAL( dropped( TQDropEvent*, TQListViewItem* ) ), this, TQ_SLOT( slotDropped( TQDropEvent*, TQListViewItem* ) ) );
    }

    DocumentListView::~DocumentListView()
    {
        // nothing
    }

    void DocumentListView::setFactory( KXMLGUIFactory *factory, KXMLGUIClient *client )
    {
        m_contextMenu = static_cast<TDEPopupMenu*>( factory -> container( "popup_bibtexlist", client ) );
    }

    bool DocumentListView::setBibTeXFile( BibTeX::File *bibtexFile )
    {
        m_bibtexFile = bibtexFile;
        setItems();

        return true;
    }

    BibTeX::File* DocumentListView::getBibTeXFile( )
    {
        return m_bibtexFile;
    }

    void DocumentListView::setItems()
    {
        TQApplication::setOverrideCursor( TQt::waitCursor );

        KProgressDialog *prgDlg = new KProgressDialog( this, "prgDlg", i18n( "List View" ), i18n( "Updating main view ..." ), true );
        prgDlg->show();
        KProgress *progress = prgDlg->progressBar();
        progress->setTotalSteps( m_bibtexFile->count() );

        bool update = viewport()->isUpdatesEnabled();
        viewport()->setUpdatesEnabled( false );
        int sortCol = sortColumn();
        setSortColumn( -1 );

        clear();
        for ( unsigned int i = 0; i < m_bibtexFile->count(); i++ )
        {
            BibTeX::Element *element = m_bibtexFile->at( i );
            new DocumentListViewItem( m_bibtexFile, element, this );
            progress->setProgress( i );

            if ( i % 43 == 23 )
                kapp->processEvents();
        }

        viewport()->setUpdatesEnabled( update );
        setSortColumn( sortCol );
        triggerUpdate();
        delete prgDlg;

        updateVisiblity();

        TQApplication::restoreOverrideCursor();
    }

    void DocumentListView::insertItems( BibTeX::File *items, KBibTeX::DocumentListViewItem *after )
    {
        for ( BibTeX::File::ElementList::iterator it = items->begin(); it != items->end(); it++ )
            after = insertItem( *it, after );
    }

    KBibTeX::DocumentListViewItem * DocumentListView::insertItem( BibTeX::Element *item, KBibTeX::DocumentListViewItem *after )
    {
        if ( m_bibtexFile == NULL )
            m_bibtexFile = new BibTeX::File();

        BibTeX::Element *element = NULL;
        BibTeX::Entry *entry = dynamic_cast<BibTeX::Entry *>( item );
        if ( entry != NULL )
        {
            BibTeX::Entry *newEntry = new BibTeX::Entry( entry );
            if ( m_bibtexFile->containsKey( newEntry->id() ) )
            {
                int counter = 0;
                TQString newId = TQString( newEntry->id() ).append( '_' ).append( TQString::number( ++counter ) );
                while ( m_bibtexFile->containsKey( newId ) )
                    newId = TQString( newEntry->id() ).append( '_' ).append( TQString::number( ++counter ) );
                newEntry->setId( newId );
            }
            element = newEntry;
        }
        else
            element = item->clone();


        m_bibtexFile->appendElement( element, after == NULL ? NULL : after->element() );
        after = new DocumentListViewItem( m_bibtexFile, element, this, after );
        after->setUnreadStatus( true );
        updateVisiblity( after );
        m_unreadItems.append( after );

        emit modified();
        TQTimer::singleShot( 3500, this, TQ_SLOT( makeNewItemsUnread() ) );

        return after;
    }

    void DocumentListView::insertItem( BibTeX::Element *item )
    {
        insertItem( item, NULL );
    }

    void DocumentListView::updateVisiblity()
    {
        TQListViewItemIterator it( this );
        while ( it.current() )
        {
            DocumentListViewItem * kblvi = dynamic_cast<DocumentListViewItem*>( it.current() );
            updateVisiblity( kblvi );
            it++;
        }
    }

    void DocumentListView::updateVisiblity( KBibTeX::DocumentListViewItem *item )
    {
        Settings * settings = Settings::self( m_bibtexFile );
        BibTeX::Element *element = item->element();
        bool notFiltered = m_filter.isEmpty() || element ->containsPattern( m_filter, m_filterFieldType, m_filterType );

        BibTeX::Macro *macro = dynamic_cast<BibTeX::Macro*>( element );
        if ( macro != NULL )
            item->setVisible( notFiltered && settings->editing_ShowMacros );
        else
        {
            BibTeX::Comment *comment = dynamic_cast<BibTeX::Comment*>( element );
            if ( comment != NULL )
                item->setVisible( notFiltered && settings->editing_ShowComments );
            else
                item->setVisible( notFiltered );
        }
    }

    void DocumentListView::deferredInitialization()
    {
        connect( header(), TQ_SIGNAL( sizeChange( int, int, int ) ), this, TQ_SLOT( saveColumnWidths() ) );
        connect( header(), TQ_SIGNAL( indexChange( int, int, int ) ), this, TQ_SLOT( saveColumnIndex() ) );
    }

    void DocumentListView::restoreState()
    {
        Settings * settings = Settings::self( m_bibtexFile );
        if ( settings->editing_UseSpecialFont )
            setFont( settings->editing_SpecialFont );
        else
            setFont( TDEGlobalSettings::generalFont() );
        header() ->setFont( TDEGlobalSettings::generalFont() );

        restoreColumnIndex();
        restoreColumnWidths();
        restoreSortingColumn();
    }

    void DocumentListView::setViewShowColumnsMenu( TDEActionMenu *actionMenu )
    {
        if ( m_headerMenu == NULL )
        {
            m_headerMenu = actionMenu->popupMenu();
            m_headerMenu->insertTitle( i18n( "Show Columns" ) );
            m_headerMenu->setCheckable( true );
            connect( m_headerMenu, TQ_SIGNAL( activated( int ) ), this, TQ_SLOT( activateShowColumnMenu( int ) ) );

            Settings * settings = Settings::self( m_bibtexFile );

            int item = m_headerMenu->insertItem( i18n( "Element Type" ), 0 );
            m_headerMenu->setItemChecked( item, settings->editing_MainListColumnsWidth[ 0 ] > 0 );
            m_headerMenu->insertSeparator();

            for ( int i = 0; i <= ( int ) BibTeX::EntryField::ftYear - ( int ) BibTeX::EntryField::ftAbstract; i++ )
            {
                BibTeX::EntryField::FieldType fieldType = ( BibTeX::EntryField::FieldType )( i + ( int ) BibTeX::EntryField::ftAbstract );
                TQString label = Settings::fieldTypeToI18NString( fieldType );
                item = m_headerMenu->insertItem( label, ( int ) fieldType + 2 );
                m_headerMenu->setItemChecked( item, settings->editing_MainListColumnsWidth[ i + 2 ] > 0 );
            }
        }
    }

    void DocumentListView::deleteSelected()
    {
        TQListViewItemIterator it( this, TQListViewItemIterator::Selected | TQListViewItemIterator::Visible );
        if ( it.current() == NULL ) return;

        TQListViewItem *above = it.current() ->itemAbove();
        TQValueList<DocumentListViewItem*> toBeDeleted;
        while ( it.current() )
        {
            DocumentListViewItem * kblvi = dynamic_cast<DocumentListViewItem*>( it.current() );
            toBeDeleted.append( kblvi );
            it++;
        }

        for ( TQValueList<DocumentListViewItem*>::Iterator it = toBeDeleted.begin(); it != toBeDeleted.end(); ++it )
        {
            m_bibtexFile->deleteElement(( *it )->element() );
            takeItem( *it );
            delete( *it );
        }

        if ( above )
            ensureItemVisible( above );

        emit modified();
    }

    const TQValueList<BibTeX::Element*> DocumentListView::selectedItems()
    {
        TQValueList<BibTeX::Element*> result;

        TQListViewItemIterator it( this, TQListViewItemIterator::Selected );
        while ( it.current() )
        {
            DocumentListViewItem * kblvi = dynamic_cast<DocumentListViewItem*>( it.current() );
            if ( kblvi->isVisible() )
                result.append( kblvi->element() );
            it++;
        }

        return result;
    }

    TQString DocumentListView::selectedToBibTeXText()
    {
        BibTeX::FileExporterBibTeX *exporter = new BibTeX::FileExporterBibTeX();
        exporter->setEncoding( "latex" );

        TQBuffer buffer;
        buffer.open( IO_WriteOnly );
        TQValueList<BibTeX::Element*> selectedElements = selectedItems();
        for ( TQValueList<BibTeX::Element*>::iterator it = selectedElements.begin(); it != selectedElements.end(); ++it )
            exporter->save( &buffer, *it );
        buffer.close();
        delete exporter;

        buffer.open( IO_ReadOnly );
        TQTextStream in( &buffer );
        in.setEncoding( TQTextStream::UnicodeUTF8 );
        TQString result = in.read();
        buffer.close();

        return result;
    }

    TQString DocumentListView::selectedToBibTeXRefs()
    {
        TQString refs;
        TQValueList<BibTeX::Element*> selectedElements = selectedItems();
        for ( TQValueList<BibTeX::Element*>::iterator it = selectedElements.begin(); it != selectedElements.end(); ++it )
        {
            BibTeX::Entry *entry = dynamic_cast<BibTeX::Entry*>( *it );
            if ( entry == NULL ) continue;

            if ( !refs.isEmpty() )
                refs.append( "," );
            refs.append( entry->id() );
        }
        return TQString( "\\cite{%1}" ).arg( refs );
    }

    void DocumentListView::copy()
    {
        kapp->clipboard() ->setText( selectedToBibTeXText() );
    }

    void DocumentListView::copyReferences()
    {
        kapp->clipboard() ->setText( selectedToBibTeXRefs() );
    }

    void DocumentListView::cut()
    {
        copy();
        deleteSelected();
    }

    bool DocumentListView::paste()
    {
        DocumentListViewItem * dlvi =  dynamic_cast<KBibTeX::DocumentListViewItem *>( selectedItem() );
        if ( dlvi == NULL )
            dlvi = dynamic_cast<KBibTeX::DocumentListViewItem *>( currentItem() );

        TQString clipboardText = kapp->clipboard() ->text();
        return paste( clipboardText, dlvi );
    }

    bool DocumentListView::paste( const TQString& text, DocumentListViewItem *at )
    {
        Settings * settings = Settings::self( m_bibtexFile );

        /** check if clipboard contains BibTeX content */
        if ( BibTeX::FileImporterBibTeX::guessCanDecode( text ) )
        {
            BibTeX::FileImporter *importer = new BibTeX::FileImporterBibTeX( settings->editing_FirstNameFirst );
            BibTeX::File *clipboardData = importer->load( text );
            delete importer;

            if ( clipboardData != NULL )
            {
                insertItems( clipboardData, at );
                delete clipboardData;
                return true;
            }
            else
                return false;
        }
        else if ( settings->external_xml2bibAvailable && settings->external_end2xmlAvailable && BibTeX::FileImporterBibUtils::guessCanDecode( text ) )
        {
            Settings * settings = Settings::self( m_bibtexFile );
            BibTeX::File::FileFormat inputFormat = BibTeX::FileImporterBibUtils::guessInputFormat( text );
            BibTeX::FileImporter *importer = NULL;
            if ( inputFormat == BibTeX::File::formatRIS && !settings->fileIO_useBibUtils )
                importer = new BibTeX::FileImporterRIS();
            else
                importer = new BibTeX::FileImporterBibUtils( inputFormat );
            BibTeX::File *clipboardData = importer->load( text );
            delete importer;

            if ( clipboardData != NULL )
            {
                insertItems( clipboardData, at );
                delete clipboardData;
                return true;
            }
            else
                return false;
        }
        else if ( BibTeX::FileImporterRIS::guessCanDecode( text ) )
        {
            BibTeX::FileImporter *importer = new BibTeX::FileImporterRIS( );
            BibTeX::File *clipboardData = importer->load( text );
            delete importer;

            if ( clipboardData != NULL )
            {
                insertItems( clipboardData, at );
                delete clipboardData;
                return true;
            }
            else
                return false;
        }
        else
        {
            /** Decoding the paste text as bibtex failed. Maybe the user wants
                to paste the text as link address, abstract, etc... */
            if ( !at ) // no list view item selected to add data to
                return false;

            // fetch BibTeX element from current list view item
            BibTeX::Entry * element = dynamic_cast<BibTeX::Entry*>( at->element() );
            if ( ! element )
                return false;

            // build popup menu
            TDEPopupMenu * popup = new TDEPopupMenu( this, "pastePopup" );
            popup->insertTitle( i18n( "Paste text as..." ) );
            for ( int i = ( int ) BibTeX::EntryField::ftAuthor; i <= ( int ) BibTeX::EntryField::ftYear; i++ )
            {
                BibTeX::EntryField::FieldType ft = ( BibTeX::EntryField::FieldType ) i;
                popup->insertItem( Settings::fieldTypeToI18NString( ft ), i );
            }
            popup->insertSeparator();
            TQIconSet cancelPixmap = TDEGlobal::iconLoader() ->loadIconSet( "cancel", TDEIcon::Small );
            int cancelId = popup->insertItem( cancelPixmap, i18n( "Cancel" ) );

            // show popup menu
            int selectedId = popup->exec( TQCursor::pos() );
            if ( selectedId == cancelId || selectedId == -1 )
                return false; // cancel menu

            // determine field to add clipboard value to
            BibTeX::EntryField::FieldType fieldType = ( BibTeX::EntryField::FieldType ) selectedId;
            BibTeX::EntryField * field = element->getField( fieldType );
            if ( field == NULL )
            {
                field = new BibTeX::EntryField( fieldType );
                element->addField( field );
            }
            else if ( field->value() != NULL )
                delete field->value();

            TQString encodedText = BibTeX::EncoderLaTeX::currentEncoderLaTeX() ->encode( text );

            // create new value from clipboard's content
            BibTeX::Value * value = new BibTeX::Value();
            if ( fieldType == BibTeX::EntryField::ftAuthor || fieldType == BibTeX::EntryField::ftEditor )
            {
                Settings * settings = Settings::self( m_bibtexFile );
                value->items.append( new BibTeX::PersonContainer( encodedText, settings->editing_FirstNameFirst ) );
            }
            else if ( fieldType == BibTeX::EntryField::ftKeywords )
                value->items.append( new BibTeX::KeywordContainer( encodedText ) );
            else
                value->items.append( new BibTeX::PlainText( encodedText ) );

            field->setValue( value );

            return true;
        }
    }

    void DocumentListView::selectAll()
    {
        TQListView::selectAll( true );
    }

    /*        void DocumentListView::sendSelectedToLyx()
        {
            TQStringList refsToSend;
            TQListViewItemIterator it( this, TQListViewItemIterator::Selected );
            while ( it.current() )
            {
                DocumentListViewItem * kblvi = dynamic_cast<DocumentListViewItem*>( it.current() );
                BibTeX::Entry *entry = dynamic_cast<BibTeX::Entry*>( kblvi->element() );
                if ( entry != NULL && kblvi->isVisible() )
                    refsToSend.append( entry->id() );
                it++;
            }

            Settings * settings = Settings::self( m_bibtexFile );
            TQString lyxPipeFilename = settings->detectLyXInPipe();
            kdDebug() << "sendSelectedToLyx: lyxPipeFilename= " << lyxPipeFilename << endl;
            TQFile pipe( lyxPipeFilename );
            if ( pipe.exists() && pipe.open( IO_WriteOnly ) )
            {
                TQTextStream * writer = new TQTextStream( &pipe );
                TQString msg = "LYXCMD:kbibtex:citation-insert:" + refsToSend.join( "," );
                *writer << msg << endl;
                delete writer;
                pipe.close();
            }
            else
                KMessageBox::error( this, ( lyxPipeFilename.isEmpty() ? i18n( "Cannot establish a link to LyX" ) : TQString( i18n( "Cannot establish a link to LyX using the pipe \"%1\"" ) ).arg( lyxPipeFilename ) ) + i18n( "\nMaybe LyX is not running?" ), i18n( "Error communicating with LyX" ) );
        }*/

    void DocumentListView::slotDoubleClick( TQListViewItem *item )
    {
        DocumentListViewItem *dlvi = dynamic_cast<DocumentListViewItem*>( item );
        if ( dlvi != NULL ) emit executed( dlvi );
    }

    void DocumentListView::filter( const TQString & text, BibTeX::Element::FilterType filterType, BibTeX::EntryField::FieldType fieldType )
    {
        m_filter = text;
        m_filterType = filterType;
        m_filterFieldType = fieldType;
        updateVisiblity();
    }

    void DocumentListView::setReadOnly( bool isReadOnly )
    {
        m_isReadOnly = isReadOnly;
    }

    void DocumentListView::activateShowColumnMenu( int id )
    {
        if ( id >= 0 )
        {
            if ( columnWidth( id ) > 0 )
            {
                hideColumn( id );
                m_headerMenu->setItemChecked( id, false );
            }
            else
            {
                showColumn( id );
                m_headerMenu->setItemChecked( id, true );
            }
        }
    }

    void DocumentListView::showBibtexListContextMenu( TDEListView *, TQListViewItem *, const TQPoint & p )
    {
        if ( m_contextMenu != NULL )
        {
            emit selectionChanged();
            m_contextMenu->popup( p );
        }
    }

    void DocumentListView::setSortingColumn( int column )
    {
        Settings * settings = Settings::self( m_bibtexFile );
        settings->editing_MainListSortingColumn = column;
        settings->editing_MainListSortingOrder = ( sortOrder() == TQt::Ascending ) ? 1 : -1;
    }

    bool DocumentListView::acceptDrag( TQDropEvent * event ) const
    {
        if ( event->source() == this ) return false;
        return TQTextDrag::canDecode( event ) || TQUriDrag::canDecode( event );
    }

    void DocumentListView::startDrag()
    {
        Settings * settings = Settings::self( m_bibtexFile );
        TQDragObject *d = new TQTextDrag( settings->editing_DragAction == Settings::COPYREFERENCE ? selectedToBibTeXRefs() : selectedToBibTeXText(), this );
        d->dragCopy();
    }
    void DocumentListView::saveColumnIndex()
    {
        Settings * settings = Settings::self( m_bibtexFile );
        TQHeader *hdr = header();

        for ( int i = 0; i < columns(); i++ )
            settings->editing_MainListColumnsIndex[ i ] = hdr->mapToIndex( i );
    }

    void DocumentListView::restoreColumnIndex()
    {
        Settings * settings = Settings::self( m_bibtexFile );
        TQHeader *hdr = header();

        for ( int i = 0; i < columns(); i++ )
            hdr->moveSection( i, settings->editing_MainListColumnsIndex[ i ] );
    }

    void DocumentListView::saveColumnWidths( int col )
    {
        Settings * settings = Settings::self( m_bibtexFile );

        int from = col == -1 ? 0 : col, to = col == -1 ? columns() : ( col + 1 );

        for ( int i = from; i < to; i++ )
        {
            if ( columnWidthMode( i ) == TQListView::Manual )
                settings->editing_MainListColumnsWidth[ i ] = columnWidth( i );
            else
                settings->editing_MainListColumnsWidth[ i ] = 0xffff;
        }
    }

    void DocumentListView::restoreColumnWidths()
    {
        Settings * settings = Settings::self( m_bibtexFile );

        for ( int col = 0; col < columns(); col++ )
        {
            int colWidth = settings->editing_MainListColumnsWidth[ col ];
            showColumn( col, colWidth );
        }
    }

    void DocumentListView::restoreSortingColumn()
    {
        Settings * settings = Settings::self( m_bibtexFile );
        setSortColumn( settings->editing_MainListSortingColumn );
        setSortOrder( settings->editing_MainListSortingOrder > 0 ? TQt::Ascending : TQt::Descending );
    }

    void DocumentListView::makeNewItemsUnread()
    {
        for ( TQValueList<DocumentListViewItem*>::ConstIterator it = m_unreadItems.begin() ; it != m_unreadItems.end(); ++it )
        {
            ( *it ) ->setUnreadStatus( false );
            ( *it ) ->repaint();
        }

        m_unreadItems.clear();
    }

    void DocumentListView::slotDropped( TQDropEvent * event, TQListViewItem * item )
    {
        TQString text;
        TQStrList urlList;

        if ( TQTextDrag::decode( event, text ) && KURL( text ).isValid() )
            urlList.append( text.utf8() );

        if ( !urlList.isEmpty() || TQUriDrag::decode( event, urlList ) )
        {
            TQString url = urlList.at( 0 );
            TQString tmpFile;
            if ( ! TDEIO::NetAccess::download( url, tmpFile, 0 ) )
            {
                KMessageBox::error( this, TDEIO::NetAccess::lastErrorString() );
                return ;
            }
            TQFile f( tmpFile );
            if ( ! f.open( IO_ReadOnly ) )
            {
                KMessageBox::error( this, f.errorString() );
                TDEIO::NetAccess::removeTempFile( tmpFile );
                return ;
            }
            TQByteArray ba = f.readAll();
            text = TQString( ba );
            f.close();
            TDEIO::NetAccess::removeTempFile( tmpFile );
        }
        else if ( !TQTextDrag::decode( event, text ) )
            return;

        event->accept( true );
        DocumentListViewItem * dlvi = dynamic_cast<KBibTeX::DocumentListViewItem *>( item );

        paste( text, dlvi );
    }

    bool DocumentListView::eventFilter( TQObject * watched, TQEvent * e )
    {
        if ( watched == header() )
        {
            switch ( e->type() )
            {
            case TQEvent::MouseButtonPress:
                {
                    if ( static_cast<TQMouseEvent *>( e ) ->button() == RightButton && m_headerMenu != NULL )
                        m_headerMenu->popup( TQCursor::pos() );

                    break;
                }

            default:
                break;
            }
        }

        return TDEListView::eventFilter( watched, e );
    }

    void DocumentListView::keyPressEvent( TQKeyEvent *e )
    {
        if ( e->key() == TQKeyEvent::Key_Enter || e->key() == TQKeyEvent::Key_Return )
        {
            DocumentListViewItem *item = dynamic_cast<DocumentListViewItem*>( selectedItem() );
            if ( item == NULL )
                item = dynamic_cast<DocumentListViewItem*>( currentItem() );
            if ( item != NULL )
                emit executed( item );
        }
        else
            TDEListView::keyPressEvent( e );
    }

    void DocumentListView::showColumn( int col, int colWidth )
    {
        if ( colWidth == 0xffff )
        {
            adjustColumn( col );
            if ( columnWidth( col ) > width() / 3 )
                colWidth = width() / 4;
            if ( columnWidth( col ) < width() / 12 )
                colWidth = width() / 8;
        }

        if ( colWidth < 0xffff )
            setColumnWidth( col, colWidth );

        header() ->setResizeEnabled( colWidth > 0, col );
        setColumnWidthMode( col, colWidth < 0xffff ? TQListView::Manual : TQListView::Maximum );
        saveColumnWidths( col );
    }

    void DocumentListView::hideColumn( int col )
    {
        showColumn( col, 0 );
    }

    void DocumentListView::buildColumns()
    {
        addColumn( i18n( "Element Type" ) );
        addColumn( i18n( "Entry Id" ) );

        for ( int i = 0; i <= ( int ) BibTeX::EntryField::ftYear - ( int ) BibTeX::EntryField::ftAbstract; i++ )
        {
            BibTeX::EntryField::FieldType fieldType = ( BibTeX::EntryField::FieldType )( i + ( int ) BibTeX::EntryField::ftAbstract );
            TQString label = Settings::fieldTypeToI18NString( fieldType );
            addColumn( label );
        }
    }
}

#include "documentlistview.moc"
