/***************************************************************************
*   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.             *
***************************************************************************/
#include <qtimer.h>
#include <qheader.h>
#include <qwidget.h>
#include <qlayout.h>
#include <qtooltip.h>
#include <qframe.h>
#include <qwidgetstack.h>
#include <qlabel.h>
#include <qcheckbox.h>
#include <qspinbox.h>
#include <qapplication.h>
#include <qeventloop.h>
#include <qbuffer.h>

#include <klocale.h>
#include <kcombobox.h>
#include <kiconloader.h>
#include <kdebug.h>
#include <kurllabel.h>
#include <klineedit.h>
#include <kapplication.h>
#include <kpushbutton.h>
#include <kprogress.h>
#include <kcompletion.h>
#include <kmessagebox.h>
#include <kconfig.h>
#include <kwin.h>

#include <settings.h>
#include <idsuggestions.h>
#include <entrywidget.h>
#include <webqueryarxiv.h>
#include <webquerybibsonomy.h>
#include <webquerycsb.h>
#include <webquerycitebase.h>
#include <webqueryciteseerx.h>
#include <webquerydblp.h>
#include <webquerygooglescholar.h>
#include <webqueryieeexplore.h>
#include <webquerymathscinet.h>
#include <webquerypubmed.h>
#include <webquerysciencedirect.h>
#include <webqueryspireshep.h>
#ifdef HAVE_YAZ
#include <webqueryz3950.h>
#endif // HAVE_YAZ
#include <webqueryzmath.h>
#include "webquery.h"

#define min(a,b) ((a)>(b)?(b):(a))

namespace KBibTeX
{
    WebQueryWidget::WebQueryWidget( QWidget *parent, const char *name )
            : QWidget( parent, name ), lineEditQuery( NULL ), spinBoxMaxHits( NULL )
    {
// nothing
    }

    bool WebQueryWidget::searchPossible()
    {
        return lineEditQuery != NULL && !lineEditQuery->text().stripWhiteSpace().replace( '$', "" ).isEmpty();
    }

    void WebQueryWidget::init()
    {
        QVBoxLayout *vLayout = new QVBoxLayout( this, 0, KDialog::spacingHint() );

        QHBoxLayout *hLayout = new QHBoxLayout( );
        vLayout->addLayout( hLayout );

        KPushButton *clearSearchText = new KPushButton( this );
        clearSearchText->setIconSet( QIconSet( SmallIcon( "locationbar_erase" ) ) );
        hLayout->addWidget( clearSearchText );
        QLabel *label = new QLabel( i18n( "Search &term:" ), this );
        hLayout->addWidget( label );
        lineEditQuery = new KLineEdit( this );
        hLayout->addWidget( lineEditQuery );
        label->setBuddy( lineEditQuery );
        hLayout->addSpacing( KDialog::spacingHint() * 2 );
        connect( clearSearchText, SIGNAL( clicked() ), lineEditQuery, SLOT( clear() ) );
        connect( lineEditQuery, SIGNAL( textChanged( const QString& ) ), this, SLOT( slotTextChanged( const QString& ) ) );
        hLayout->setStretchFactor( lineEditQuery, 4 );
        KCompletion *completionQuery = lineEditQuery->completionObject();

        label = new QLabel( i18n( "&Number of results:" ), this );
        hLayout->addWidget( label );
        spinBoxMaxHits = new QSpinBox( 1, 250, 1, this );
        spinBoxMaxHits->setValue( 10 );
        hLayout->addWidget( spinBoxMaxHits );
        label->setBuddy( spinBoxMaxHits );

        vLayout->addStretch( 0 );

        connect( lineEditQuery, SIGNAL( returnPressed() ), this, SIGNAL( startSearch() ) );
        connect( lineEditQuery, SIGNAL( returnPressed( const QString& ) ), completionQuery, SLOT( addItem( const QString& ) ) );
    }

    void WebQueryWidget::slotTextChanged( const QString& text )
    {
        slotTextChanged( text, false );
    }

    void WebQueryWidget::slotTextChanged( const QString& text, bool delayed )
    {
        bool doEnable = !text.stripWhiteSpace().replace( '$', "" ).isEmpty();
        if ( delayed && doEnable )
            QTimer::singleShot( 100, this, SLOT( slotEnableSearchTrue() ) );
        else if ( !delayed )
            emit enableSearch( doEnable );
    }

    void WebQueryWidget::slotEnableSearchTrue()
    {
        emit enableSearch( true );
    }

    WebQuery::WebQuery( QWidget *parent ): QObject(), m_parent( parent ), m_progressDialog( NULL ), m_currentJob( NULL )
    {
// nothing
    }

    WebQuery::~WebQuery()
    {
        if ( m_progressDialog != NULL )
            delete m_progressDialog;
    }

    void WebQuery::query()
    {
        if ( m_progressDialog != NULL )
            delete m_progressDialog;
        m_aborted = false;
        m_progressDialog = new KProgressDialog( m_parent, "WebQuery_progressDialog", i18n( "Searching" ), QString( i18n( "Searching %1" ) ).arg( title() ) );
        m_progressDialog->progressBar()->setMinimumWidth( 256 );
        m_progressDialog->setAutoClose( true );
        m_progressDialog->setMinimumDuration( 10 );
        m_progressDialog->setEnabled( true );
        connect( m_progressDialog, SIGNAL( cancelClicked() ), this, SLOT( slotCancelQuery() ) );
    }

    void WebQuery::cancelQuery()
    {
        // nothing
    }

    void WebQuery::slotCancelQuery()
    {
        m_aborted = true;
        cancelQuery();
    }

    void WebQuery::setEndSearch( WebQuery::Status status )
    {
        if ( m_progressDialog != NULL )
            m_progressDialog->hide();
        emit endSearch( status );
    }

    void WebQuery::setNumStages( int numStages )
    {
        m_currentStage = 0;
        m_numStages = numStages;
        m_progressDialog->progressBar()->setTotalSteps( m_numStages * 100 );
    }

    void WebQuery::enterNextStage()
    {
        ++m_currentStage;
        if ( m_progressDialog != NULL )
            m_progressDialog->progressBar()->setProgress( m_currentStage * 100 );
    }

    QString WebQuery::download( const KURL& url )
    {
        QString data = downloadHTML( url );
        if ( data == QString::null )
            return QString::null;

        /** post-processing */
        if ( data != QString::null )
        {
            data.replace( QRegExp( "</?(p|br)[^>]*>" ), "\n" );
            data.replace( QRegExp( "</?[^>]*>" ), "" );
            data.replace( "@import", "" );/// JavaScript import?
        }

        return data;
    }

    QString WebQuery::downloadHTML( const KURL& url )
    {
        if ( m_currentJob != NULL ) return QString::null;

        qDebug( "WebQuery::download( %s )", url.prettyURL().latin1() );

        m_incomingData = "";
        m_currentJobTotalSize = -1;
        m_currentJob = KIO::get( url, false, false );
        connect( m_currentJob, SIGNAL( totalSize( KIO::Job*, KIO::filesize_t ) ), this, SLOT( slotSetJobTotalSize( KIO::Job*, KIO::filesize_t ) ) );
        connect( m_currentJob, SIGNAL( processedSize( KIO::Job*, KIO::filesize_t ) ), this, SLOT( slotSetJobProcessedSize( KIO::Job*, KIO::filesize_t ) ) );
        connect( m_currentJob, SIGNAL( data( KIO::Job*, const QByteArray & ) ), this, SLOT( slotJobData( KIO::Job*, const QByteArray & ) ) );
        connect( m_currentJob, SIGNAL( result( KIO::Job* ) ), this, SLOT( slotJobFinished( KIO::Job* ) ) );

        qApp->eventLoop()->enterLoop();

        return m_incomingData;
    }

    BibTeX::File *WebQuery::downloadBibTeXFile( const KURL& url, QTextStream::Encoding encoding )
    {
        QString data = download( url );
        if ( data == QString::null )
            return NULL;

        BibTeX::FileImporterBibTeX importer( FALSE );
        importer.setIgnoreComments( TRUE );
        QBuffer buffer;

        buffer.open( IO_WriteOnly );
        QTextStream ts( &buffer );
        ts.setEncoding( encoding );
        ts << data << endl;
        buffer.close();

        buffer.open( IO_ReadOnly );
        BibTeX::File *result = importer.load( &buffer );
        buffer.close();

        return result;
    }

    void WebQuery::slotSetJobTotalSize( KIO::Job *job, KIO::filesize_t size )
    {
        if ( job != m_currentJob ) return;
        m_currentJobTotalSize = size;
    }

    void WebQuery::slotSetJobProcessedSize( KIO::Job *job, KIO::filesize_t size )
    {
        if ( job != m_currentJob ) return;
        if ( m_currentJobTotalSize <= 0 ) m_currentJobTotalSize = size;
        m_progressDialog->progressBar()->setProgress( m_currentStage * 100 + min( 100, size * 100 / m_currentJobTotalSize ) );
    }

    void WebQuery::slotJobData( KIO::Job *job, const QByteArray &data )
    {
        if ( job != m_currentJob ) return;
        QCString dataStr = QCString( data, data.size() + 1 );
        if ( data.size() > 0 )
            m_incomingData.append( dataStr );
    }

    void WebQuery::slotJobFinished( KIO::Job *job )
    {
        if ( job != m_currentJob ) return;
        m_currentJob = NULL;
        if ( job->error() )
        {
            job->showErrorDialog();
            m_incomingData = QString::null;
        }
        enterNextStage();
        qApp->eventLoop()->exitLoop();
    }

    WebQueryWizard::WebQueryWizard( KDialogBase *dlg, const char* name ) : QWidget( dlg, name ), m_dlg( dlg ), m_pushButtonSearch( NULL )
    {
        setupGUI( );

        Settings *settings = Settings::self( NULL );
        m_comboBoxEngines->setCurrentItem( settings->webQuery_LastEngine );
        otherEngineSelected( settings->webQuery_LastEngine );
        m_checkBoxImportAll->setChecked( settings->webQuery_ImportAll );
        m_pushButtonSearch->setEnabled( false );
    }

    WebQueryWizard::~WebQueryWizard()
    {
        KConfig * config = kapp->config();
        config->setGroup( "WebQueryWizard" );
        saveWindowSize( config );
    }

    void WebQueryWizard::showEvent( QShowEvent * )
    {
        KConfig * config = kapp->config();
        config->setGroup( "WebQueryWizard" );
        restoreWindowSize( config );
    }

    int WebQueryWizard::execute( QWidget *parent, QValueList<BibTeX::Entry*> &results )
    {
        KDialogBase *dlg = new KDialogBase( parent, "WebQueryWizard", true, i18n( "Import" ), KDialogBase::Ok | KDialogBase::Cancel, ( KDialogBase::ButtonCode )0, true );
        WebQueryWizard *wiz = new WebQueryWizard( dlg, "WebQueryWizard" );
        dlg->setButtonOK( KGuiItem( i18n( "&Import" ), "import", i18n( "Import selected items" ) ) );
        dlg->setMainWidget( wiz );
        connect( wiz, SIGNAL( changeButtonOK( bool ) ), dlg, SLOT( enableButtonOK( bool ) ) );
        dlg->enableButtonOK( false );

        results.clear();
        int result = dlg->exec();
        if ( result == QDialog::Accepted )
        {
            QListViewItemIterator it = wiz->m_checkBoxImportAll->isChecked() ? QListViewItemIterator( wiz->m_listViewResults ) : QListViewItemIterator( wiz->m_listViewResults, QListViewItemIterator::Selected );
            while ( it.current() )
            {
                ResultsListViewItem *item = dynamic_cast<ResultsListViewItem*>( it.current() );
                results.append( new BibTeX::Entry( item->entry() ) );
                ++it;
            }
        }

        Settings *settings = Settings::self( NULL );
        settings->webQuery_LastEngine = wiz->m_comboBoxEngines->currentItem();
        settings->webQuery_ImportAll = wiz->m_checkBoxImportAll->isChecked();

        delete dlg;

        return result;
    }

    void WebQueryWizard::previewEntry( QListViewItem *item )
    {
        ResultsListViewItem *rlvi = dynamic_cast<ResultsListViewItem*>( item );
        if ( rlvi != NULL )
        {
            BibTeX::Entry *entry = rlvi->entry();
            KBibTeX::EntryWidget::execute( entry, NULL, TRUE, FALSE );
        }
    }

    void WebQueryWizard::importEnableChanging( )
    {
        QListViewItemIterator it( m_listViewResults, QListViewItemIterator::Selected );

        emit changeButtonOK(( m_checkBoxImportAll->isChecked() && m_listViewResults->childCount() > 0 ) || it.current() != NULL );
    }

    void WebQueryWizard::otherEngineSelected( int index )
    {
        if ( index < 0 || index >= ( int )m_webQueries.size() ) return;

        m_pushButtonSearch->setCaption( QString( i18n( "Search %1" ) ).arg( m_webQueries[index]->title() ) );
        m_disclaimerLabel->setText( m_webQueries[index]->disclaimer() );
        m_disclaimerLabel->setURL( m_webQueries[index]->disclaimerURL() );
        QToolTip::remove( m_disclaimerLabel );
        QToolTip::add( m_disclaimerLabel, m_webQueries[index]->disclaimerURL() );
        m_widgetStackQueries->raiseWidget( m_webQueries[index]->widget() );
        m_pushButtonSearch->setEnabled( m_webQueries[index]->widget()->searchPossible() );
    }

    void WebQueryWizard::startSearch()
    {
        if ( !m_pushButtonSearch->isEnabled() )
        {
            kdDebug() << "WebQueryWizard::startSearch not enabled" << endl;
            return;
        }

        int index = m_comboBoxEngines->currentItem();

        setEnabled( FALSE );
        m_dlg->enableButtonCancel( FALSE );
        QApplication::setOverrideCursor( Qt::waitCursor );
        m_listViewResults->clear();
        connect( m_webQueries[index], SIGNAL( foundEntry( BibTeX::Entry*, bool ) ), this, SLOT( addHit( BibTeX::Entry*, bool ) ) );
        connect( m_webQueries[index], SIGNAL( endSearch( WebQuery::Status ) ), this, SLOT( endSearch( WebQuery::Status ) ) );

        m_webQueries[index]->query();
    }

    void WebQueryWizard::endSearch( WebQuery::Status status )
    {
        int index = m_comboBoxEngines->currentItem();
        disconnect( m_webQueries[index], SIGNAL( foundEntry( BibTeX::Entry*, bool ) ), this, SLOT( addHit( BibTeX::Entry*, bool ) ) );
        disconnect( m_webQueries[index], SIGNAL( endSearch( WebQuery::Status ) ), this, SLOT( endSearch( WebQuery::Status ) ) );
        setEnabled( TRUE );
        m_dlg->enableButtonCancel( TRUE );
        importEnableChanging();
        QApplication::restoreOverrideCursor();
        if ( status == WebQuery::statusInsufficientPermissions )
            KMessageBox::sorry( this, i18n( "You do not have the necessary permissions to query data from this service." ) );
    }

    void WebQueryWizard::addHit( BibTeX::Entry *entry, bool keepId )
    {
        Settings * settings = Settings::self();
        if ( !keepId && settings->idSuggestions_default >= 0 )
            entry->setId( IdSuggestions::createDefaultSuggestion( NULL, entry ) );
        new ResultsListViewItem( m_listViewResults, new BibTeX::Entry( entry ) );
    }

    void WebQueryWizard::enableSearch( bool enabled )
    {
        m_pushButtonSearch->setEnabled( enabled );
    }

    void WebQueryWizard::openURL( const QString& url )
    {
        Settings::openUrl( KURL( url ), this );
    }

    void WebQueryWizard::setupGUI()
    {
        Settings * settings = Settings::self();
        setMinimumSize( 640, 384 );
        QGridLayout *layout = new QGridLayout( this, 5, 4, 0, KDialog::spacingHint() );
        layout->setColStretch( 2, 1 );
        layout->setRowStretch( 3, 1 );

        QLabel *label = new QLabel( i18n( "&Engine:" ), this );
        layout->addWidget( label, 0, 0 );
        m_comboBoxEngines = new KComboBox( FALSE, this );
        label->setBuddy( m_comboBoxEngines );
        layout->addWidget( m_comboBoxEngines, 0, 1 );
        connect( m_comboBoxEngines, SIGNAL( activated( int ) ), this, SLOT( otherEngineSelected( int ) ) );

        m_widgetStackQueries = new QWidgetStack( this );
        layout->addMultiCellWidget( m_widgetStackQueries, 1, 2, 0, 2 );
        setupQueries();

        m_pushButtonSearch = new KPushButton( i18n( "&Search" ), this );
        layout->addWidget( m_pushButtonSearch, 0, 3 );
        m_pushButtonSearch->setIconSet( QIconSet( SmallIcon( "find" ) ) );
        m_pushButtonSearch->setEnabled( FALSE );

        m_listViewResults = new KListView( this );
        m_listViewResults->addColumn( i18n( "Year" ), 64 );
        m_listViewResults->addColumn( i18n( "Author" ), 128 );
        m_listViewResults->addColumn( i18n( "Title" ), 512 );
        if ( settings->editing_UseSpecialFont )
            m_listViewResults->setFont( settings->editing_SpecialFont );
        else
            m_listViewResults->setFont( KGlobalSettings::generalFont() );
        m_listViewResults->header() ->setFont( KGlobalSettings::generalFont() );
        m_listViewResults->setAllColumnsShowFocus( TRUE );
        m_listViewResults->setFullWidth( true );
        m_listViewResults->setSelectionMode( QListView::Extended );
        layout->addMultiCellWidget( m_listViewResults, 3, 3, 0, 3 );
        connect( m_listViewResults, SIGNAL( executed( QListViewItem* ) ), this, SLOT( previewEntry( QListViewItem* ) ) );
        connect( m_listViewResults, SIGNAL( returnPressed( QListViewItem* ) ), this, SLOT( previewEntry( QListViewItem* ) ) );

        QHBoxLayout *horizontalLayout = new QHBoxLayout();
        layout->addMultiCellLayout( horizontalLayout, 4, 4, 0, 3 );
        m_disclaimerLabel = new KURLLabel( this );
        horizontalLayout->addWidget( m_disclaimerLabel );
        horizontalLayout->setStretchFactor( m_disclaimerLabel, 4 );
        m_checkBoxImportAll = new QCheckBox( i18n( "Import all hits" ), this );
        m_checkBoxImportAll->setSizePolicy( QSizePolicy::Minimum, QSizePolicy::Minimum );
        horizontalLayout->addWidget( m_checkBoxImportAll );

        connect( m_disclaimerLabel, SIGNAL( leftClickedURL( const QString& ) ), this, SLOT( openURL( const QString& ) ) );
        connect( m_listViewResults, SIGNAL( selectionChanged( ) ), this, SLOT( importEnableChanging( ) ) );
        connect( m_listViewResults, SIGNAL( clicked( QListViewItem* ) ), this, SLOT( importEnableChanging( ) ) );
        connect( m_checkBoxImportAll, SIGNAL( toggled( bool ) ), this, SLOT( importEnableChanging( ) ) );
        connect( m_pushButtonSearch, SIGNAL( clicked() ), this, SLOT( startSearch() ) );
    }

    void WebQueryWizard::setupQueries()
    {
        WebQuery *query = new WebQueryArXiv( this );
        m_webQueries.append( query );
        //         query = new WebQueryAmatex( this );
        //         m_webQueries.append( query );
        query = new WebQueryBibSonomy( this );
        m_webQueries.append( query );
        query = new WebQueryCitebase( this );
        m_webQueries.append( query );
        query = new WebQueryCiteSeerX( this );
        m_webQueries.append( query );
        query = new WebQueryCSB( this );
        m_webQueries.append( query );
        query = new WebQueryDBLP( this );
        m_webQueries.append( query );
        query = new WebQueryGoogleScholar( this );
        m_webQueries.append( query );
        query = new WebQueryIEEExplore( this );
        m_webQueries.append( query );
        query = new WebQueryMathSciNet( this );
        m_webQueries.append( query );
        query = new WebQueryPubMed( this );
        m_webQueries.append( query );
        query = new WebQueryScienceDirect( this );
        m_webQueries.append( query );
        query = new WebQuerySpiresHep( this );
        m_webQueries.append( query );
#ifdef HAVE_YAZ
        query = new WebQueryZ3950( this );
        m_webQueries.append( query );
#endif // HAVE_YAZ
        query = new WebQueryZMATH( this );
        m_webQueries.append( query );

        for ( QValueList<WebQuery*>::Iterator it = m_webQueries.begin(); it != m_webQueries.end(); ++it )
        {
            m_comboBoxEngines->insertItem(( *it )->title() );
            m_widgetStackQueries->addWidget(( *it )->widget() );
            connect(( *it )->widget(), SIGNAL( enableSearch( bool ) ), this, SLOT( enableSearch( bool ) ) );
            connect(( *it )->widget(), SIGNAL( startSearch() ), this, SLOT( startSearch() ) );
        }
    }

    /* This function was taken form KMainWindow of KDE 3.5 and modified to fit KBibTeX */
    void WebQueryWizard::saveWindowSize( KConfig *config ) const
    {
        int scnum = QApplication::desktop()->screenNumber( parentWidget() );
        QRect desk = QApplication::desktop()->screenGeometry( scnum );
        int w, h;
#if defined Q_WS_X11
        // save maximalization as desktop size + 1 in that direction
        KWin::WindowInfo info = KWin::windowInfo( m_dlg->winId(), NET::WMState );
        w = info.state() & NET::MaxHoriz ? desk.width() + 1 : m_dlg->width();
        h = info.state() & NET::MaxVert ? desk.height() + 1 : m_dlg->height();
#else
        if ( isMaximized() )
        {
            w = desk.width() + 1;
            h = desk.height() + 1;
        }
        //TODO: add "Maximized" property instead "+1" hack
#endif
        QRect size( desk.width(), w, desk.height(), h );
        bool defaultSize = false;//( size == d->defaultWindowSize );
        QString widthString = QString::fromLatin1( "Width %1" ).arg( desk.width() );
        QString heightString = QString::fromLatin1( "Height %1" ).arg( desk.height() );
        if ( !config->hasDefault( widthString ) && defaultSize )
            config->revertToDefault( widthString );
        else
            config->writeEntry( widthString, w );

        if ( !config->hasDefault( heightString ) && defaultSize )
            config->revertToDefault( heightString );
        else
            config->writeEntry( heightString, h );
    }

    /* This function was taken form KMainWindow of KDE 3.5 and modified to fit KBibTeX */
    void WebQueryWizard::restoreWindowSize( KConfig *config )
    {
        // restore the size
        int scnum = QApplication::desktop()->screenNumber( parentWidget() );
        QRect desk = QApplication::desktop()->screenGeometry( scnum );
        QSize size( config->readNumEntry( QString::fromLatin1( "Width %1" ).arg( desk.width() ), 0 ),
                    config->readNumEntry( QString::fromLatin1( "Height %1" ).arg( desk.height() ), 0 ) );
        if ( size.isEmpty() )
        {
            // try the KDE 2.0 way
            size = QSize( config->readNumEntry( QString::fromLatin1( "Width" ), 0 ),
                          config->readNumEntry( QString::fromLatin1( "Height" ), 0 ) );
            if ( !size.isEmpty() )
            {
                // make sure the other resolutions don't get old settings
                config->writeEntry( QString::fromLatin1( "Width" ), 0 );
                config->writeEntry( QString::fromLatin1( "Height" ), 0 );
            }
        }
        if ( !size.isEmpty() )
        {
#ifdef Q_WS_X11
            int state = ( size.width() > desk.width() ? NET::MaxHoriz : 0 )
                        | ( size.height() > desk.height() ? NET::MaxVert : 0 );
            if (( state & NET::Max ) == NET::Max )
                ; // no resize
            else if (( state & NET::MaxHoriz ) == NET::MaxHoriz )
                m_dlg->resize( width(), size.height() );
            else if (( state & NET::MaxVert ) == NET::MaxVert )
                m_dlg->resize( size.width(), height() );
            else
                m_dlg->resize( size );
            // QWidget::showMaximized() is both insufficient and broken
            KWin::setState( m_dlg->winId(), state );
#else
            if ( size.width() > desk.width() || size.height() > desk.height() )
                m_dlg->setWindowState( WindowMaximized );
            else
                m_dlg->resize( size );
#endif
        }
    }

    ResultsListViewItem::ResultsListViewItem( QListView * parent, BibTeX::Entry * entry ) : QListViewItem( parent ), m_entry( entry )
    {
        BibTeX::EntryField * field = entry->getField( BibTeX::EntryField::ftTitle );
        if ( field != NULL && field->value() != NULL )
            setText( 2, field ->value() ->text().replace( '{', "" ).replace( '}', "" ).replace( '~', ' ' ) );
        field = entry->getField( BibTeX::EntryField::ftAuthor );
        if ( field != NULL && field->value() != NULL )
        {
            BibTeX::PersonContainer* personContainer = dynamic_cast<BibTeX::PersonContainer*>( field->value()->items.first() );
            if ( personContainer != NULL )
            {
                QStringList authors;
                QValueList<BibTeX::Person*> list = personContainer->persons;
                for ( QValueList<BibTeX::Person*>::ConstIterator it = list.begin(); it != list.end(); ++it )
                    authors.append(( *it ) ->text() );
                setText( 1, authors.join( " and " ).replace( '{', "" ).replace( '}', "" ).replace( '~', ' ' ) );
            }
            else setText( 1, field ->value() ->text().replace( '{', "" ).replace( '}', "" ).replace( '~', ' ' ) );
        }
        field = entry->getField( BibTeX::EntryField::ftYear );
        if ( field != NULL && field->value() != NULL )
            setText( 0, field ->value() ->text().replace( '{', "" ).replace( '}', "" ).replace( '~', ' ' ) );
    }

    ResultsListViewItem::~ResultsListViewItem()
    {
        if ( m_entry != NULL )
            delete m_entry;
    }

    BibTeX::Entry* ResultsListViewItem::entry()
    {
        return m_entry;
    }

}
#include "webquery.moc"
