/***************************************************************************
    copyright            : (C) 2005-2006 by Robby Stephenson
    email                : robby@periapsis.org
 ***************************************************************************/

/***************************************************************************
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of version 2 of the GNU General Public License as  *
 *   published by the Free Software Foundation;                            *
 *                                                                         *
 ***************************************************************************/

#include "numberfieldwidget.h"
#include "datewidget.h"
#include "../field.h"

#include <klineedit.h>

#include <tqlayout.h>
#include <tqvalidator.h>

using Tellico::GUI::NumberFieldWidget;

NumberFieldWidget::NumberFieldWidget(Data::FieldPtr field_, TQWidget* parent_, const char* name_/*=0*/)
    : FieldWidget(field_, parent_, name_), m_lineEdit(0), m_spinBox(0) {

  if(field_->flags() & Data::Field::AllowMultiple) {
    initLineEdit();
  } else {
    initSpinBox();
  }

  registerWidget();
}

void NumberFieldWidget::initLineEdit() {
  m_lineEdit = new KLineEdit(this);
  connect(m_lineEdit, TQ_SIGNAL(textChanged(const TQString&)), TQ_SIGNAL(modified()));
  // connect(kl, TQ_SIGNAL(returnPressed(const TQString&)), this, TQ_SLOT(slotHandleReturn()));

  // regexp is any number of digits followed optionally by any number of
  // groups of a semi-colon followed optionally by a space, followed by digits
  TQRegExp rx(TQString::fromLatin1("-?\\d*(; ?-?\\d*)*"));
  m_lineEdit->setValidator(new TQRegExpValidator(rx, this));
}

void NumberFieldWidget::initSpinBox() {
  // intentionally allow only positive numbers
  m_spinBox = new GUI::SpinBox(-1, INT_MAX, this);
  connect(m_spinBox, TQ_SIGNAL(valueChanged(int)), TQ_SIGNAL(modified()));
  // TQSpinBox doesn't emit valueChanged if you edit the value with
  // the lineEdit until you change the keyboard focus
  connect(m_spinBox->child("qt_spinbox_edit"), TQ_SIGNAL(textChanged(const TQString&)), TQ_SIGNAL(modified()));
  // I want to allow no value, so set space as special text. Empty text is ignored
  m_spinBox->setSpecialValueText(TQChar(' '));
}

TQString NumberFieldWidget::text() const {
  if(isSpinBox()) {
    // minValue = special empty text
    if(m_spinBox->value() > m_spinBox->minValue()) {
      return TQString::number(m_spinBox->value());
    }
    return TQString();
  }

  TQString text = m_lineEdit->text();
  if(field()->flags() & Data::Field::AllowMultiple) {
    text.replace(s_semiColon, TQString::fromLatin1("; "));
  }
  return text.simplifyWhiteSpace();
}

void NumberFieldWidget::setText(const TQString& text_) {
  blockSignals(true);

  if(isSpinBox()) {
    bool ok;
    int n = text_.toInt(&ok);
    if(ok) {
      // did just allow positive
      if(n < 0) {
        m_spinBox->setMinValue(INT_MIN+1);
      }
      m_spinBox->blockSignals(true);
      m_spinBox->setValue(n);
      m_spinBox->blockSignals(false);
    }
  } else {
    m_lineEdit->blockSignals(true);
    m_lineEdit->setText(text_);
    m_lineEdit->blockSignals(false);
  }

  blockSignals(false);
}

void NumberFieldWidget::clear() {
  if(isSpinBox()) {
    // show empty special value text
    m_spinBox->setValue(m_spinBox->minValue());
  } else {
    m_lineEdit->clear();
  }
  editMultiple(false);
}

void NumberFieldWidget::updateFieldHook(Data::FieldPtr, Data::FieldPtr newField_) {
  bool wasLineEdit = !isSpinBox();
  bool nowLineEdit = newField_->flags() & Data::Field::AllowMultiple;

  if(wasLineEdit == nowLineEdit) {
    return;
  }

  TQString value = text();
  if(wasLineEdit && !nowLineEdit) {
    layout()->remove(m_lineEdit);
    delete m_lineEdit;
    m_lineEdit = 0;
    initSpinBox();
  } else if(!wasLineEdit && nowLineEdit) {
    layout()->remove(m_spinBox);
    delete m_spinBox;
    m_spinBox = 0;
    initLineEdit();
  }

  // should really be FIELD_EDIT_WIDGET_INDEX from fieldwidget.cpp
  static_cast<TQBoxLayout*>(layout())->insertWidget(2, widget(), 1 /*stretch*/);
  widget()->show();
  setText(value);
}

TQWidget* NumberFieldWidget::widget() {
  if(isSpinBox()) {
    return m_spinBox;
  }
  return m_lineEdit;
}

#include "numberfieldwidget.moc"
