/**
 * Copyright (C) 2000-2002 the KGhostView authors. See file AUTHORS.
 *
 * 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.
 */


// Add header files alphabetically

#include <qbuttongroup.h>
#include <qcheckbox.h>
#include <qgroupbox.h>
#include <qlabel.h>
#include <qlayout.h>
#include <qradiobutton.h>

#include <kdebug.h>
#include <kglobal.h>
#include <kconfig.h>
#include <kinstance.h>
#include <klineedit.h>
#include <klocale.h>
#include <kstandarddirs.h>
#include <kurlrequester.h>
#include <kprocess.h>

#include "kgv_view.h"

#include "kgvconfigdialog.h"

KGVConfigDialog::KGVConfigDialog( QWidget *parent, const char *name,
				  bool modal )
  : KDialogBase( TreeList, i18n( "Configure" ), Ok|Cancel|Default,
		 Ok, parent, name, modal )
{
    /*== General ==========================================================*/
    QFrame* generalPage = addPage( i18n( "General" ),
				   i18n( "General Settings" ) );

    QString antiAliasLabel = i18n( "Enable anti-aliasing of fonts and images" );
    QString platformFontLabel = i18n( "Use platform fonts" );
    QString messagesLabel = i18n( "Show Ghostscript messages in a seperate box" );

    mAntiAliasCheck    = new QCheckBox( antiAliasLabel, generalPage );
    mPlatformFontCheck = new QCheckBox( platformFontLabel, generalPage );
    mMessagesCheck     = new QCheckBox( messagesLabel, generalPage );
    mPaletteGroup = new QButtonGroup( 1, Vertical, i18n( "Palette" ),
				      generalPage );
    mMonoRadio = new QRadioButton( i18n("Monochrome"), mPaletteGroup );
    mGrayscaleRadio = new QRadioButton( i18n("Grayscale"), mPaletteGroup );
    mColorRadio = new QRadioButton( i18n("Color"), mPaletteGroup );

    QVBoxLayout* generalLayout = new QVBoxLayout( generalPage, 0, 6 );
    generalLayout->addWidget( mAntiAliasCheck );
    generalLayout->addWidget( mPlatformFontCheck );
    generalLayout->addWidget( mMessagesCheck );
    generalLayout->addWidget( mPaletteGroup );
    generalLayout->addStretch();

    connect( mAntiAliasCheck, SIGNAL( toggled( bool ) ),
	     this, SLOT( slotAaToggled( bool ) ) );
    connect( mMonoRadio, SIGNAL( toggled( bool ) ),
	     this, SLOT( slotMonoOrGrayToggled( bool ) ) );
    connect( mGrayscaleRadio, SIGNAL( toggled( bool ) ),
	     this, SLOT( slotMonoOrGrayToggled( bool ) ) );

    /*== Ghostscript ======================================================*/
    QFrame* ghostscriptPage = addPage( i18n( "Ghostscript" ),
				    i18n( "Ghostscript Configuration" ) );

    mConfigureButton = new QPushButton( i18n( "Configure" ),
					ghostscriptPage );
    QGroupBox* manualConfigBox = new QGroupBox( 1, Horizontal,
			i18n( "Settings" ), ghostscriptPage );
    // TODO -- buddies for the labels
    new QLabel( i18n( "Interpreter: " ), manualConfigBox );
    mInterpreterReq = new KURLRequester( manualConfigBox);
    new QLabel( i18n( "Non-antialiasing arguments: " ), manualConfigBox );
    mNonAntiAliasArgsEdit = new KLineEdit( manualConfigBox );
    new QLabel( i18n( "Antialiasing arguments: " ), manualConfigBox );
    mAntiAliasArgsEdit = new KLineEdit( manualConfigBox );

    QVBoxLayout* layout1 = new QVBoxLayout( ghostscriptPage, 0, 6 );
    QHBoxLayout* layout2 = new QHBoxLayout( layout1 );
    layout1->addWidget( manualConfigBox );
    layout1->addStretch();
    layout2->addWidget( mConfigureButton );
    layout2->addStretch();

    connect( mConfigureButton, SIGNAL( clicked() ),
	     this, SLOT( slotConfigureGhostscript() ) );

    readSettings();
}

KGVConfigDialog::~KGVConfigDialog()
{
    writeSettings();
}


    static
	QString getGSVersion( QString fullPathToExec )
	{
	    QString res;
	    QString chkVersion = KProcess::quote(fullPathToExec) + " --version";
	    FILE* p = popen( QFile::encodeName(chkVersion), "r" );
	    if( p ) {
		// FIXME: a badly configured interpreter can hang us
		QFile qp;
		qp.open( IO_ReadOnly, p );
		qp.readLine( res, 80 );
		qp.close();
		pclose( p );
		res = res.stripWhiteSpace();
	    }
	    kdDebug(4500) << "kgvconfigdialog.cpp::{unamed}::getGSVersion() returning " << res <<  endl;
	    return res;
	}


/* A mechanism for triggering redection of gs versions:
 *
 * The idea is that whenever we find we need to workaround a certain version of gs,
 * we cannot rely that there will solelly be a new kghostviewrc, but that users will
 * upgrade kghostview. Therefore, whenever we want to trigger redection on a new version,
 * we increment the counter below. It should have the old value from the previous version
 * of kghostview and this function will get called.
 * 
 */

/* On a related note:
 * We don't detect upgrades (or downgrades, for that matter) of gs.
 * I am seeing if I can get the version out of gs as a side effect to displaying a file.
 * This way, using kconfig:/Ghostscript/GS Version we will see whether the version has changed
 * and trigger a redetection without the trouble of running "gs --version" on each launch.
 *
 * LPC (9 April 2003)
 */
const int currentRedetection = 1;


/* Here are the issues we found so far in version of gs:
 *
 * - gs before 6.50 uses device x11alpha instead of x11
 * - gs 6.5x does not work well with -dMaxBitmap=...
 * - gs 8.0 changed the meaning of -dSAFER to -dPARANOIDSAFER and it must be worked around.
 *
 */

/* It is not so good to keep version detection in two functions,
 * but, for now, it will have to do.
 * 
 */
static void redoGSDetection( KConfig* config ) 
{
    kdDebug() << "kgvconfigdialog.cpp::{unnamed}::redoGSDetection()" << endl;
    QString version = getGSVersion( config->readEntry( "Interpreter", "gs" ) );
    if ( version < QString::number( 7.00 ) ) 
    {
	QStringList arguments = QStringList::split( ' ', config->readEntry( "Antialiasing arguments", "" ) );
	arguments.remove( QString::fromLatin1( "-dMaxBitmap=10000000" ) );
	QString antiAliasArgs = arguments.join( " " );

	config->writeEntry( "Antialiasing arguments", antiAliasArgs );
    }
    config->writeEntry( "GS Version", version );
    config->writeEntry( "Redetection Counter", currentRedetection );
    config->sync();
}

bool KGVConfigDialog::slotConfigureGhostscript()
{
    kdDebug(4500) << "KGVConfigDialog::slotConfigureGhostscript" << endl;

    QString exe = "gs";
    if( !KStandardDirs::findExe( exe ) ) {
	return false;
    }
    QString versionString = getGSVersion( exe );
    if ( versionString.isNull() ) return false;

    mInterpreterPath = exe;
    mNonAntiAliasArgs = "-sDEVICE=x11";
    mAntiAliasArgs =  versionString < QString::number(6.50)
		? "-sDEVICE=x11alpha"
		: "-sDEVICE=x11 -dTextAlphaBits=4 -dGraphicsAlphaBits=2";
    // -dMaxBitmap is half broken in gs 6.5x, so only use after 7.00
    if ( versionString > QString::number( 7.00 ) ) mAntiAliasArgs += " -dMaxBitmap=10000000";
    setup();

    return true;
}

void KGVConfigDialog::slotAaToggled( bool on )
{
    if( on )
	mColorRadio->setChecked( true );
}

void KGVConfigDialog::slotMonoOrGrayToggled( bool on )
{
    if( on )
	mAntiAliasCheck->setChecked( false );
}

void KGVConfigDialog::setup()
{
    mAntiAliasCheck->setChecked( mAntialias );
    mPlatformFontCheck->setChecked( mPlatformFonts );
    mMessagesCheck->setChecked( mShowMessages );

    mMonoRadio->setChecked( mPaletteType == MONO_PALETTE );
    mGrayscaleRadio->setChecked( mPaletteType == GRAY_PALETTE );
    mColorRadio->setChecked( mPaletteType == COLOR_PALETTE );

    mInterpreterReq->setURL( mInterpreterPath );
    mNonAntiAliasArgsEdit->setText( mNonAntiAliasArgs );
    mAntiAliasArgsEdit->setText( mAntiAliasArgs );
}

void KGVConfigDialog::slotOk()
{
    // mInterpreterPath  = mInterpreterEdit->text();
    mAntialias = mAntiAliasCheck->isChecked();
    mShowMessages = mMessagesCheck->isChecked();
    mPlatformFonts = mPlatformFontCheck->isChecked();
    if( mColorRadio->isChecked() )
	mPaletteType = COLOR_PALETTE;
    else if( mGrayscaleRadio->isChecked() )
	mPaletteType = GRAY_PALETTE;
    else
	mPaletteType = MONO_PALETTE;

    mInterpreterPath = mInterpreterReq->url();
    mNonAntiAliasArgs = mNonAntiAliasArgsEdit->text();
    mAntiAliasArgs = mAntiAliasArgsEdit->text();

    writeSettings();
    accept();
}


void KGVConfigDialog::slotDefault()
{
    mInterpreterPath	= "gs";
    mAntialias		= true;
    mShowMessages	= true;
    mPlatformFonts	= false;
    mPaletteType	= COLOR_PALETTE;
    setup();
}

void KGVConfigDialog::readSettings()
{
    kdDebug(4500) << "KGVConfigDialog::readSettings" << endl;

    KConfig* config = KGVFactory::instance()->config();
    QString oldGroup = config->group();

    config->setGroup( "General" );

    mAntialias = config->readBoolEntry( "Antialiasing", true );
    mShowMessages = config->readBoolEntry( "Messages", false );
    mPlatformFonts = config->readBoolEntry( "Platform fonts", false );

    QString text = config->readEntry( "Palette" );
    if( text.find( "mono" ) == 0 )
	mPaletteType = MONO_PALETTE;
    else if( text.find( "gray" ) == 0 )
	mPaletteType = GRAY_PALETTE;
    else
	mPaletteType = COLOR_PALETTE;

    if( config->hasGroup( "Ghostscript" ) ) {
	config->setGroup( "Ghostscript" );
	if ( config->readNumEntry( "Redetection Counter", 0 ) < currentRedetection ) {
	    redoGSDetection( config );
	}
	mInterpreterPath = config->readPathEntry( "Interpreter" );
	mNonAntiAliasArgs = config->readEntry( "Non-antialiasing arguments" );
	mAntiAliasArgs = config->readEntry( "Antialiasing arguments" );
    }
    else if( slotConfigureGhostscript() ) {
	config->setGroup( "Ghostscript" );
	config->writeEntry( "Interpreter", mInterpreterPath );
	config->writeEntry( "Non-antialiasing arguments", mNonAntiAliasArgs );
	config->writeEntry( "Antialiasing arguments", mAntiAliasArgs );
	config->writeEntry( "Redetection Counter", currentRedetection ); // slotConfigureGhostscript() does the checks
	config->sync();
    }

    config->setGroup( oldGroup );

    setup();
}

void KGVConfigDialog::writeSettings()
{
    kdDebug(4500) << "KGVConfigDialog::writeSettings" << endl;

    KConfig* config = KGVFactory::instance()->config();
    QString oldGroup = config->group();

    config->setGroup( "General" );

    config->writeEntry( "Interpreter", mInterpreterPath );
    config->writeEntry( "Antialiasing", mAntialias );
    config->writeEntry( "Platform fonts", mPlatformFonts );
    config->writeEntry( "Messages", mShowMessages );

    QString text;
    if( mPaletteType == COLOR_PALETTE )
	text = "color";
    else if( mPaletteType == GRAY_PALETTE )
	text = "grayscale";
    else
	text = "monochrome";
    config->writeEntry( "Palette", text );

    config->setGroup( "Ghostscript" );
    config->writeEntry( "Interpreter", mInterpreterPath );
    config->writeEntry( "Non-antialiasing arguments", mNonAntiAliasArgs );
    config->writeEntry( "Antialiasing arguments", mAntiAliasArgs );

    config->setGroup( oldGroup );
    config->sync();
}

#include "kgvconfigdialog.moc"

// vim:sw=4:sts=4:ts=8:noet
