/***************************************************************************
                           datawidget.cpp  -  description
                             -------------------
    begin                : Tue Feb 12 2002
    copyright            : (C) 2002 by Scott Wheeler
    email                : wheeler@kde.org
***************************************************************************/

/***************************************************************************
 *   This program is free software; you can redistribute it and/or modify  *a
 *   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.                                   *
***************************************************************************/

#include "datawidget.h"

#include <klocale.h>
#include <kpushbutton.h>
#include <kmessagebox.h>
#include <ktextedit.h>
#include <klistview.h>
#include <kconfig.h>
#include <kdebug.h>


#include <qlayout.h>
#include <qlabel.h>
#include <qsplitter.h>

class CardListViewItem : public KListViewItem
{
public:
  CardListViewItem(QListView *parent, const QString &front, const QString &back) :
    KListViewItem(parent, front.simplifyWhiteSpace(), back.simplifyWhiteSpace()),
    formattedFrontText(front),
    formattedBackText(back) {}

  CardListViewItem(QListView *parent, QListViewItem *after,
                   const QString &front, const QString &back) :
    KListViewItem(parent, after, front.simplifyWhiteSpace(), back.simplifyWhiteSpace()),
    formattedFrontText(front),
    formattedBackText(back) {}

  QString front() const { return formattedFrontText; }
  QString back()  const { return formattedBackText; }

  void setFront(const QString &text) {
    formattedFrontText = text;
    setText(0, text.simplifyWhiteSpace());
  }

  void setBack(const QString &text) {
    formattedBackText = text;
    setText(1, text.simplifyWhiteSpace());
  }

private:
  QString formattedFrontText;
  QString formattedBackText;
};

////////////////////////////////////////////////////////////////////////////////
// public members
////////////////////////////////////////////////////////////////////////////////

DataWidget::DataWidget(QWidget *parent, const char *name) : QWidget(parent, name)
{
  setupLayout();
  readConfig();
}

DataWidget::~DataWidget()
{
  writeConfig();
}

CardList DataWidget::cardList() const
{
  CardListViewItem *i = static_cast<CardListViewItem *>(cardListView->firstChild());
  CardList list;

  while(i) {
    list.append(Card(i->front(), i->back()));
    i = static_cast<CardListViewItem *>(i->itemBelow());
  }

  return list;
}

void DataWidget::clear()
{
  cardListView->clear();
  frontBox->clear();
  backBox->clear();
  cardListView->setSorting(cardListView->columns() + 1);
}

void DataWidget::loadCards(const CardList &cards)
{
  for(CardList::ConstIterator it = cards.begin(); it != cards.end(); it++)
    new CardListViewItem(cardListView, (*it).front(), (*it).back());
}

void DataWidget::cut()
{
  if(frontBox && frontBox->hasSelectedText())
    frontBox->cut();
  else if(backBox && backBox->hasSelectedText())
    backBox->cut();
}

void DataWidget::copy()
{
  if(frontBox && frontBox->hasSelectedText())
    frontBox->copy();
  else if(backBox && backBox->hasSelectedText())
    backBox->copy();
}

void DataWidget::paste()
{
  if(frontBox)
    frontBox->paste();
  else if(backBox)
    backBox->paste();
}

bool DataWidget::hasSelectedText() const
{
  return frontBox && backBox && (frontBox->hasSelectedText() || backBox->hasSelectedText());
}

////////////////////////////////////////////////////////////////////////////////
// private members
////////////////////////////////////////////////////////////////////////////////

void DataWidget::setupLayout()
{
  (new QVBoxLayout(this, 0))->setAutoAdd(true);
  splitter = new QSplitter(Qt::Vertical, this, "splitter");

  cardListView = new KListView(splitter, "cardListView");
  cardListView->addColumn(i18n("Front"));
  cardListView->addColumn(i18n("Card backside", "Back"));

  cardListView->setFullWidth(true);
  cardListView->setAllColumnsShowFocus(true);
  cardListView->setSorting(cardListView->columns() + 1);

  connect(cardListView, SIGNAL(selectionChanged(QListViewItem *)),
	  this, SLOT(changeSelection(QListViewItem *)));

  QWidget *layoutWidget = new QWidget(splitter, "layoutWidget");
  QVBoxLayout *layout = new QVBoxLayout(layoutWidget, 0, 2 , "layout");
  QGridLayout *labelLayout = new QGridLayout(2, 2, 2, "labelLayout");
  layout->addLayout(labelLayout);

  QLabel *frontLabel = new QLabel(i18n("Front"), layoutWidget, "frontLabel");
  frontLabel->setAlignment(Qt::AlignHCenter);
  labelLayout->addWidget(frontLabel, 0, 0);

  QLabel *backLabel = new QLabel(i18n("Card backside", "Back"), layoutWidget, "backLabel");
  backLabel->setAlignment(Qt::AlignHCenter);
  labelLayout->addWidget(backLabel , 0, 1);

  frontBox = new KTextEdit(layoutWidget, "frontBox");
  labelLayout->addWidget(frontBox, 1, 0);

  backBox = new KTextEdit(layoutWidget, "backBox");
  labelLayout->addWidget(backBox, 1, 1);

  connect(frontBox, SIGNAL(selectionChanged()), this, SIGNAL(selectionChanged()));

  connect(backBox, SIGNAL(selectionChanged()), this, SIGNAL(selectionChanged()));

  frontBox->installEventFilter(this);
  backBox->installEventFilter(this);

  QHBoxLayout *buttonLayout = new QHBoxLayout(layout, 2);

  addCardButton = new KPushButton(i18n("Add Card"), layoutWidget, "addCardButton");
  buttonLayout->addWidget(addCardButton);
  KPushButton *deleteCardButton =
    new KPushButton(i18n("Delete Card"), layoutWidget, "deleteCardButton");
  buttonLayout->addWidget(deleteCardButton);
  KPushButton *updateCardButton =
    new KPushButton(i18n("Update Card"), layoutWidget, "updateCardButton");
  buttonLayout->addWidget(updateCardButton);

  connect(addCardButton, SIGNAL(clicked()), this, SLOT(addCard()));
  connect(deleteCardButton, SIGNAL(clicked()), this, SLOT(deleteCard()));
  connect(updateCardButton, SIGNAL(clicked()), this, SLOT(updateCard()));
}

void DataWidget::readConfig()
{
  KConfig *config = KGlobal::config();
  {
    KConfigGroupSaver saver(config, "DataWidget");
    QValueList<int> sizes = config->readIntListEntry("SplitterSizes");
    if(sizes.isEmpty())
      sizes << 300 << 100;

    splitter->setSizes(sizes);
  }
}

void DataWidget::writeConfig()
{
  KConfig *config = KGlobal::config();
  {
    KConfigGroupSaver saver(config, "DataWidget");
    config->writeEntry("SplitterSizes", splitter->sizes());
  }
}

// This should be the same as QuizWidget::eventFilter() -- I'm just too lazy at the 
// moment to create a base class for QuizWidget and DataWidget that has just this.

bool DataWidget::eventFilter(QObject *object, QEvent *event)
{
  if(event && event->type() == QEvent::KeyPress)
  {
    QKeyEvent * ev = static_cast<QKeyEvent *>(event);
    if((ev->key() == Qt::Key_Tab) || ((ev->state() & Qt::ControlButton)
          && (ev->key() == Qt::Key_Return)))
    {
      if(object == frontBox) {
        backBox->setFocus();
        return true;
      }
      if(object == backBox) {
        if(ev->key() == Qt::Key_Return) {
          addCard();
          frontBox->setFocus();
        }
        else
          addCardButton->setFocus();
        return true;
      }
    }
  }
  if(event && event->type() == QEvent::FocusIn) {
    if(dynamic_cast<KTextEdit *>(object))
      emit editWidgetFocusIn();
  }
  if(event && event->type() == QEvent::FocusOut) {
    QFocusEvent *focusEvent = static_cast<QFocusEvent *>(event);
    if(dynamic_cast<KTextEdit *>(object) && focusEvent->reason() != QFocusEvent::Popup)
      emit editWidgetFocusOut();
  }
  return QWidget::eventFilter(object, event);
}

////////////////////////////////////////////////////////////////////////////////
// private slots
////////////////////////////////////////////////////////////////////////////////

void DataWidget::changeSelection(QListViewItem *item)
{
  CardListViewItem *i = static_cast<CardListViewItem *>(item);
  frontBox->setText(i->front());
  backBox->setText(i->back());
}

void DataWidget::addCard()
{
  if(frontBox->text().stripWhiteSpace().isEmpty() ||
     backBox->text().stripWhiteSpace().isEmpty())
  {
    KMessageBox::sorry(
	this, i18n("You must enter text for both the front and back of the card."));
  }
  else
  {
    new CardListViewItem(cardListView,
			 cardListView->lastItem(),
			 frontBox->text(),
			 backBox->text());
    frontBox->clear();
    backBox->clear();
    frontBox->setFocus();
    emit dataChanged();
  }
}

void DataWidget::deleteCard()
{
  delete cardListView->currentItem();
  frontBox->clear();
  backBox->clear();
  frontBox->setFocus();
  emit dataChanged();
}

void DataWidget::updateCard()
{
  if(cardListView->currentItem()) {
    CardListViewItem *i = static_cast<CardListViewItem *>(cardListView->currentItem());

    i->setFront(frontBox->text());
    i->setBack(backBox->text());
    frontBox->setFocus();

    int sortColumn = cardListView->sortColumn();

    if(sortColumn >= 0 && sortColumn < cardListView->columns()) {
      cardListView->sort();
      cardListView->ensureItemVisible(i);
    }
    emit dataChanged();
  }
}

// vim: sw=2 sts=2 et
#include "datawidget.moc"
