/*
 * listeditor.cpp
 *
 * Copyright (C) 2003 Sebastian Sauer <dipesh@gmx.de>
 *
 * 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.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Steet, Fifth Floor, Boston, MA 02110-1301, USA.
 *
 */

#include "listeditor.h"

#include <qlabel.h>
#include <qtooltip.h>
#include <qwhatsthis.h>
#include <qvbox.h>
#include <qhbox.h>

#include <kglobal.h>
#include <kconfig.h>
#include <klocale.h>
#include <kdebug.h>
#include <kpushbutton.h>
#include <klistview.h>
#include <klineedit.h>

/*** ListEditorEdit ***/

ListEditorEdit::ListEditorEdit(QWidget *parent, int columnpos) : QHBox(parent)
{
    this->columnpos = columnpos;
    edit = new KLineEdit(this);
    connect(edit, SIGNAL(textChanged(const QString &)), this, SLOT(slotEditChanged()));
}

inline int ListEditorEdit::getColumnPos() { return columnpos; }
inline void ListEditorEdit::setText(const QString& text) { edit->setText(text); }

void ListEditorEdit::slotEditChanged()
{
    emit editChanged(columnpos, edit->text());
}

/*** ListEditorItem ***/

ListEditorItem::ListEditorItem(QListView* parent, int pos) : KListViewItem(parent)
{
    setPosition(pos);
}

inline int ListEditorItem::getPosition() { return position; }
inline void ListEditorItem::setPosition(int pos) { position = pos; }

int ListEditorItem::compare(QListViewItem *item, int, bool asc) const
{
    int pos = ((ListEditorItem*)item)->getPosition();
    return asc ? ( (position < pos) ? -1 : (position > pos) ? 1 : 0 )
               : ( (position > pos) ? -1 : (position < pos) ? 1 : 0 );
}

void ListEditorItem::moveItem(QListViewItem *after)
{
    KListViewItem::moveItem(after);
    int pos = position;
    setPosition( ((ListEditorItem*)after)->getPosition() );
    ((ListEditorItem*)after)->setPosition(pos);
}

/*** ListEditor ***/

ListEditor::ListEditor(QWidget *parent)
    : QVBox(parent)
{
    Modified = false;
    setSpacing(6);

    QHBox *box = new QHBox(this);
    box->setSpacing(6);
    setStretchFactor(box, 1);

    list = new KListView(box);
    list->setSelectionMode(QListView::Single);
    list->setAllColumnsShowFocus(true);
    connect(list, SIGNAL(selectionChanged()), this, SLOT(slotListChanged()));

    QVBox *btnBox = new QVBox(box);

    btnAdd = new KPushButton(i18n("&Add"), btnBox);
    QToolTip::add(btnAdd, i18n("Add a new item to the list"));
    connect(btnAdd, SIGNAL(clicked()), this, SLOT(slotAdd()));

    btnRem = new KPushButton(i18n("&Remove"), btnBox);
    QToolTip::add(btnRem, i18n("Remove selected item from list"));
    connect(btnRem, SIGNAL(clicked()), this, SLOT(slotRemove()));

    btnUp = new KPushButton(i18n("&Up"), btnBox);
    QToolTip::add(btnUp, i18n("Move selected item up"));
    connect(btnUp, SIGNAL(clicked()), this, SLOT(slotUp()));

    btnDown = new KPushButton(i18n("&Down"), btnBox);
    QToolTip::add(btnDown, i18n("Move selected item down"));
    connect(btnDown, SIGNAL(clicked()), this, SLOT(slotDown()));

    btnBox->setStretchFactor(new QWidget(btnBox), 1);

    editBox = new QVBox(this);
    editBox->setSpacing(6);

    slotListChanged();
}

QValueList<QStringList> ListEditor::getRows()
{
    QValueList<QStringList> items;
    int i;
    QStringList sl;
    QListViewItemIterator it( list );
    while (it.current()) {
        sl.clear();
        for (i = 0; i <= list->columns(); i++)
            sl << it.current()->text(i);
        items.append(sl);
        ++it;
    }
    return items;
}

ListEditorEdit* ListEditor::addColumn(const QString column, const QString& tooltip, bool editable)
{
    list->addColumn(column);
    list->setColumnWidthMode(list->columns() - 1, QListView::Manual);
    ListEditorEdit *edit = 0;
    if (editable) {
        QHBox *box = new QHBox(editBox);
        if (! tooltip.isEmpty()) QToolTip::add(box, tooltip);
        new QLabel(column, box);
        edit = new ListEditorEdit(box, list->columns() - 1);
        edits.append(edit);
        connect(edit, SIGNAL( editChanged(int, const QString&) ), this, SLOT( slotEditChanged(int, const QString&) ));
    }
    return edit;
}

ListEditorItem* ListEditor::addRow(const QStringList& items)
{
    if (items.count() < 1) return 0;
    ListEditorItem *item = new ListEditorItem(list, list->childCount());
    for (uint i = 0; i <= items.count() && (int)i <= list->columns(); i++)
        item->setText(i, items[i]);
    return item;
}

void ListEditor::addRows(QValueList<QStringList> items, bool clear)
{
    if (clear) {
        removeRows();
        Modified = false;
    }
    for (QValueList<QStringList>::Iterator lit = items.begin(); lit != items.end(); ++lit)
        addRow(*lit);
}

void ListEditor::removeRows()
{
    list->clear();
    slotListChanged();
}

void ListEditor::slotListChanged()
{
    editBox->setEnabled( list->selectedItem() );

    for (QValueList<ListEditorEdit*>::Iterator it = edits.begin(); it != edits.end(); ++it) {
        if (! (*it)) continue;
        (*it)->setText( list->selectedItem()
                        ? list->selectedItem()->text( (*it)->getColumnPos() )
                        : QString("") );
    }

    btnRem->setEnabled( list->selectedItem() );
    btnUp->setEnabled( list->selectedItem() && list->selectedItem()->itemAbove() );
    btnDown->setEnabled( list->selectedItem() && list->selectedItem()->itemBelow() );
}

void ListEditor::slotEditChanged(int columnpos, const QString& text)
{
    if (list->selectedItem() && list->selectedItem()->text(columnpos) != text) {
        list->selectedItem()->setText(columnpos, text);
        Modified = true;
    }
}

void ListEditor::slotAdd()
{
    ListEditorItem *item = new ListEditorItem(list, list->childCount());
    list->sort();
    list->setSelected(item, true);
    Modified = true;
}

void ListEditor::slotRemove()
{
    ListEditorItem *item = (ListEditorItem*)list->selectedItem();
    if (! item) return;

    if (item->itemAbove())
        list->setSelected(item->itemAbove(), true);
    else if (item->itemBelow())
        list->setSelected(item->itemBelow(), true);

    ListEditorItem *i = item;
    while(i->itemBelow()) {
        i = (ListEditorItem*)i->itemBelow();
        i->setPosition(i->getPosition() - 1);
    }

    list->removeItem(item);
    slotListChanged();
    Modified = true;
}

void ListEditor::slotUp()
{
    if ( (! list->selectedItem()) || (! list->selectedItem()->itemAbove()) ) return;
    ((ListEditorItem*)list->selectedItem()->itemAbove())->moveItem( list->selectedItem() );
    slotListChanged();
    Modified = true;
}

void ListEditor::slotDown()
{
    if ( (! list->selectedItem()) || (! list->selectedItem()->itemBelow()) ) return;
    ((ListEditorItem*)list->selectedItem())->moveItem( list->selectedItem()->itemBelow() );
    slotListChanged();
    Modified = true;
}

/*** AutoRenamerListEditor ***/

AutoRenamerListEditor::AutoRenamerListEditor(QWidget *parent) : ListEditor(parent)
{
    addColumn(i18n("Search for"), i18n("Search for regular expression..."));
    addColumn(i18n("Replace with"), i18n("Replace searched regular expression with..."));
}

#include "listeditor.moc"
