/*
 *   kljettool - LaserJet Tool
 *   This file only: Copyright (C) 2000 Espen Sand, espen@kde.org
 *
 *   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 <iostream.h>

#include <qcheckbox.h>
#include <qcombobox.h>
#include <qfile.h>
#include <qfont.h>
#include <qframe.h>
#include <qgroupbox.h>
#include <qlayout.h>
#include <qlabel.h>
#include <qlineedit.h>
#include <qpushbutton.h>
#include <qradiobutton.h>
#include <qtextstream.h>
#include <qtimer.h>
#include <qvbuttongroup.h> 
 
#include <kapp.h>
#include <kiconloader.h>
#include <klocale.h>
#include <kmessagebox.h>

#include "optiondialog.h"
#include "version.h"

#include "optiondialog.moc"


OptionDialog::OptionDialog( QWidget *parent, char *name, bool modal )
  :KDialogBase( Tabbed, QString::null, Help|Apply|Ok|Close,
		Ok, parent, name, modal )
{
  setHelp( "kljettool/kljettool.html", QString::null );

  setupPrinterPage();
  setupPaperPage();
  setupOperationPage();
  setupFontPage();
  setupAboutPage();
  
  setState();
  parsePrintcap();
}


OptionDialog::~OptionDialog( void )
{
}


void OptionDialog::setupPaperPage( void )
{
  QFrame *page = addPage( i18n("Paper") );
  QHBoxLayout *topLayout = new QHBoxLayout( page, 0, spacingHint() );
 
  QVBoxLayout *vlay1 = new QVBoxLayout( topLayout );
  QVBoxLayout *vlay2 = new QVBoxLayout();
  topLayout->addLayout(vlay2,10);

  QLabel *label = new QLabel( i18n("Format:"), page );
  vlay1->addWidget( label );
  
  mPaper.formatCombo = new QComboBox( false, page, "formatcombo" );
  mPaper.formatCombo->insertItem( i18n("A4") );
  mPaper.formatCombo->insertItem( i18n("Letter") );
  mPaper.formatCombo->insertItem( i18n("Legal") );
  mPaper.formatCombo->insertItem( i18n("Executive") );
  mPaper.formatCombo->insertItem( i18n("Com10") );
  mPaper.formatCombo->insertItem( i18n("B5") );
  mPaper.formatCombo->insertItem( i18n("C5") );
  mPaper.formatCombo->insertItem( i18n("DL") );
  mPaper.formatCombo->insertItem( i18n("Monarch") );
  vlay1->addWidget( mPaper.formatCombo );

  label = new QLabel( i18n("Copies:"), page );
  vlay1->addWidget( label );

  mPaper.copyEdit = new QLineEdit( page, "copyedit" );
  mPaper.copyEdit->setText( "1" );
  vlay1->addWidget( mPaper.copyEdit );

  label = new QLabel( i18n("Lines:"), page );
  vlay1->addWidget( label );

  mPaper.linesEdit = new QLineEdit( page, "lineedit" );
  mPaper.linesEdit->setText( "66" );
  vlay1->addWidget( mPaper.linesEdit );

  vlay1->addStretch(10);

  QVButtonGroup *group = new QVButtonGroup( i18n("Orientation"), page );
  vlay2->addWidget( group );
  mPaper.portraitRadio = new QRadioButton( i18n("Portrait"), group );
  mPaper.landscapeRadio = new QRadioButton( i18n("Landscape"), group );
 
  group = new QVButtonGroup( i18n("Miscellaneous"), page );
  vlay2->addWidget( group );
  mPaper.manualCheck = new QCheckBox( i18n("Manual Feed"), group );
  mPaper.autoCheck = new QCheckBox( i18n("Auto Continue"), group );
}


void OptionDialog::setupPrinterPage( void )
{
  QFrame *page = addPage( i18n("Printer") );
  QHBoxLayout *topLayout = new QHBoxLayout( page, 0, spacingHint() );

  QVBoxLayout *vlay1 = new QVBoxLayout();
  QVBoxLayout *vlay2 = new QVBoxLayout();
  topLayout->addLayout(vlay1,10);
  topLayout->addLayout(vlay2,10);
  
  QVButtonGroup *group = new QVButtonGroup( i18n("Mode"), page );
  vlay1->addWidget( group );
  mPrinter.economyRadio = new QRadioButton( i18n("Economy"), group );
  mPrinter.presentationRadio = new QRadioButton( i18n("Presentation"), group );
 
  group = new QVButtonGroup( i18n("Resolution"), page );
  vlay2->addWidget( group );
  mPrinter.dpi300Radio = new QRadioButton( i18n("300 dpi"), group );
  mPrinter.dpi600Radio = new QRadioButton( i18n("600 dpi"), group );

  QLabel *label = new QLabel( i18n("Printer:"), page );
  vlay1->addWidget( label );
  mPrinter.printerCombo = new  QComboBox( page, "printer" );
  vlay1->addWidget( mPrinter.printerCombo );

  connect( mPrinter.printerCombo, SIGNAL( highlighted(const QString&) ),
           SLOT( setPrinter(const QString&) ));

  vlay1->addStretch(10);

  label = new QLabel( i18n("Density:"), page );
  vlay2->addWidget( label );
  mPrinter.densityCombo = new  QComboBox( page, "density" );
  mPrinter.densityCombo->insertItem( i18n("very light") );
  mPrinter.densityCombo->insertItem( i18n("light") );
  mPrinter.densityCombo->insertItem( i18n("medium") );
  mPrinter.densityCombo->insertItem( i18n("dark") );
  mPrinter.densityCombo->insertItem( i18n("very dark") );
  vlay2->addWidget( mPrinter.densityCombo );

  label = new QLabel( i18n("Resolution Enhancement:"), page );
  vlay2->addWidget( label );
  mPrinter.resolutionCombo = new  QComboBox( page, "resolution" );
  mPrinter.resolutionCombo->insertItem( i18n("off") );
  mPrinter.resolutionCombo->insertItem( i18n("light") );
  mPrinter.resolutionCombo->insertItem( i18n("medium") );
  mPrinter.resolutionCombo->insertItem( i18n("dark") );
  vlay2->addWidget( mPrinter.resolutionCombo );

  vlay2->addStretch(10);
}


void OptionDialog::setupOperationPage( void )
{
  QFrame *page = addPage( i18n("Operations") );
  QVBoxLayout *topLayout = new QVBoxLayout( page, 0, spacingHint() );

  QHBoxLayout *hlay = new QHBoxLayout( topLayout );
 
  QVButtonGroup *group = new QVButtonGroup( i18n("End of Line Mode"), page );
  hlay->addWidget( group );
  mOperation.unixRadio = new QRadioButton( i18n("UNIX (LF)"), group );
  mOperation.dosRadio  = new QRadioButton( i18n("Dos (CR+LF)"), group );
  hlay->addStretch(10);

  //
  // 2000-01-23 Espen Sand
  // This is a BAD hack. The frame is not made wide enough if the 
  // title is too long
  //
  int w1 = group->fontMetrics().width( group->title() ) +
    group->fontMetrics().maxWidth()*2;
  int w2 = group->sizeHint().width();
  group->setMinimumWidth( QMAX( w1, w2 ) );


  QBoxLayout *vlay = new QVBoxLayout( hlay );
  hlay->addStretch(10);

  QLabel *label = new QLabel( i18n("PageProtect:"), page );
  vlay->addWidget( label );
  mOperation.pageProtectCombo = new QComboBox( page, "pageprotect" );
  mOperation.pageProtectCombo->insertItem( i18n("on") );
  mOperation.pageProtectCombo->insertItem( i18n("off") );
  mOperation.pageProtectCombo->insertItem( i18n("auto") );
  vlay->addWidget( mOperation.pageProtectCombo );

  vlay->addStretch(10);

  label = new QLabel( i18n("Powersave Time:"), page );
  vlay->addWidget( label );
  mOperation.powersaveCombo = new QComboBox( page, "powersave" );
  mOperation.powersaveCombo->insertItem( "0" );
  mOperation.powersaveCombo->insertItem( "15" );
  mOperation.powersaveCombo->insertItem( "30" );
  mOperation.powersaveCombo->insertItem( "60" );
  mOperation.powersaveCombo->insertItem( "120" );
  mOperation.powersaveCombo->insertItem( "180" );
  vlay->addWidget( mOperation.powersaveCombo );

  topLayout->addStretch(10);

  hlay = new QHBoxLayout( topLayout );
  QPushButton *pb = new QPushButton( i18n("Reset"), page );
  connect( pb, SIGNAL(clicked()), this, SLOT(resetButtonClicked()) );
  hlay->addWidget( pb );
  pb = new QPushButton( i18n("Eject"), page );
  connect( pb, SIGNAL(clicked()), this, SLOT(ejectButtonClicked()) );
  hlay->addWidget( pb );
  pb = new QPushButton( i18n("Initialize"), page );
  connect( pb, SIGNAL(clicked()), this, SLOT(initializeButtonClicked()) );
  hlay->addWidget( pb );
  hlay->addStretch(10);
  
  topLayout->addStretch(10);
}


void OptionDialog::setupFontPage( void )
{
  QFrame *page = addPage( i18n("Fonts") );
  QHBoxLayout *topLayout = new QHBoxLayout( page, 0, spacingHint() );

  topLayout->addStretch( 10 );
  QGridLayout *glay = new QGridLayout( topLayout, 6, 3 );
  topLayout->addStretch( 10 );

  QLabel *label = new QLabel( i18n("Language:"), page );
  glay->addWidget( label, 0, 0, AlignRight );
  mFont.languageCombo = new QComboBox( page, "language" );
  mFont.languageCombo->insertItem( i18n("pcl") );
  mFont.languageCombo->insertItem( i18n("postscript") );
  mFont.languageCombo->insertItem( i18n("escp") );
  mFont.languageCombo->insertItem( i18n("auto") );
  glay->addWidget( mFont.languageCombo, 0, 1 );

  label = new QLabel( i18n("Symbol Set:"), page );
  glay->addWidget( label, 1, 0, AlignRight );
  mFont.symbolCombo = new QComboBox( page, "symbol" );
  mFont.symbolCombo->insertItem( i18n("Desktop") );
  mFont.symbolCombo->insertItem( i18n("ISO4") );
  mFont.symbolCombo->insertItem( i18n("ISO6") );
  mFont.symbolCombo->insertItem( i18n("ISO11") );
  mFont.symbolCombo->insertItem( i18n("ISO15") );
  mFont.symbolCombo->insertItem( i18n("ISO17") );
  mFont.symbolCombo->insertItem( i18n("ISO21") );
  mFont.symbolCombo->insertItem( i18n("ISO60") );
  mFont.symbolCombo->insertItem( i18n("ISO69") );
  mFont.symbolCombo->insertItem( i18n("ISOL1") );
  mFont.symbolCombo->insertItem( i18n("ISOL2") );
  mFont.symbolCombo->insertItem( i18n("ISOL5") );
  mFont.symbolCombo->insertItem( i18n("Legal") );
  mFont.symbolCombo->insertItem( i18n("Math8") );
  mFont.symbolCombo->insertItem( i18n("MSPubl") );
  mFont.symbolCombo->insertItem( i18n("PC8") );
  mFont.symbolCombo->insertItem( i18n("PC8DN") );
  mFont.symbolCombo->insertItem( i18n("PC850") );
  mFont.symbolCombo->insertItem( i18n("PC852") );
  mFont.symbolCombo->insertItem( i18n("PC8TK") );
  mFont.symbolCombo->insertItem( i18n("Pifont") );
  mFont.symbolCombo->insertItem( i18n("PSMath") );
  mFont.symbolCombo->insertItem( i18n("PSText") );
  mFont.symbolCombo->insertItem( i18n("Roman8") );
  mFont.symbolCombo->insertItem( i18n("VNIntl") );
  mFont.symbolCombo->insertItem( i18n("VNMath") );
  mFont.symbolCombo->insertItem( i18n("VNUS") );
  mFont.symbolCombo->insertItem( i18n("Win30") );
  mFont.symbolCombo->insertItem( i18n("WinL1") );
  mFont.symbolCombo->insertItem( i18n("WinL2") );
  mFont.symbolCombo->insertItem( i18n("WinL5") );
  glay->addWidget( mFont.symbolCombo, 1, 1 );

  label = new QLabel( i18n("Font:"), page );
  glay->addWidget( label, 2, 0, AlignRight );
  mFont.fontEdit = new QLineEdit( page, "font" );
  glay->addWidget( mFont.fontEdit, 2, 1 );

  label = new QLabel( i18n("Pitch:"), page );
  glay->addWidget( label, 3, 0, AlignRight );
  mFont.pitchEdit = new QLineEdit( page, "pitch" );
  glay->addWidget( mFont.pitchEdit, 3, 1 );
  label = new QLabel( i18n("cpi"), page );
  glay->addWidget( label, 3, 2 );

  label = new QLabel( i18n("Point Size:"), page );
  glay->addWidget( label, 4, 0, AlignRight );
  mFont.pointSizeEdit = new QLineEdit( page, "pointsize" );
  glay->addWidget( mFont.pointSizeEdit, 4, 1 );
  label = new QLabel( i18n("points"), page );
  glay->addWidget( label, 4, 2 );

  glay->setRowStretch ( 5, 10 );  
}


void OptionDialog::setupAboutPage( void )
{
  QFrame *page = addPage( i18n("About") );
  // An extra margin here
  QVBoxLayout *topLayout = new QVBoxLayout( page, spacingHint() ); 

  QString authorText = i18n(""
    "<h2>KLjetTool %1</h2>"
    "<nobr>Bernd Johannes Wuebben</nobr><br>"
    "wuebben@kde.org<br>"
    "Copyright (C) 1997<br><br>"
    "Updated by Espen Sand<br>"
    "espen@kde.org<br>"
    "in January 2000<br>").arg(KLJETVERSION);

  QHBoxLayout *hlay = new QHBoxLayout( topLayout );

  QLabel *logo = new QLabel(page);
  logo->setPixmap( BarIcon("kljetlogo") );
  hlay->addWidget( logo );

  QLabel *label = new QLabel( authorText, page );
  hlay->addWidget( label, 10, AlignHCenter );
  hlay->addSpacing( spacingHint() );
}


void OptionDialog::slotOk( void )
{
  slotApply();
  accept();
}


void OptionDialog::slotApply( void )
{
  mState.Economode  = mPrinter.presentationRadio->isChecked() ? "off" : "on";
  mState.Resolution = mPrinter.dpi600Radio->isChecked() ? "600" : "300";
  mState.Density.setNum( mPrinter.densityCombo->currentItem()+1 );
  mState.RET        = mPrinter.resolutionCombo->currentText();

  mState.Format     = mPaper.formatCombo->currentText();
  mState.Copies     = mPaper.copyEdit->text();
  mState.Formlines  = mPaper.linesEdit->text();
  mState.Orientation= mPaper.portraitRadio->isChecked() ? 
    "Portrait" : "Landscape";
  mState.Manualfeed = mPaper.manualCheck->isChecked() ? "on" : "off";
  mState.Autocont   = mPaper.autoCheck->isChecked() ? "on" : "off";

  mState.Pageprotect= mOperation.pageProtectCombo->currentText();
  mState.Powersave  = mOperation.powersaveCombo->currentText();
  mState.Termination= mOperation.unixRadio->isChecked() ? "unix" : "dos";

  mState.Language   = mFont.languageCombo->currentText();
  mState.Symset     = mFont.symbolCombo->currentText();
  mState.Fontnumber = mFont.fontEdit->text();
  mState.Pitch      = mFont.pitchEdit->text();
  mState.Ptsize     = mFont.pointSizeEdit->text();

  mState.print();
  mState.writeSettings();
}


void OptionDialog::slotDefault( void )
{
}


void OptionDialog::setState( void )
{
  setPrinter( mState );
  setPaper( mState );
  setOperations( mState );
  setFont( mState );
}


void OptionDialog::setPrinter( const Data &state )
{
  if( state.Economode == "off" )
  {
    mPrinter.presentationRadio->setChecked(true);
  }
  else
  {
    mPrinter.economyRadio->setChecked(true);
  }

  if( state.Resolution == "600" )
  {
    mPrinter.dpi600Radio->setChecked(true);
  }
  else
  {
    mPrinter.dpi300Radio->setChecked(true);
  }

  int count = mPrinter.densityCombo->count();
  if( count == 0 )
  {
    cerr << "Printer: densityCombo empty" << endl;
    return;
  }

  int item = state.Density.toInt() - 1;
  if( item < 0 || item > count-1 )
  {
    cerr << "Printer: density out of range " << item+1 << endl;
  }
  mPrinter.densityCombo->setCurrentItem(item);

  count = mPrinter.resolutionCombo->count();
  if( count == 0 )
  {
    cerr << "Printer: resolutionCombo empty" << endl;
    return;
  }

  for( int i = 0; i < count; i++ )
  {
    if ( mPrinter.resolutionCombo->text(i) == state.RET )
    {
      mPrinter.resolutionCombo->setCurrentItem(i);
      break;
    }
  }

}


void OptionDialog::setPaper( const Data &state )
{
  int count = mPaper.formatCombo->count();
  if( count == 0 )
  {
    return;
  }

  for( int i = 0; i < count; i++ )
  {
    if( mPaper.formatCombo->text(i) == state.Format )
    {
      mPaper.formatCombo->setCurrentItem(i);
      break;
    }
  }

  mPaper.copyEdit->setText( state.Copies );
  mPaper.linesEdit->setText( state.Formlines );
  
  if( state.Orientation == "Portrait" )
  {
    mPaper.portraitRadio->setChecked(true);
  }
  else
  {
    mPaper.landscapeRadio->setChecked(true);
  }

  mPaper.manualCheck->setChecked( state.Manualfeed == "off" ? false : true );
  mPaper.autoCheck->setChecked( state.Autocont == "off" ? false : true );
}


void OptionDialog::setOperations( const Data &state )
{
  int count = mOperation.pageProtectCombo->count();
  if( count == 0 )
  {
    cerr << "Operations: pageProtectCombo empty" << endl;
    return;
  }

  for( int i = 0; i < count; i++ )
  {
    if( mOperation.pageProtectCombo->text(i) == state.Pageprotect )
    {
      mOperation.pageProtectCombo->setCurrentItem(i);
      break;
    }
  }

  count = mOperation.powersaveCombo->count();
  if( count == 0 )
  {
    cerr << "Operations: powersaveCombo empty" << endl;
    return;
  }
  for( int i = 0; i < count; i++)
  {
    if( mOperation.powersaveCombo->text(i) == state.Powersave )
    {
      mOperation.powersaveCombo->setCurrentItem(i);
      break;
    }
  }

  if( state.Termination == "unix" )
  {
    mOperation.unixRadio->setChecked(true);
  }
  else
  {
    mOperation.dosRadio->setChecked(true);
  }
}


void OptionDialog::setFont( const Data &state )
{
  int count = mFont.languageCombo->count();
  if( count == 0 )
  {
    cerr << "Fonts: languageCombo empty" << endl;
    return;
  }
  
  for( int i = 0; i < count; i++ )
  {
    if( mFont.languageCombo->text(i) == state.Language )
    {
      mFont.languageCombo->setCurrentItem(i);
      break;
    }
  }

  count = mFont.symbolCombo->count();
  if( count == 0 )
  {
    cerr << "Fonts: symbolCombo empty" << endl;
    return;
  }

  for( int i = 0; i < count; i++ )
  {
    if( mFont.symbolCombo->text(i) == state.Symset )
    {
      mFont.symbolCombo->setCurrentItem(i);
      break;
    }
  }

  mFont.fontEdit->setText( state.Fontnumber );
  mFont.pitchEdit->setText( state.Pitch );
  mFont.pointSizeEdit->setText( state.Ptsize );
}


void OptionDialog::parsePrintcap( void )
{
  QFile printcap( "/etc/printcap" );
  if( !printcap.open(IO_ReadOnly) )
  {
    QTimer::singleShot( 100, this, SLOT(printcapReadError()) ); 
    return;
  }

  //
  // This section is borrowed from Christopher Neerfeld's klpq
  //
  QTextStream st( (QIODevice *) &printcap);
  while( !st.eof() )
  {
    QString temp = st.readLine();
    if( temp[0] == '#' || temp.isEmpty() )
    { 
      continue;
    }

    QString name = temp.left( temp.find(':') );
    if( name.isEmpty() )
    {
      continue;
    }

    if( name.contains('|') )
    {
      name = name.left( name.find('|') );
    }

    name.stripWhiteSpace();
    if( name.isEmpty() )
    {
      continue;
    }

    while( temp.right(1) == (QString)"\\" )
    {
      temp = st.readLine();
      if( temp[0] == '#')
      {
	temp = "\\";
      }
    }

    mPrinter.printerCombo->insertItem( name );
  }

  if( mPrinter.printerCombo->count() == 0 )
  {
    QTimer::singleShot( 100, this, SLOT(printcapNoEntryError()) ); 
    return;
  }

}


void OptionDialog::printcapReadError( void )
{
  QString msg = i18n("Unable to open the \"/etc/printcap\" file.");
  KMessageBox::sorry(0, msg );
}


void OptionDialog::printcapNoEntryError( void )
{
  QString msg = i18n(""
    "Unable to parse the \"/etc/printcap\" file.\n"
    "Please email your printcap to wuebben@kde.org" );  
  KMessageBox::sorry(0, msg );
}


void OptionDialog::ejectButtonClicked( void )
{
  mState.eject();
}


void OptionDialog::resetButtonClicked( void )
{
  mState.reset();
}


void OptionDialog::initializeButtonClicked( void )
{
  mState.initialize();
}

void OptionDialog::setPrinter(const QString& str)
{
  mState.setPrinter( str );
}
