/***************************************************************************
*   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 <tqlayout.h>
#include <tqlabel.h>
#include <tqdir.h>
#include <tqheader.h>
#include <tqcombobox.h>
#include <tqslider.h>
#include <tqtooltip.h>
#include <tqwhatsthis.h>
#include <tqgroupbox.h>
#include <tqpushbutton.h>
#include <tqcheckbox.h>

#include <kpushbutton.h>
#include <kdirselectdialog.h>
#include <kiconloader.h>
#include <tdelocale.h>
#include <kurlrequester.h>
#include <tdemessagebox.h>
#include <klineedit.h>
#include <kdialog.h>
#include <tdefontdialog.h>
#include <kurlcompletion.h>

#include "documentlistview.h"
#include "settingsediting.h"

namespace KBibTeX
{
    const TQChar SettingsEditing::pathListSeparator = TQChar( ';' );

    SettingsEditingPaths::SettingsEditingPaths( TQStringList& pathList, TQWidget*parent, const char *name )
            : TQWidget( parent, name ), m_pathList( pathList )
    {
        TQGridLayout *layout = new TQGridLayout( this, 5, 3, 0, KDialog::spacingHint() );
        setMinimumWidth( 480 );

        TQLabel *label = new TQLabel( i18n( "Path to add:" ), this );
        layout->addWidget( label, 0, 0 );
        m_urlRequesterNewPath = new KURLRequester( this );
        m_urlRequesterNewPath->setMode( KFile::Directory | KFile::ExistingOnly | KFile::LocalOnly );
        m_urlRequesterNewPath->completionObject()->setDir( TQDir::currentDirPath() );
        label->setBuddy( m_urlRequesterNewPath );
        layout->addWidget( m_urlRequesterNewPath, 1, 0 );
        TQToolTip::add( m_urlRequesterNewPath->button(), i18n( "Select a path to add" ) );
        m_pushButtonAddDir = new KPushButton( i18n( "Add" ), this );
        m_pushButtonAddDir->setIconSet( TQIconSet( SmallIcon( "add" ) ) );
        m_pushButtonAddDir->setEnabled( false );
        TQToolTip::add( m_pushButtonAddDir, i18n( "Add chosen path to list" ) );
        layout->addWidget( m_pushButtonAddDir, 1, 2 );

        label = new TQLabel( i18n( "List of paths:" ), this );
        layout->addWidget( label, 2, 0 );
        m_listViewPathList = new TDEListView( this );
        m_listViewPathList->addColumn( i18n( "Path" ) );
        m_listViewPathList->header()->setClickEnabled( false );
        m_listViewPathList->setFullWidth( true );
        label->setBuddy( m_listViewPathList );
        layout->addMultiCellWidget( m_listViewPathList, 3, 4, 0, 1 );
        m_pushButtonDelDir = new KPushButton( i18n( "Delete" ), this );
        layout->addWidget( m_pushButtonDelDir, 3, 2 );
        m_pushButtonDelDir->setEnabled( false );
        m_pushButtonDelDir->setIconSet( TQIconSet( SmallIcon( "edit-delete" ) ) );
        TQToolTip::add( m_pushButtonDelDir, i18n( "Remove selected path from list" ) );

        layout->setRowStretch( 4, 1 );
        layout->setColStretch( 0, 1 );

        connect( m_urlRequesterNewPath, TQ_SIGNAL( textChanged( const TQString& ) ), this, TQ_SLOT( slotTextChanged( const TQString& ) ) );
        connect( m_urlRequesterNewPath, TQ_SIGNAL( urlSelected( const TQString& ) ), this, TQ_SLOT( slotTextChanged( const TQString& ) ) );
        connect( m_pushButtonAddDir, TQ_SIGNAL( clicked() ), this, TQ_SLOT( slotAddDir() ) );
        connect( m_listViewPathList, TQ_SIGNAL( selectionChanged() ), this, TQ_SLOT( slotSelectionChanged() ) );
        connect( m_pushButtonDelDir, TQ_SIGNAL( clicked() ), this, TQ_SLOT( slotDelDir() ) );

        for ( TQStringList::Iterator it = pathList.begin(); it != pathList.end(); ++it )
            new TQListViewItem( m_listViewPathList, *it );
    }

    bool SettingsEditingPaths::execute( TQWidget *parent, TQStringList &pathList )
    {
        KDialogBase *dlg = new KDialogBase( parent, "SettingsEditingPathsDialog", true, i18n( "Edit Document Search Paths" ), KDialogBase::Ok | KDialogBase::Cancel, KDialogBase::Ok, false );
        SettingsEditingPaths *sep = new SettingsEditingPaths( pathList, dlg, "SettingsEditingPaths" );
        dlg->setMainWidget( sep );
        connect( dlg, TQ_SIGNAL( apply() ), sep, TQ_SLOT( slotApply() ) );
        connect( dlg, TQ_SIGNAL( okClicked() ), sep, TQ_SLOT( slotApply() ) );

        bool result = dlg->exec() == TQDialog::Accepted;
        delete dlg;

        return result;
    }

    void SettingsEditingPaths::slotApply()
    {
        m_pathList.clear();
        TQListViewItem *item = m_listViewPathList->firstChild();
        while ( item != NULL )
        {
            m_pathList.append( item->text( 0 ) );
            item = item->nextSibling();
        }
    }

    void SettingsEditingPaths::slotTextChanged( const TQString&text )
    {
        TQDir pathObj( text );
        m_pushButtonAddDir->setEnabled( pathObj.exists() && pathObj.isReadable() );
    }

    void SettingsEditingPaths::slotAddDir()
    {
        TQString path = m_urlRequesterNewPath->lineEdit()->text();
        TQDir pathObj( path );
        if ( pathObj.exists() && pathObj.isReadable() )
        {
            TQListViewItem *item = new TDEListViewItem( m_listViewPathList, path );
            m_listViewPathList->ensureItemVisible( item );
            m_listViewPathList->setSelected( item, true );
            slotSelectionChanged();
        }
        else
            KMessageBox::error( this, TQString( i18n( "Folder '%1' does not exist or is not readable." ) ).arg( path ) );
    }

    void SettingsEditingPaths::slotSelectionChanged()
    {
        m_pushButtonDelDir->setEnabled( m_listViewPathList->selectedItem() != NULL );
    }

    void SettingsEditingPaths::slotDelDir()
    {
        m_listViewPathList->takeItem( m_listViewPathList->selectedItem() );
        slotSelectionChanged();
    }

    SettingsEditing::SettingsEditing( TQWidget *parent, const char *name )
            : TQWidget( parent, name ), m_findDuplicatesSensitivityMin( 3 ), m_findDuplicatesSensitivityMax( 13 )
    {
        TQGroupBox * group = NULL;
        TQVBoxLayout *layout = new TQVBoxLayout( this, 0, KDialog::spacingHint() );

        group = new TQGroupBox( 2, TQt::Horizontal, i18n( "Main List" ), this );
        layout->addWidget( group );
        TQLabel *label = new TQLabel( i18n( "&Sorting:" ), group );
        m_comboBoxSortingColumn = new TQComboBox( false, group );
        m_comboBoxSortingColumn->insertItem( i18n( "Element Type" ) );
        m_comboBoxSortingColumn->insertItem( 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 );
            m_comboBoxSortingColumn->insertItem( label );
        }
        label->setBuddy( m_comboBoxSortingColumn );

        label = new TQLabel( i18n( "So&rting order:" ), group );
        m_comboBoxSortingOrder = new TQComboBox( false, group );
        m_comboBoxSortingOrder->insertItem( i18n( "Ascending" ) );
        m_comboBoxSortingOrder->insertItem( i18n( "Descending" ) );
        label->setBuddy( m_comboBoxSortingOrder );

        label = new TQLabel( i18n( "&Double click action:" ), group );
        m_comboBoxDoubleClickAction = new TQComboBox( false, group );
        m_comboBoxDoubleClickAction->insertItem( i18n( "Edit element" ) );
        m_comboBoxDoubleClickAction->insertItem( i18n( "Open document" ) );
        label->setBuddy( m_comboBoxDoubleClickAction );

        label = new TQLabel( i18n( "On dragging with mouse:" ), group );
        m_comboBoxDragAction = new TQComboBox( false, group );
        m_comboBoxDragAction->insertItem( i18n( "Copy reference (\\cite{...})" ) );
        m_comboBoxDragAction->insertItem( i18n( "Copy BibTeX text (@article{...})" ) );
        label->setBuddy( m_comboBoxDragAction );

        group = new TQGroupBox( 1, TQt::Vertical, i18n( "Entry Editing" ), this );
        layout->addWidget( group );
        m_checkBoxEnableAllFields = new TQCheckBox( i18n( "Enable all &fields for editing" ), group );

        group = new TQGroupBox( 1, TQt::Vertical, i18n( "Search Bar" ), this );
        layout->addWidget( group );
        m_checkBoxSearchBarClearField = new TQCheckBox( i18n( "Reset field filter when changing filter text" ), group );

        group = new TQGroupBox( 2, TQt::Horizontal, i18n( "Presentation" ), this );
        layout->addWidget( group );
        m_checkBoxUseSpecialFont = new TQCheckBox( i18n( "Use special &font" ), group );
        m_pushButtonSpecialFont = new TQPushButton( group );
        label = new TQLabel( i18n( "Author and editor names:" ), group );
        m_comboBoxNameOrder = new TQComboBox( group );
        label->setBuddy( m_comboBoxNameOrder );
        m_comboBoxNameOrder->insertItem( i18n( "John Doe" ) );
        m_comboBoxNameOrder->insertItem( i18n( "Doe, John" ) );
        TQToolTip::add( m_comboBoxNameOrder, i18n( "Show names as 'John Doe' instead of 'Doe, John'" ) );
        TQWhatsThis::add( m_comboBoxNameOrder, i18n( "Show names as 'John Doe' instead of 'Doe, John'.\n\nTakes only effect after the next start of KBibTeX." ) );

        group = new TQGroupBox( 1, TQt::Vertical, i18n( "Document Search Paths" ), this );
        layout->addWidget( group );
        KPushButton *btnSelectDocumentSearchPath = new KPushButton( SmallIcon( "document-open" ), i18n( "Edit Search Paths" ), group );

        group = new TQGroupBox( 1, TQt::Vertical, i18n( "Find Duplicates" ), this );
        layout->addWidget( group );
        label = new TQLabel( i18n( "Sensitivity:" ), group );
        TQWidget *spacer = new TQWidget( group );
        spacer->setFixedSize( KDialog::spacingHint() * 3, KDialog::spacingHint() );
        TQLabel *label2 = new TQLabel( i18n( "Low" ), group );
        m_sliderBarFindDuplicatesSensitivity = new TQSlider( TQt::Horizontal, group );
        m_sliderBarFindDuplicatesSensitivity->setMinValue( m_findDuplicatesSensitivityMin );
        m_sliderBarFindDuplicatesSensitivity->setMaxValue( m_findDuplicatesSensitivityMax );
        m_sliderBarFindDuplicatesSensitivity->setLineStep( 1 );
        m_sliderBarFindDuplicatesSensitivity->setPageStep( 5 );
        label->setBuddy( m_sliderBarFindDuplicatesSensitivity );
        label2 = new TQLabel( i18n( "High" ), group );

        layout->addStretch();

        connect( m_checkBoxSearchBarClearField, TQ_SIGNAL( toggled( bool ) ), this, TQ_SLOT( slotConfigChanged() ) );
        connect( m_checkBoxEnableAllFields, TQ_SIGNAL( toggled( bool ) ), this, TQ_SLOT( slotConfigChanged() ) );
        connect( m_comboBoxDoubleClickAction, TQ_SIGNAL( activated( int ) ), this, TQ_SLOT( slotConfigChanged() ) );
        connect( m_comboBoxDragAction, TQ_SIGNAL( activated( int ) ), this, TQ_SLOT( slotConfigChanged() ) );
        connect( m_comboBoxSortingColumn, TQ_SIGNAL( activated( int ) ), this, TQ_SLOT( slotConfigChanged() ) );
        connect( m_comboBoxSortingOrder, TQ_SIGNAL( activated( int ) ), this, TQ_SLOT( slotConfigChanged() ) );
        connect( m_pushButtonSpecialFont, TQ_SIGNAL( clicked() ), this, TQ_SLOT( slotSelectSpecialFont() ) );
        connect( m_checkBoxUseSpecialFont, TQ_SIGNAL( toggled( bool ) ), m_pushButtonSpecialFont, TQ_SLOT( setEnabled( bool ) ) );
        connect( m_checkBoxUseSpecialFont, TQ_SIGNAL( toggled( bool ) ), this, TQ_SLOT( slotConfigChanged() ) );
        connect( btnSelectDocumentSearchPath, TQ_SIGNAL( clicked() ), this, TQ_SLOT( slotSelectDocumentSearchPath() ) );
    }


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

    void SettingsEditing::applyData()
    {
        Settings * settings = Settings::self();

        settings->editing_SearchBarClearField = m_checkBoxSearchBarClearField->isChecked();
        settings->editing_EnableAllFields = m_checkBoxEnableAllFields->isChecked();
        settings->editing_MainListSortingColumn = m_comboBoxSortingColumn->currentItem();
        settings->editing_MainListSortingOrder = m_comboBoxSortingOrder->currentItem() == 0 ? 1 : -1;
        settings->editing_MainListDoubleClickAction = m_comboBoxDoubleClickAction->currentItem();
        settings->editing_DragAction = m_comboBoxDragAction->currentItem() == 0 ? Settings::COPYREFERENCE : Settings::COPYBIBTEX;

        settings->editing_UseSpecialFont = m_checkBoxUseSpecialFont->isChecked();
        settings->editing_SpecialFont = m_specialFont;

        settings->editing_FirstNameFirst = m_comboBoxNameOrder->currentItem() == 0;

        settings->editing_DocumentSearchPaths.clear();
        for ( TQStringList::Iterator it = m_documentSearchPaths.begin(); it != m_documentSearchPaths.end(); ++it )
            settings->editing_DocumentSearchPaths.append( *it );

        settings->editing_findDuplicatesSensitivity = ( m_findDuplicatesSensitivityMin + m_findDuplicatesSensitivityMax ) - m_sliderBarFindDuplicatesSensitivity->value();
    }

    void SettingsEditing::readData()
    {
        Settings * settings = Settings::self();

        m_checkBoxSearchBarClearField->setChecked( settings->editing_SearchBarClearField );
        m_checkBoxEnableAllFields->setChecked( settings->editing_EnableAllFields );
        m_comboBoxSortingColumn->setCurrentItem( settings->editing_MainListSortingColumn );
        m_comboBoxSortingOrder->setCurrentItem( settings->editing_MainListSortingOrder == 1 ? 0 : 1 );
        m_comboBoxDoubleClickAction->setCurrentItem( settings->editing_MainListDoubleClickAction );
        m_comboBoxDragAction->setCurrentItem( settings->editing_DragAction == Settings::COPYREFERENCE ? 0 : 1 );

        m_checkBoxUseSpecialFont->setChecked( settings->editing_UseSpecialFont );
        m_specialFont = settings->editing_SpecialFont;
        updateFontData();
        m_pushButtonSpecialFont->setEnabled( m_checkBoxUseSpecialFont->isChecked() );

        m_comboBoxNameOrder->setCurrentItem( settings->editing_FirstNameFirst ? 0 : 1 );

        m_documentSearchPaths.clear();
        for ( TQStringList::Iterator it = settings->editing_DocumentSearchPaths.begin(); it != settings->editing_DocumentSearchPaths.end(); ++it )
            m_documentSearchPaths.append( *it );

        m_sliderBarFindDuplicatesSensitivity->setValue(( m_findDuplicatesSensitivityMin + m_findDuplicatesSensitivityMax ) - settings->editing_findDuplicatesSensitivity );
    }

    void SettingsEditing::slotConfigChanged()
    {
        emit configChanged();
    }

    void SettingsEditing::slotSelectSpecialFont()
    {
        int result = TDEFontDialog::getFont( m_specialFont );
        if ( result == TDEFontDialog::Accepted )
        {
            updateFontData();
            emit configChanged();
        }
    }

    void SettingsEditing::slotSelectDocumentSearchPath()
    {
        if ( editPathList( m_documentSearchPaths ) )
            slotConfigChanged();
    }

    void SettingsEditing::updateFontData()
    {
        m_pushButtonSpecialFont->setText( m_specialFont.family() );
        m_pushButtonSpecialFont->setFont( m_specialFont );
    }

    bool SettingsEditing::editPathList( TQStringList &pathList )
    {
        return SettingsEditingPaths::execute( this, pathList );
    }
}

#include "settingsediting.moc"
