/* -*- C++ -*-
   This file implements a widget for navigating through sets of data.

   the K Desktop Environment

   $ 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.11 $
*/

#include "widget_datanavigator.h"
#include <qlineedit.h>
#include <qspinbox.h>
#include <qcombobox.h>
#include <qstringlist.h>
#include <qpushbutton.h>
#include <qlayout.h>
#include <kiconloader.h>
#include <kapp.h>
#include <kdebug.h>
#include <knotifyclient.h>

#include "widget_datanavigator.moc"

KDataNavigator::KDataNavigator(QWidget* parent, const char* name)
  : QFrame(parent, name),
    buttonFirst(new QPushButton(this)),
    buttonPrevious(new QPushButton(this)),
    buttonNext(new QPushButton(this)),
    buttonLast(new QPushButton(this)),
    buttonNew(new QPushButton(this)),
    leIndex(new QLineEdit(this)),
    sbIndex(new QSpinBox(this)),
    cbIndex(new QComboBox(this)),
    min(0),
    max(0),
    current(0),
    mode(Manual),
    buttonNewVisible(true)
{
  // ###########################################################################
  QPushButton* buttons[]= {
    buttonFirst, buttonPrevious, buttonNext, buttonLast, buttonNew
  };
  const char* icons[]= {
    // "2leftarrow", "1leftarrow", "1rightarrow", "2rightarrow", "filenew2"
    "start", "back", "forward", "finish", "filenew"
  };
  int count;
  QPixmap pixmap;
  // -----
  layout=new QGridLayout(this, 1, 6);
  // -----
  if(buttonFirst==0 || buttonPrevious==0 || buttonNext==0 || buttonLast==0 ||
     buttonNew==0 || leIndex==0 || sbIndex==0 || cbIndex==0)
    {
      // possibly throw exception when they are completely implemented
    }
  leIndex->setEnabled(false);
  for(count=0; count<5; ++count)
    {
      pixmap=BarIcon(icons[count]);
      if(!pixmap.isNull())
	{
	  buttons[count]->setPixmap(pixmap);
	}
    }
  layout->addWidget(buttonFirst, 0, 0);
  layout->addWidget(buttonPrevious, 0, 1);
  // < in between is the combo box >
  setMode(mode); // this adds the appropriate central widget
  layout->addWidget(buttonNext, 0, 3);
  layout->addWidget(buttonLast, 0, 4);
  layout->addWidget(buttonNew, 0, 5);
  layout->setColStretch(0, 1);
  layout->setColStretch(1, 1);
  layout->setColStretch(2, 10000);
  layout->setColStretch(3, 1);
  layout->setColStretch(4, 1);
  layout->setColStretch(5, 1);
  // debug("KDataNavigator ctor: layout sizehints %ix%i pixels.",
  // layout->sizeHint().width(), layout->sizeHint().height());
  // -----
  connect(buttonFirst, SIGNAL(clicked()), SLOT(buttonFirstClicked()));
  connect(buttonPrevious, SIGNAL(clicked()), SLOT(buttonPreviousClicked()));
  connect(buttonNext, SIGNAL(clicked()), SLOT(buttonNextClicked()));
  connect(buttonLast, SIGNAL(clicked()), SLOT(buttonLastClicked()));
  connect(buttonNew, SIGNAL(clicked()), SLOT(buttonNewClicked()));
  connect(leIndex, SIGNAL(textChanged(const QString&)),
	  SLOT(leTextChanged(const QString&)));
  connect(cbIndex, SIGNAL(activated(int)), SLOT(cbItemSelected(int)));
  connect(sbIndex, SIGNAL(valueChanged(int)), SLOT(sbValueChanged(int)));
  // -----
  setFrameStyle(QFrame::Box | QFrame::Plain);
  setLineWidth(1);
  enableButtons();
  // ###########################################################################
}

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

/*
  void
  KDataNavigator::resizeEvent(QResizeEvent*)
  {
  // ###########################################################################
  setLayout();
  // ###########################################################################
  }

  QSize
  KDataNavigator::sizeHint()
  {
  // ###########################################################################
  const int ButtonWidth=20; // KButtons do not seem to report it
  const int NoOfButtons= buttonNewVisible ? 5 : 4;
  // -----
  switch(mode)
  {
  case Manual:
  return QSize((NoOfButtons+6)*ButtonWidth+2*frameWidth(),
  ButtonWidth+2*frameWidth());
  case List:
  return QSize((NoOfButtons+8)*ButtonWidth+2*frameWidth(),
  ButtonWidth+2*frameWidth());
  default:
  return QSize((NoOfButtons+4)*ButtonWidth+2*frameWidth(),
  ButtonWidth+2*frameWidth());
  }
  // ###########################################################################
  }
*/


void
KDataNavigator::setLayout()
{
  // ###########################################################################

  // ###########################################################################
}

void
KDataNavigator::buttonFirstClicked()
{
  // ###########################################################################
  switch(mode)
    {
    case Manual: // the most easy case: do nothing
      break;
    case Index:
      if(min<current)
	{
	  current=min;
	  emit(itemSelected(current));
	  sbIndex->setValue(current);
	  enableButtons();
	} else {
	  KNotifyClient::beep(); // cannot happen
	}
      break;
    case List:
      if(current>0 && cbIndex->count()>0)
	{
	  current=0;
	  cbIndex->setCurrentItem(current);
	  emit(itemSelected(current));
	  enableButtons();
	}
      break;
    }
  emit(first());
  // ###########################################################################
}

void
KDataNavigator::buttonPreviousClicked()
{
  // ###########################################################################
  switch(mode)
    {
    case Manual:
      break;
    case Index:
      if(min<current)
	{
	  --current;
	  emit(itemSelected(current));
	  sbIndex->setValue(current);
	  enableButtons();
	} else {
	  KNotifyClient::beep();
	}
      break;
    case List:
      if(current>0 && cbIndex->count()>0)
	{
	  --current;
	  cbIndex->setCurrentItem(current);
	  emit(itemSelected(current));
	  enableButtons();
	}
      break;
    }
  emit(previous());
  // ###########################################################################
}

void
KDataNavigator::buttonNextClicked()
{
  // ###########################################################################
  switch(mode)
    {
    case Manual:
      break;
    case Index:
      if(current<max)
	{
	  ++current;
	  emit(itemSelected(current));
	  sbIndex->setValue(current);
	  enableButtons();
	} else {
	  KNotifyClient::beep();
	}
      break;
    case List:
      if(current<cbIndex->count()-1 && cbIndex->count()>0)
	{
	  ++current;
	  cbIndex->setCurrentItem(current);
	  emit(itemSelected(current));
	  enableButtons();
	}
      break;
    }
  emit(next());
  // ###########################################################################
}

void
KDataNavigator::buttonLastClicked()
{
  // ###########################################################################
  switch(mode)
    {
    case Manual:
      break;
    case Index:
      if(current<max)
	{
	  current=max;
	  emit(itemSelected(current));
	  sbIndex->setValue(current);
	  enableButtons();
	} else {
	  KNotifyClient::beep();
	}
      break;
    case List:
      if(current<cbIndex->count()-1 && cbIndex->count()>0)
	{
	  current=cbIndex->count()-1;
	  cbIndex->setCurrentItem(current);
	  emit(itemSelected(current));
	  enableButtons();
	}
      break;
    }
  emit(last());
  // ###########################################################################
}

void
KDataNavigator::buttonNewClicked()
{
  // ###########################################################################
  emit(newItem());
  // ###########################################################################
}

void
KDataNavigator::setText(const QString & c)
{
  // ###########################################################################
  setMode(Manual);
  leIndex->setText(c);
  // ###########################################################################
}

void
KDataNavigator::setIndexMode(int begin, int end, int cur)
{
  // ###########################################################################
  min=begin;
  max=end;
  current=cur;
  sbIndex->setRange(min, max);
  if(min<=current && current<=max)
    {
      sbIndex->setValue(current);
    } else {
      sbIndex->setValue(min);
    }
  leIndex->hide();
  cbIndex->hide();
  sbIndex->show();
  // -----
  mode=Index;
  enableButtons();
  // ###########################################################################
}

void
KDataNavigator::showButtonNew(bool state)
{
  // ###########################################################################
  if(state)
    {
      buttonNew->show();
    } else {
      buttonNew->hide();
    }
  buttonNewVisible=state;
  // -----
  setLayout();
  // ###########################################################################
}

void
KDataNavigator::enableButtonFirst(bool state)
{
  // ###########################################################################
  buttonFirst->setEnabled(state);
  // ###########################################################################
}

void
KDataNavigator::enableButtonNext(bool state)
{
  // ###########################################################################
  buttonNext->setEnabled(state);
  // ###########################################################################
}

void
KDataNavigator::enableButtonPrevious(bool state)
{
  // ###########################################################################
  buttonPrevious->setEnabled(state);
  // ###########################################################################
}

void
KDataNavigator::enableButtonLast(bool state)
{
  // ###########################################################################
  buttonLast->setEnabled(state);
  // ###########################################################################
}

void
KDataNavigator::enableButtonNew(bool state)
{
  // ###########################################################################
  buttonNew->setEnabled(state);
  // ###########################################################################
}

void
KDataNavigator::enableButtons()
{
  // ###########################################################################
  switch(mode)
    {
    case Manual:
      break;
    case Index:
      buttonFirst->setEnabled(current!=min);
      buttonPrevious->setEnabled(current!=min);
      buttonNext->setEnabled(current!=max);
      buttonLast->setEnabled(current!=max);
      break;
    case List:
      buttonFirst->setEnabled(current!=0);
      buttonPrevious->setEnabled(current!=0);
      buttonNext->setEnabled(current!=cbIndex->count()-1 && cbIndex->count()>0);
      buttonLast->setEnabled(current!=cbIndex->count()-1 && cbIndex->count()>0);
      cbIndex->setEnabled(cbIndex->count()>0);
      break;
    }
  // ###########################################################################
}

void
KDataNavigator::leTextChanged(const QString& s)
{
  // ###########################################################################
  emit(textChanged(s));
  // ###########################################################################
}

void
KDataNavigator::sbValueChanged(int i)
{
  // ###########################################################################
  if(min<=i && i<=max)
    {
      current=i;
      enableButtons();
      emit(itemSelected(i));
    }
  // ###########################################################################
}

void
KDataNavigator::cbItemSelected(int i)
{
  // ###########################################################################
  current=i;
  enableButtons();
  emit(itemSelected(i));
  // ###########################################################################
}

void
KDataNavigator::setMode(Modes m)
{
  // ###########################################################################
  mode=m;
  switch(mode)
    {
    case Manual:
      leIndex->show();
      sbIndex->hide();
      cbIndex->hide();
      layout->addWidget(leIndex, 0, 2);
      buttonFirst->setEnabled(true);
      buttonPrevious->setEnabled(true);
      buttonNext->setEnabled(true);
      buttonLast->setEnabled(true);
      break;
    case Index:
      leIndex->hide();
      sbIndex->show();
      cbIndex->hide();
      layout->addWidget(sbIndex, 0, 2);
      break;
    case List:
      leIndex->hide();
      sbIndex->hide();
      cbIndex->show();
      layout->addWidget(cbIndex, 0, 2);
      break;
    }
  enableButtons();
  setLayout();
  // ###########################################################################
}

void
KDataNavigator::setList(QStringList* strings)
{
  register bool GUARD; GUARD=false;
  // ###########################################################################
  kdDebug() << "KDataNavigator::setList: called, %i items." <<
	     strings->count();
  // -----
  if(cbIndex->count()>0) cbIndex->clear();
  cbIndex->insertStringList(*strings);
  if(cbIndex->count()>0)
    {
      cbIndex->setCurrentItem(0);
      current=0;
    }
  setMode(List);
  // ###########################################################################
}

