/*****
*
* TOra - An Oracle Toolkit for DBA's and developers
* Copyright (C) 2003-2005 Quest Software, Inc
* Portions Copyright (C) 2005 Other Contributors
* 
* 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;  only version 2 of
* the License is valid for this program.
* 
* 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., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
*
*      As a special exception, you have permission to link this program
*      with the Oracle Client libraries and distribute executables, as long
*      as you follow the requirements of the GNU GPL in regard to all of the
*      software in the executable aside from Oracle client libraries.
*
*      Specifically you are not permitted to link this program with the
*      Qt/UNIX, Qt/Windows or Qt Non Commercial products of TrollTech.
*      And you are not permitted to distribute binaries compiled against
*      these libraries without written consent from Quest Software, Inc.
*      Observe that this does not disallow linking to the Qt Free Edition.
*
*      You may link this product with any GPL'd Qt library such as Qt/Free
*
* All trademarks belong to their respective owners.
*
*****/

#include "utils.h"

#include "toconf.h"
#include "tohighlightedtext.h"
#include "tomarkedtext.h"
#include "tomemoeditor.h"
#include "toresultview.h"

#include <qcheckbox.h>
#include <qheader.h>
#include <qlabel.h>
#include <qlayout.h>
#include <qpixmap.h>
#include <qtoolbar.h>
#include <qtoolbutton.h>

#include "tomemoeditor.moc"

#include "icons/commit.xpm"
#include "icons/copy.xpm"
#include "icons/cut.xpm"
#include "icons/fileopen.xpm"
#include "icons/filesave.xpm"
#include "icons/forward.xpm"
#include "icons/next.xpm"
#include "icons/paste.xpm"
#include "icons/previous.xpm"
#include "icons/rewind.xpm"

class toMemoText : public toMarkedText
{
    toMemoEditor *MemoEditor;
public:
    toMemoText(toMemoEditor *edit, QWidget *parent, const char *name = NULL)
            : toMarkedText(parent, name), MemoEditor(edit)
    { }
    virtual void keyPressEvent(QKeyEvent *e)
    {
        if (toCheckKeyEvent(e, QKeySequence(qApp->translate("toMemoEditor", "Ctrl+Return", "Memo Editor|Save changes"))))
        {
            MemoEditor->store();
            e->accept();
        }
        else
        {
            toMarkedText::keyPressEvent(e);
        }
    }
};

class toMemoSQL : public toHighlightedText
{
    toMemoEditor *MemoEditor;
public:
    toMemoSQL(toMemoEditor *edit, QWidget *parent, const char *name = NULL)
            : toHighlightedText(parent, name), MemoEditor(edit)
    { }
    virtual void keyPressEvent(QKeyEvent *e)
    {
        if (toCheckKeyEvent(e, QKeySequence(qApp->translate("toMemoEditor", "Ctrl+Return", "Memo Editor|Save changes"))))
        {
            MemoEditor->store();
            e->accept();
        }
        else
        {
            toHighlightedText::keyPressEvent(e);
        }
    }
};

void toMemoEditor::openFile(void)
{
    Editor->editOpen();
}

void toMemoEditor::saveFile(void)
{
    Editor->editSave(true);
}

toMemoEditor::toMemoEditor(QWidget *parent, const QString &str, int row, int col,
                           bool sql, bool modal, bool navigation)
        : QDialog(parent, NULL, modal, modal ? 0 : WDestructiveClose), Row(row), Col(col)
{
    setMinimumSize(400, 300);
    QDesktopWidget *paramDesktop = new QDesktopWidget;
    setMaximumWidth(paramDesktop->availableGeometry(this).width()*2/3);

    setCaption("Memo Editor");

    QBoxLayout *l = new QVBoxLayout(this);

    Toolbar = toAllocBar(this, tr("Memo Editor"));
    l->addWidget(Toolbar);

    if (sql)
        Editor = new toMemoSQL(this, this);
    else
        Editor = new toMemoText(this, this);
    l->addWidget(Editor);
    Editor->setReadOnly(Row < 0 || Col < 0 || listView());
    Editor->setFocus();

    QToolButton *btn;
    if (Row >= 0 && Col >= 0 && !listView())
    {
        new QToolButton(QPixmap(const_cast<const char**>(commit_xpm)),
                        tr("Save changes"),
                        tr("Save changes"),
                        this, SLOT(store(void)),
                        Toolbar);
        Toolbar->addSeparator();
        new QToolButton(QPixmap(const_cast<const char**>(fileopen_xpm)),
                        tr("Open file"),
                        tr("Open file"),
                        this, SLOT(openFile()), Toolbar);
        new QToolButton(QPixmap(const_cast<const char**>(filesave_xpm)),
                        tr("Save file"),
                        tr("Save file"),
                        this, SLOT(saveFile()), Toolbar);
        Toolbar->addSeparator();
        btn = new QToolButton(QPixmap(const_cast<const char**>(cut_xpm)),
                              tr("Cut to clipboard"),
                              tr("Cut to clipboard"),
                              Editor, SLOT(cut()), Toolbar);
        connect(Editor, SIGNAL(copyAvailable(bool)),
                btn, SLOT(setEnabled(bool)));
        btn->setEnabled(false);
    }
    else
    {
        new QToolButton(QPixmap(const_cast<const char**>(filesave_xpm)),
                        tr("Save file"),
                        tr("Save file"),
                        this, SLOT(saveFile()), Toolbar);
        Toolbar->addSeparator();
    }
    btn = new QToolButton(QPixmap(const_cast<const char**>(copy_xpm)),
                          tr("Copy to clipboard"),
                          tr("Copy to clipboard"),
                          Editor, SLOT(copy()), Toolbar);
    connect(Editor, SIGNAL(copyAvailable(bool)),
            btn, SLOT(setEnabled(bool)));
    btn->setEnabled(false);
    if (Row >= 0 && Col >= 0 && !listView())
        new QToolButton(QPixmap(const_cast<const char**>(paste_xpm)),
                        tr("Paste from clipboard"),
                        tr("Paste from clipboard"),
                        Editor, SLOT(paste()), Toolbar);

    toListView *lst = listView();
    if (lst || navigation)
    {
        Toolbar->addSeparator();
        new QToolButton(QPixmap(const_cast<const char**>(rewind_xpm)),
                        tr("First column"),
                        tr("First column"),
                        this, SLOT(firstColumn()), Toolbar);
        new QToolButton(QPixmap(const_cast<const char**>(previous_xpm)),
                        tr("Previous column"),
                        tr("Previous column"),
                        this, SLOT(previousColumn()), Toolbar);
        new QToolButton(QPixmap(const_cast<const char**>(next_xpm)),
                        tr("Next column"),
                        tr("Next column"),
                        this, SLOT(nextColumn()), Toolbar);
        new QToolButton(QPixmap(const_cast<const char**>(forward_xpm)),
                        tr("Last column"),
                        tr("Last column"),
                        this, SLOT(lastColumn()), Toolbar);
    }
    Toolbar->addSeparator();
    Null = new QCheckBox(tr("NULL"), Toolbar, TO_KDE_TOOLBAR_WIDGET);
    connect(Null, SIGNAL(toggled(bool)), this, SLOT(null(bool)));
    Null->setEnabled(!Editor->isReadOnly());
    Null->setFocusPolicy(StrongFocus);

    setText(str);

    Label = new QLabel(Toolbar, TO_KDE_TOOLBAR_WIDGET);
    Label->setAlignment(AlignRight | AlignVCenter);
    Toolbar->setStretchableWidget(Label);

    if (lst)
    {
        connect(parent, SIGNAL(currentChanged(QListViewItem *)),
                this, SLOT(changeCurrent(QListViewItem *)));
        Label->setText(QString::fromLatin1("<B>") +
                       lst->header()->label(Col) +
                       QString::fromLatin1("</B>"));
    }

    if (!modal)
        show();
}

void toMemoEditor::setText(const QString &str)
{
    Editor->setText(str);
    Null->setChecked(str.isNull());
    Editor->setModified(false);
}

void toMemoEditor::null(bool nul)
{
    Editor->setModified(true);
    Editor->setDisabled(nul);
}

QString toMemoEditor::text(void)
{
    return Editor->text();
}

void toMemoEditor::store(void)
{
    if (Editor->isReadOnly())
        return ;
    if (Editor->isModified())
    {
        if (!Editor->isEnabled())
            emit changeData(Row, Col, QString::null);
        else
            emit changeData(Row, Col, Editor->text());
    }
    accept();
}

void toMemoEditor::changePosition(int row, int cols)
{
    if (Editor->isModified())
    {
        if (!Editor->isEnabled())
            emit changeData(Row, Col, QString::null);
        else
            emit changeData(Row, Col, Editor->text());
        Editor->setModified(false);
    }

    toListView *lst = listView();
    if (lst)
        Label->setText(QString::fromLatin1("<B>") +
                       lst->header()->label(Col) +
                       QString::fromLatin1("</B>"));

    Row = row;
    Col = cols;
}

toListView *toMemoEditor::listView(void)
{
    return dynamic_cast<toListView *>(parentWidget());
}

void toMemoEditor::firstColumn(void)
{
    toListView *lst = listView();
    if (lst)
    {
        QListViewItem *cur = lst->currentItem();
        if (!cur)
            return ;

        if (Col == 0)
        {
            QListViewItem *item = lst->firstChild();
            QListViewItem *next = item;
            while (next && next != cur)
            {
                item = next;
                if (item->firstChild())
                    next = item->firstChild();
                else if (item->nextSibling())
                    next = item->nextSibling();
                else
                {
                    next = item;
                    do
                    {
                        next = next->parent();
                    }
                    while (next && !next->nextSibling());
                    if (next)
                        next = next->nextSibling();
                }
            }
            lst->setCurrentItem(item);
        }
        else
        {
            Col = 0;
            Label->setText("<B>" + lst->header()->label(Col) + "</B>");

            toResultViewItem *resItem = dynamic_cast<toResultViewItem *>(cur);
            toResultViewCheck *chkItem = dynamic_cast<toResultViewCheck *>(cur);
            if (resItem)
                setText(resItem->allText(Col));
            else if (chkItem)
                setText(chkItem->allText(Col));
            else
                setText(cur->text(Col));
        }
    }
}

void toMemoEditor::previousColumn(void)
{
    toListView *lst = listView();
    if (lst)
    {
        QListViewItem *cur = lst->currentItem();
        if (!cur)
            return ;

        if (Col == 0)
        {
            Col = lst->columns() - 1;
            QListViewItem *item = lst->firstChild();
            QListViewItem *next = item;
            while (next && next != cur)
            {
                item = next;
                if (item->firstChild())
                    next = item->firstChild();
                else if (item->nextSibling())
                    next = item->nextSibling();
                else
                {
                    next = item;
                    do
                    {
                        next = next->parent();
                    }
                    while (next && !next->nextSibling());
                    if (next)
                        next = next->nextSibling();
                }
            }
            if (item != cur)
            {
                lst->setCurrentItem(item);
                cur = NULL;
            }
        }
        else
            Col--;

        if (cur)
        {
            toResultViewItem *resItem = dynamic_cast<toResultViewItem *>(cur);
            toResultViewCheck *chkItem = dynamic_cast<toResultViewCheck *>(cur);
            if (resItem)
                setText(resItem->allText(Col));
            else if (chkItem)
                setText(chkItem->allText(Col));
            else
                setText(cur->text(Col));
        }
        Label->setText(QString::fromLatin1("<B>") +
                       lst->header()->label(Col) +
                       QString::fromLatin1("</B>"));
    }
}

void toMemoEditor::nextColumn(void)
{
    toListView *lst = listView();
    if (lst)
    {
        QListViewItem *cur = lst->currentItem();
        if (!cur)
            return ;

        if (Col == lst->columns() - 1)
        {
            Col = 0;
            QListViewItem *next = cur;
            if (cur->firstChild())
                next = cur->firstChild();
            else if (cur->nextSibling())
                next = cur->nextSibling();
            else
            {
                next = cur;
                do
                {
                    next = next->parent();
                }
                while (next && !next->nextSibling());
                if (next)
                    next = next->nextSibling();
            }
            if (next)
            {
                lst->setCurrentItem(next);
                cur = NULL;
            }
        }
        else
            Col++;
        if (cur)
        {
            toResultViewItem *resItem = dynamic_cast<toResultViewItem *>(cur);
            toResultViewCheck *chkItem = dynamic_cast<toResultViewCheck *>(cur);
            if (resItem)
                setText(resItem->allText(Col));
            else if (chkItem)
                setText(chkItem->allText(Col));
            else
                setText(cur->text(Col));
        }
        Label->setText(QString::fromLatin1("<B>") +
                       lst->header()->label(Col) +
                       QString::fromLatin1("</B>"));
    }
}

void toMemoEditor::lastColumn(void)
{
    toListView *lst = listView();
    if (lst)
    {
        QListViewItem *cur = lst->currentItem();
        if (!cur)
            return ;

        if (Col == lst->columns() - 1)
        {
            QListViewItem *next = cur;
            if (cur->firstChild())
                next = cur->firstChild();
            else if (cur->nextSibling())
                next = cur->nextSibling();
            else
            {
                next = cur;
                do
                {
                    next = next->parent();
                }
                while (next && !next->nextSibling());
                if (next)
                    next = next->nextSibling();
            }
            if (next)
                lst->setCurrentItem(next);
        }
        else
        {
            Col = lst->columns() - 1;
            Label->setText(QString::fromLatin1("<B>") +
                           lst->header()->label(Col) +
                           QString::fromLatin1("</B>"));
            toResultViewItem *resItem = dynamic_cast<toResultViewItem *>(cur);
            toResultViewCheck *chkItem = dynamic_cast<toResultViewCheck *>(cur);
            if (resItem)
                setText(resItem->allText(Col));
            else if (chkItem)
                setText(chkItem->allText(Col));
            else
                setText(cur->text(Col));
        }
    }
}

void toMemoEditor::changeCurrent(QListViewItem *)
{
    toListView *lst = listView();
    if (lst)
    {
        QListViewItem *cur = lst->currentItem();
        if (!cur)
            return ;

        toResultViewItem *resItem = dynamic_cast<toResultViewItem *>(cur);
        toResultViewCheck *chkItem = dynamic_cast<toResultViewCheck *>(cur);
        if (resItem)
            setText(resItem->allText(Col));
        else if (chkItem)
            setText(chkItem->allText(Col));
        else
            setText(cur->text(Col));
    }
}
