/* -*- C++ -*-
   This file implements a widget to edit string lists.

   the KDE addressbook
   $ Author: Mirko Boehm $
   $ Copyright: (C) 1996-2000, Mirko Boehm $
   $ Contact: mirko@kde.org
         http://www.kde.org $
   $ License: GPL with the following explicit clarification:
         This code may be linked against any version of the Qt toolkit
         from Troll Tech, Norway. $

   $Revision: 1.10 $
*/

#include <qsize.h>
#include <qbitmap.h>
#include <qtooltip.h>
#include "widget_editstringlist.h"
#include <kiconloader.h>
#include <klocale.h>
#include <kapp.h>
#include <knotifyclient.h>
#include <qpushbutton.h>
#include <qlineedit.h>
#include <qlistbox.h>

StringListEditWidget::StringListEditWidget(QWidget* parent, const char* name)
  : QWidget(parent, name)
{
  // ############################################################################
  // ----- set button texts, tooltips and bitmaps
  buttonUp=new QPushButton(this);
  buttonUp->setPixmap(BarIcon("up"));
  buttonDown=new QPushButton(this);
  buttonDown->setPixmap(BarIcon("down"));
  buttonDelete=new QPushButton(this);
  buttonDelete->setPixmap(BarIcon("eraser"));
  buttonNew=new QPushButton(this);
  buttonNew->setPixmap(BarIcon("filenew"));
  QToolTip::add(buttonNew, i18n("Add a new string"));
  QToolTip::add(buttonUp, i18n("Move this string up"));
  QToolTip::add(buttonDown, i18n("Move this string down"));
  QToolTip::add(buttonDelete, i18n("Delete this string"));
  leLine=new QLineEdit(this);
  leLine->setEnabled(false);
  lbStrings=new QListBox(this);
  connect(lbStrings, SIGNAL(highlighted(int)), SLOT(itemSelected(int)));
  connect(buttonUp, SIGNAL(clicked()), SLOT(upPressed()));
  connect(buttonDown, SIGNAL(clicked()), SLOT(downPressed()));
  connect(buttonDelete, SIGNAL(clicked()), SLOT(deletePressed()));
  connect(leLine, SIGNAL(textChanged(const QString&)),
	  SLOT(itemChanged(const QString&)));
  connect(buttonNew, SIGNAL(clicked()), SLOT(newItem()));
  // -----
  connect(kapp, SIGNAL(appearanceChanged()), SLOT(initializeGeometry()));
  initializeGeometry();
  enableButtons();
  // ############################################################################
}


StringListEditWidget::~StringListEditWidget()
{
  // ############################################################################
  // ############################################################################
}

void StringListEditWidget::initializeGeometry()
{
  // ############################################################################
  setMinimumSize(sizeHint());
  // ############################################################################
}

QSize StringListEditWidget::sizeHint() const
{
  // ############################################################################
  float GoldenerSchnitt=2.0/3;
  const int ButtonSize1=QMAX(buttonNew->sizeHint().width(), buttonUp->sizeHint().width());
  const int ButtonSize2=QMAX(buttonDown->sizeHint().width(), buttonDelete->sizeHint().width());
  const int Grid=3, ButtonSize=QMAX(ButtonSize1, ButtonSize2);
  int cx, cy;
  // -----
  cx=QMAX((int)1.5*leLine->sizeHint().width()+Grid+ButtonSize, // le, new-button
	  lbStrings->sizeHint().width()+Grid+ButtonSize);
  cy=QMAX(leLine->sizeHint().height(), ButtonSize)
    +Grid
    +QMAX(lbStrings->sizeHint().height(),
	  3*ButtonSize+2*Grid+10);
  // ----- it is a matter of taste,
  if(cx*GoldenerSchnitt<cy) cx=(int)(cy*(1.0/GoldenerSchnitt));
  return QSize(cx, cy);
  // ############################################################################
}

void StringListEditWidget::resizeEvent(QResizeEvent*)
{
  // ############################################################################
  const int ButtonSize1=
    QMAX(buttonNew->sizeHint().width(), buttonUp->sizeHint().width());
  const int ButtonSize2=
    QMAX(buttonDown->sizeHint().width(), buttonDelete->sizeHint().width());
  const int Grid=3, ButtonSize=QMAX(ButtonSize1, ButtonSize2);
  QPushButton* buttons[]= {
    buttonUp,
      buttonDown,
      buttonDelete };
  const int Size=sizeof(buttons)/sizeof(buttons[0]);
  int i, j, h, tempx, tempy;
  // -----
  h=leLine->sizeHint().height();
  tempy=QMAX(ButtonSize, h);
  if(ButtonSize>h)
    {
      i=(ButtonSize-h)/2;
      j=0;
    } else {
      i=0;
      j=(h-ButtonSize)/2;
    }
  leLine->setGeometry(0, i, width()-Grid-ButtonSize, h);
  buttonNew->setGeometry(width()-ButtonSize, j, ButtonSize, ButtonSize);
  tempy+=Grid;
  lbStrings->setGeometry(0, tempy, width()-Grid-ButtonSize, height()-tempy);
  tempx=lbStrings->width()+Grid;
  for(i=0; i<Size; i++)
    {
      if(i==Size-1) // last button at bottom
	{
	  buttons[i]->setGeometry(tempx, tempy+lbStrings->height()-ButtonSize,
				  ButtonSize, ButtonSize);
	} else {
	  buttons[i]->setGeometry(tempx, tempy+i*(ButtonSize+Grid),
				  ButtonSize, ButtonSize);
	}	
    }
  // ############################################################################
}

void StringListEditWidget::setStrings(const QStringList& strings)
{
  // ############################################################################
  lbStrings->clear();
  lbStrings->insertStringList(strings);
  enableButtons();
  // ############################################################################
}

void StringListEditWidget::getStrings(QStringList& result)
{
  // ############################################################################
  int count;
  // -----
  result.clear();
  for(count=0; (unsigned)count<lbStrings->count(); count++)
    {
      result.append(lbStrings->text(count));
    }
  // ############################################################################
}

void StringListEditWidget::upPressed()
{
  // ############################################################################
  int index=lbStrings->currentItem();
  QString text;
  // -----
  if(index==-1 || lbStrings->count()<2)
    {
      KNotifyClient::beep();
    } else {
      if(index!=0)
	{
	  text=lbStrings->text(index);
	  lbStrings->removeItem(index);
	  lbStrings->insertItem(text, index-1);
	  lbStrings->setCurrentItem(index-1);
	  lbStrings->centerCurrentItem();
	} else {
	  KNotifyClient::beep();
	}
    }	
  enableButtons();
  // ############################################################################
}

void StringListEditWidget::downPressed()
{
  // ############################################################################
  int index=lbStrings->currentItem();
  QString text;
  // -----
  if(index==-1 || lbStrings->count()<2)
    {
      KNotifyClient::beep();
    } else {
      if((unsigned)index+1!=lbStrings->count())
	{
	  text=lbStrings->text(index);
	  lbStrings->removeItem(index);
	  lbStrings->insertItem(text, index+1);
	  lbStrings->setCurrentItem(index+1);
	  lbStrings->centerCurrentItem();
	} else {
	  KNotifyClient::beep();
	}
    }
  enableButtons();
  // ############################################################################
}

void StringListEditWidget::deletePressed()
{
  // ############################################################################
  int index=lbStrings->currentItem();
  // -----
  if(index==-1)
    {
      KNotifyClient::beep();
    } else {
      lbStrings->removeItem(index);
      if(lbStrings->count()==0)
 	{
 	  leLine->setText("");
 	  leLine->setEnabled(false);
 	}
    }
  enableButtons();
  // ############################################################################
}

void StringListEditWidget::itemSelected(int index)
{
  // ############################################################################
  leLine->setEnabled(true);
  if(index>=0 && (unsigned)index<lbStrings->count())
    {
      leLine->setText(lbStrings->text(index));
    }
  leLine->setFocus();
  enableButtons();
  // ############################################################################
}

void StringListEditWidget::newItem()
{
  // ############################################################################
  int index;
  // -----
  index=lbStrings->currentItem();
  if(index<0) // empty listbox
    {
      index=0;
    }
  lbStrings->insertItem("", index);
  lbStrings->setCurrentItem(index);
  itemSelected(0);
  leLine->setFocus();
  enableButtons();
  // ############################################################################
}

void StringListEditWidget::itemChanged(const QString& text)
{
  // ############################################################################
  static int InProgress; // WORK_TO_DO: check for endless-loop-bug in final 2.1
  int cursorPos;
  // -----
  if(!lbStrings->count()==0)
    {
      if(InProgress==0) // avoid endless loop
      	{ // this is safe as long as the GUI is single threaded
	  InProgress=1;
	  cursorPos=leLine->cursorPosition();
	  lbStrings->changeItem(text, lbStrings->currentItem());
	  leLine->setCursorPosition(cursorPos);
	  InProgress=0;
	}
    }
  // ############################################################################
}

void StringListEditWidget::enableButtons()
{
  // ############################################################################
  int index;
  // -----
  index=lbStrings->currentItem();
  buttonUp->setEnabled(index>0);
  buttonDown->setEnabled((unsigned)index < (lbStrings->count()-1) && index!=-1);
  buttonDelete->setEnabled(index!=-1);
  // ############################################################################
}

#include "widget_editstringlist.moc"
