/*
    $Id: kfontexplorer.cpp,v 1.24 2000/06/07 09:52:53 coolo Exp $

    Copyright (C) 1996 Bernd Johannes Wuebben <wuebben@math.cornell.edu>
    Copyright (C) 2000 Hans Petter Bieker <bieker@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 <qlayout.h>
#include <qlabel.h>
#include <qcombobox.h>
#include <qapplication.h>
#include <qstrlist.h> 
#include <qfile.h>
#include <qtextstream.h> 
#include <qbuttongroup.h> 

#include <klocale.h>
#include <kapp.h>
#include <kstddirs.h>

#include "kfontexplorer.h"
#include "main.h"

#define ARRAYSIZE(x) ( (int) (sizeof(x) / sizeof(x[0])) )

static unsigned char fontsizes[] = 
 { 4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,22,24,26,28,32,48,64 };


KFontExplorer::KFontExplorer( QWidget *parent, const char *name, 
			      const QStrList* fontlist )
  : QWidget( parent, name )
{
  QString string;
  QHBoxLayout *hbox;
  QVBoxLayout *vbox;
  QGroupBox *gbox;
  int i;
  
  QVBoxLayout *top = new QVBoxLayout(this,10,10);

  gbox = new QGroupBox(i18n("Requested Font"),this);
  top->addWidget(gbox);

  hbox = new QHBoxLayout(gbox,10,10);
  hbox->addStretch();
  // 1. column
  vbox = new QVBoxLayout(hbox);
  vbox->addSpacing(10);
  vbox->addWidget( new QLabel(i18n("Family:"), gbox) ); 
  vbox->addSpacing(10);
  vbox->addWidget( new QLabel(i18n("Weight:"), gbox) ); 
  vbox->addSpacing(10);
  vbox->addWidget( new QLabel(i18n("Charset:"),gbox) ); 
  vbox->addSpacing(10);
  // 2. column
  vbox = new QVBoxLayout(hbox);
  vbox->addSpacing(10);
  vbox->addWidget( family_combo = new QComboBox(false, gbox) );
  vbox->addSpacing(10);
  vbox->addWidget( weight_combo = new QComboBox(false, gbox) );
  vbox->addSpacing(10);
  vbox->addWidget(charset_combo = new QComboBox(false, gbox) );
  vbox->addSpacing(10);
  // 3. column
  hbox->addStretch();
  vbox = new QVBoxLayout(hbox);
  vbox->addSpacing(10);
  vbox->addWidget( new QLabel(i18n("Size:"),	gbox) ); 
  vbox->addSpacing(10);
  vbox->addWidget( new QLabel(i18n("Style:"),	gbox) ); 
  vbox->addSpacing(10);
  vbox->addWidget( new QLabel("",               gbox) ); 
  vbox->addSpacing(10);
  // 4. column
  vbox = new QVBoxLayout(hbox);
  vbox->addSpacing(10);
  vbox->addWidget( size_combo = new QComboBox(false,  gbox) );
  vbox->addSpacing(10);
  vbox->addWidget( style_combo = new QComboBox(false, gbox) );
  vbox->addSpacing(10);
  vbox->addWidget( new QLabel("", 		      gbox) ); 
  vbox->addSpacing(10);
  hbox->addStretch();


  // status dialogs... (second (lower) part of the display)
  gbox = new QGroupBox(i18n("Actual Font"),this);
  top->addWidget(gbox);
  
  hbox = new QHBoxLayout(gbox,10,10);
  hbox->addSpacing(10);
  hbox->addStretch();

  vbox = new QVBoxLayout(hbox);
  vbox->addSpacing(10);
  vbox->addWidget( new QLabel(i18n("Charset:"),gbox) );
  vbox->addWidget( new QLabel(i18n("Family:") ,gbox) );
  vbox->addWidget( new QLabel(i18n("Size:")   ,gbox) );
  vbox->addWidget( new QLabel(i18n("Weight:") ,gbox) );
  vbox->addWidget( new QLabel(i18n("Style:")  ,gbox) );
  vbox->addSpacing(10);

  vbox = new QVBoxLayout(hbox);
  vbox->addSpacing(10);
  vbox->addWidget( actual_charset_label_data = new QLabel("",gbox) );
  vbox->addWidget( actual_family_label_data  = new QLabel("",gbox) );
  vbox->addWidget( actual_size_label_data    = new QLabel("",gbox) );
  vbox->addWidget( actual_weight_label_data  = new QLabel("",gbox) );
  vbox->addWidget( actual_style_label_data   = new QLabel("",gbox) );
  vbox->addSpacing(10);

  hbox->addStretch();
  
  vbox = new QVBoxLayout(hbox,10);
  vbox->addSpacing(10);
  example_label = new QLabel(i18n("Dolor Ipse"),gbox);
  example_label->setFont(selFont);
  example_label->setAlignment(AlignCenter);
  example_label->setFrameStyle( QFrame::WinPanel | QFrame::Sunken );
  example_label->setLineWidth( 1 );
  example_label->setMinimumSize( 200,30 );
  vbox->addWidget( example_label,10 );
  vbox->addSpacing(10);

  hbox->addStretch();
  hbox->addSpacing(10);

  // preset entries and connect widgets
  if (fontlist) {
    if (fontlist->count())
      family_combo->insertStrList(fontlist, -1);
  }
  else 
    fill_family_combo();

  connect( family_combo, SIGNAL(activated(const QString &)),
	   SLOT(family_chosen_slot(const QString &)) );

  for (i=0; i<ARRAYSIZE(fontsizes); i++)
    size_combo->insertItem( string.setNum((int)fontsizes[i]) );
  connect( size_combo, SIGNAL(activated(const QString &)),
	   SLOT(size_chosen_slot(const QString &)) );

  weight_combo->insertItem( i18n("Normal") );
  weight_combo->insertItem( i18n("Bold") );
  connect( weight_combo, SIGNAL(activated(const QString &)),
	   SLOT(weight_chosen_slot(const QString &)) );

  style_combo->insertItem( i18n("Roman") );
  style_combo->insertItem( i18n("Italic") );
  connect( style_combo, SIGNAL(activated(const QString &)),
	   SLOT(style_chosen_slot(const QString &)) );

  int charsets_count = 0;
  QFont font;
  while (true) { 
    string = font.encodingName( (QFont::CharSet) charsets_count );
    if (!string.length())
      break;
    charset_combo->insertItem( string );
    charsets_count++;
  }

  connect( charset_combo, SIGNAL(activated(int)),
	   SLOT(charset_chosen_slot(int)) );


  connect(this,SIGNAL(fontSelected( const QFont&  )),
	  this,SLOT(display_example( const QFont&)));

  // let's initialize the display if possible
  if (family_combo->count())
    this->setFont(QFont(family_combo->text(0),12,QFont::Normal));
  
  setColors();
  connect( KApplication::kApplication(),SIGNAL(kdisplayPaletteChanged()),
	   this,SLOT(setColors()) );
}

void KFontExplorer::charset_chosen_slot(int index)
{
  selFont.setCharSet( (QFont::CharSet) index );
  emit fontSelected(selFont);
}

void KFontExplorer::setFont( const QFont &aFont)
{
  selFont = aFont;
  setCombos();
  display_example(selFont);
}  

void KFontExplorer::family_chosen_slot(const QString &family)
{
  selFont.setFamily(family);
  // display_example();
  emit fontSelected(selFont);
}

void KFontExplorer::size_chosen_slot(const QString &size)
{
  selFont.setPointSize(size.toInt());
  // display_example();
  emit fontSelected(selFont);
}

void KFontExplorer::weight_chosen_slot(const QString &weight)
{
  QString weight_string = weight;

  if ( weight_string == i18n("normal"))
    selFont.setBold(false);
  if ( weight_string == i18n("bold"))
       selFont.setBold(true);
  // display_example();
  emit fontSelected(selFont);
}

void KFontExplorer::style_chosen_slot(const QString &style)
{
  QString style_string = style;

  if ( style_string == i18n("roman"))
    selFont.setItalic(false);
  if ( style_string == i18n("italic"))
    selFont.setItalic(true);
  //  display_example();
  emit fontSelected(selFont);
}
       
void KFontExplorer::display_example(const QFont& font)
{
  QString string;

  example_label->setFont(font);

  QFontInfo info = example_label->fontInfo();
  actual_family_label_data->setText(info.family());

  actual_size_label_data->setNum(info.pointSize());

  string = info.bold() ? i18n("Bold") : i18n("Normal");
  actual_weight_label_data->setText(string);
 
  string = info.italic() ? i18n("Italic") : i18n("Roman");
  actual_style_label_data->setText(string);
  
  QFont::CharSet charset = info.charSet();
  actual_charset_label_data->setText(font.encodingName(charset) );
}

void KFontExplorer::setCombos()
{
  int number_of_entries =  family_combo->count(); 
  QString string = selFont.family();
  QComboBox *combo = family_combo; 
  bool found = false;

  for (int i = 0; i < number_of_entries; i++) {
    // kdDebug() << string.data() << " with " << ((QString) combo->text(i)).data() << "\n" << endl;
    if ( string.lower() == ((QString) combo->text(i)).lower()){
      combo->setCurrentItem(i);
      // kdDebug() << "Found Font " << string.data() << "\n" << endl;
      found = true;
      break;
    }
  }
 
  number_of_entries =  size_combo->count(); 
  string.setNum(selFont.pointSize());
  combo = size_combo; 
  found = false;

  for (int i = 0; i < number_of_entries - 1; i++){
    if ( string == (QString) combo->text(i)){
      combo->setCurrentItem(i);
      found = true;
      // kdDebug() << "Found Size " << string.data() << " setting to item " << i << "\n" << endl;
      break;
    }
  }

  if (selFont.bold())
    weight_combo->setCurrentItem(1);
  else
    weight_combo->setCurrentItem(0);

  if (selFont.italic())
    style_combo->setCurrentItem(1);
  else
    style_combo->setCurrentItem(0);

  charset_combo->setCurrentItem( (int)selFont.charSet() );
}

bool KFontExplorer::loadKDEInstalledFonts()
{
  QString fontfilename =  locate("config", "kdefonts");

  QFile fontfile(fontfilename);

  if (!fontfile.exists())
    return false;

  if(!fontfile.open(IO_ReadOnly)){
    return false;
  }

  if (!fontfile.isReadable())
    return false;
  
  
  QTextStream t(&fontfile);

  while (!t.eof()) {
    QString s(t.readLine());
    s = s.stripWhiteSpace();
    if (!s.isEmpty())
      family_combo->insertItem( s ,-1 );
  }

  fontfile.close();
  
  return true;
}


void KFontExplorer::fill_family_combo()
{
  QStrList	newlist(true);
  QString	current, qfontname;
  int		dash, dash_two;

  QStrList *fontlist = KFontList_GetXFonts();

  // if available we are done, the kde fonts are now in the family_combo
  if (loadKDEInstalledFonts())
    return;

  for (fontlist->first(); fontlist->current(); fontlist->next()) {

    qfontname = fontlist->current();
    
    dash = qfontname.find('-', 1, true); // find next dash
    if (dash == -1)	// No such next dash -- this shouldn't happen.
	continue;	// but what do I care -- lets skip it.

    // the font name is between the second and third dash so:
    // let's find the third dash:

    dash_two = qfontname.find('-', dash+1, true); 
    if (dash_two == -1)
	continue;

    // fish the name of the font info string

    qfontname = qfontname.mid(dash+1, dash_two-dash-1);

    if (!qfontname.contains("open look", true))
      if (qfontname != "nil")
        if (newlist.find(qfontname) == -1) {
          family_combo->insertItem(qfontname,-1);
	  newlist.append(qfontname);
	}
	  
  } // end for()

  delete fontlist;
}


void KFontExplorer::setColors()
{
  /* this is to the the backgound of a widget to white and the
     text color to black -- some lables such as the one of the
     font manager really shouldn't follow colorschemes The
     primary task of those label is to display the text clearly
     an visibly and not to look pretty ...*/

  QPalette mypalette( example_label->palette() );

  QColorGroup cgrp( mypalette.normal() );
  QColorGroup ncgrp(black,cgrp.background(),
		    cgrp.light(),cgrp.dark(),cgrp.mid(),black,white);

  mypalette.setNormal(ncgrp);
  mypalette.setDisabled(ncgrp);
  mypalette.setActive(ncgrp);

  example_label->setPalette(mypalette);
  example_label->setBackgroundColor(white);
}

#include "kfontexplorer.moc"
