/***************************************************************************
 *   Copyright (C) 2006 Nicolas Hadacek <hadacek@kde.org>                  *
 *   Copyright (C) 1992-2003 Trolltech AS.                                 *
 *                                                                         *
 *   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.                                   *
 ***************************************************************************/
#include "list_view.h"

#include <tqapplication.h>
#include <tqpainter.h>
#include <tqlineedit.h>
#include <tqheader.h>
#include <tqmetaobject.h>
#include <tqvariant.h>

//----------------------------------------------------------------------------
ListView::ListView(TQWidget *parent, const char *name)
  : TDEListView(parent, name)
{
  TQToolTip::remove(this);
  _tooltip = new ListViewToolTip(this);
}

ListView::~ListView()
{
  delete _tooltip;
}

TQString ListView::tooltip(const TQListViewItem &, int) const
{
  return TQString();
}

void ListView::clear()
{
  _editItems.clear();
  TDEListView::clear();
}

bool ListView::eventFilter(TQObject *o, TQEvent *e)
{
  TQValueList<EditListViewItem *>::const_iterator it;
  for (it=_editItems.begin(); it!=_editItems.end(); ++it) {
    for (uint i=0; i<(*it)->_editWidgets.count(); i++) {
      if ( TQT_BASE_OBJECT((*it)->_editWidgets[i])==TQT_BASE_OBJECT(o) ) {
        //tqDebug("event %i", e->type());
        switch (e->type()) {
          case TQEvent::KeyPress: {
            TQKeyEvent *ke = TQT_TQKEYEVENT(e);
            switch (ke->key()) {
              case Key_Enter:
              case Key_Return:
                (*it)->renameDone(true);
                return true;
              case Key_Escape:
                (*it)->removeEditBox();
                return true;
            }
            break;
          }
          case TQEvent::FocusOut: {
            //tqDebug("focus out %i %i=%i", tqApp->focusWidget(), focusWidget(), (*it)->_editWidgets[i]);
            if ( tqApp->focusWidget() && focusWidget()==(*it)->_editWidgets[i] ) break;
            //tqDebug("ext");
            TQCustomEvent *e = new TQCustomEvent(9999);
            TQApplication::postEvent(o, e);
            return true;
          }
          case 9999:
            (*it)->renameDone(false);
            return true;
          default:
            //tqDebug("  ignored");
            break;
        }
      }
    }
  }
  return TDEListView::eventFilter(o, e);
}

void ListView::stopRenaming(bool force)
{
  TQValueList<EditListViewItem *>::const_iterator it;
  for (it=_editItems.begin(); it!=_editItems.end(); ++it)
    if ( (*it)->isRenaming() ) (*it)->renameDone(force);
}

//----------------------------------------------------------------------------
void ListViewToolTip::maybeTip(const TQPoint &p)
{
  if ( _listView==0 ) return;
  const TQListViewItem* item = _listView->itemAt(p);
  if ( item==0 ) return;
  TQRect rect = _listView->itemRect(item);
  if ( !rect.isValid() ) return;
  int col = _listView->header()->sectionAt(p.x());
  TQString text = _listView->tooltip(*item, col);
  if ( !text.isEmpty() ) {
    int hpos = _listView->header()->sectionPos(col);
    rect.setLeft(hpos);
    rect.setRight(hpos + _listView->header()->sectionSize(col));
    tip(rect, text);
  }
}

//----------------------------------------------------------------------------
EditListViewItem::EditListViewItem(ListView *list)
  : TDEListViewItem(list), _renaming(false)
{
  setRenameEnabled(0, true);
  list->_editItems.append(this);
}

EditListViewItem::EditListViewItem(TDEListViewItem *item)
  : TDEListViewItem(item), _renaming(false)
{
  setRenameEnabled(0, true);
  static_cast<ListView *>(listView())->_editItems.append(this);
}

EditListViewItem::~EditListViewItem()
{
  if ( listView() ) static_cast<ListView *>(listView())->_editItems.remove(this);
  for (uint i=0; i<_editWidgets.count(); i++) delete _editWidgets[i];
}

void EditListViewItem::paintCell(TQPainter *p, const TQColorGroup &cg, int column, int width, int align)
{
  if ( column<int(_editWidgets.count()) && _editWidgets[column] )
    p->fillRect(0, 0, width, height(), cg.color(TQColorGroup::Background));
  else TDEListViewItem::paintCell(p, cg, column, width, align);
}

void EditListViewItem::startRename()
{
  if ( !renameEnabled(0) ) return;
  TQListView *lv = listView();
  if ( !lv ) return;
  TDEListViewItem::startRename(0);
  if (renameBox) {
    renameBox->removeEventFilter(lv);
    renameBox->hide();
    lv->removeChild(renameBox);
  }
  _renaming = true;
  _editWidgets.resize(lv->columns());
  for (uint i=0; i<_editWidgets.count(); i++) {
    TQRect r = lv->itemRect(this);
    r = TQRect(lv->viewportToContents(r.topLeft()), r.size());
    r.setLeft(lv->header()->sectionPos(i));
    r.setWidth(lv->header()->sectionSize(i) - 1);
    if ( i==0 ) r.setLeft(r.left() + lv->itemMargin() + (depth() + (lv->rootIsDecorated() ? 1 : 0)) * lv->treeStepSize() - 1);
    if ( (lv->contentsX() + lv->visibleWidth())<(r.x() + r.width()) )
      lv->scrollBy((r.x() + r.width() ) - ( lv->contentsX() + lv->visibleWidth() ), 0);
    if ( r.width()>lv->visibleWidth() ) r.setWidth(lv->visibleWidth());

    _editWidgets[i] = editWidgetFactory(i);
    if ( _editWidgets[i]==0 ) continue;
    _editWidgets[i]->installEventFilter(lv);
    lv->addChild(_editWidgets[i], r.x(), r.y());
    uint w = TQMIN(r.width(), _editWidgets[i]->sizeHint().width());
    _editWidgets[i]->resize(w, r.height());
    lv->viewport()->setFocusProxy(_editWidgets[i]);
    _editWidgets[i]->setFocus();
    _editWidgets[i]->show();
  }
}

void EditListViewItem::removeEditBox()
{
  TQListView *lv = listView();
  if ( !lv ) return;
  _renaming = false;
  bool resetFocus = false;
  for (uint i=0; i<_editWidgets.count(); i++) {
    if ( lv->viewport()->focusProxy()==_editWidgets[i] ) resetFocus = true;
    delete _editWidgets[i];
  }
  _editWidgets.clear();
  delete renameBox;
  renameBox = 0;
  if (resetFocus) {
    lv->viewport()->setFocusProxy(lv);
    lv->setFocus();
  }
}

void EditListViewItem::editDone(int col, const TQWidget *edit)
{
  if ( edit->metaObject()->findProperty("text", true)!=-1 )
    emit listView()->itemRenamed(this, col, edit->property("text").toString());
  else if ( edit->metaObject()->findProperty("currentText", true)!=-1 )
    emit listView()->itemRenamed(this, col, edit->property("currentText").toString());
}

void EditListViewItem::renameDone(bool force)
{
  TQListView *lv = listView();
  if ( !lv || !_renaming ) return;
  _renaming = false;
  for (uint i=0; i<_editWidgets.count(); i++) {
    if ( !force && !alwaysAcceptEdit(i) ) continue;
    emit lv->itemRenamed(this, i);
    if ( _editWidgets[i] ) editDone(i, _editWidgets[i]);
  }
  removeEditBox();
}

int EditListViewItem::width(const TQFontMetrics &fm, const TQListView *lv, int col) const
{
  int w = TDEListViewItem::width(fm, lv, col);
  TQWidget *edit = editWidgetFactory(col);
  if ( edit==0 ) return w;
  w = TQMAX(w, edit->sizeHint().width());
  delete edit;
  return w;
}
