/*
 *  Copyright (c) 2002 Patrick Julien <freak@codepimps.org>
 *                2004 Adrian Page <adrian@pagenet.plus.com>
 *
 *  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 Street, Fifth Floor, Boston, MA 02110-1301, USA.
 */
#include <tqlayout.h>
#include <tqtooltip.h>
#include <tqtoolbutton.h>
#include <tqcursor.h>
#include <tqeventloop.h>

#include <kdebug.h>
#include <tdeapplication.h>
#include <tdelocale.h>
#include <kprogress.h>
#include <kiconloader.h>

#include "kis_progress_subject.h"
#include "kis_label_progress.h"
#include "kis_cursor.h"

class EscapeButton : public TQToolButton {

public:

    EscapeButton(TQWidget * parent, const char * name) : TQToolButton(parent, name) {};

    void keyReleaseEvent(TQKeyEvent *e)
    {
        if (e->key()==TQt::Key_Escape)
            emit clicked();
    }
};

KisLabelProgress::KisLabelProgress(TQWidget *parent, const char *name, WFlags f) : super(parent, name, f)
{
    m_subject = 0;
    m_modal = false;

    TQHBoxLayout *box = new TQHBoxLayout(this);
    box->setAutoAdd(true);

    TQIconSet cancelIconSet = SmallIconSet("stop");

    m_cancelButton = new EscapeButton(this, "cancel_button");
    m_cancelButton->setIconSet(cancelIconSet);
    TQToolTip::add(m_cancelButton, i18n("Cancel"));
    connect(m_cancelButton, TQT_SIGNAL(clicked()), this, TQT_SLOT(cancelPressed()));

    m_bar = new KProgress(100, this);
}

KisLabelProgress::~KisLabelProgress()
{
}

void KisLabelProgress::setSubject(KisProgressSubject *subject, bool modal, bool canCancel)
{
    reset();

    if (subject) {
        m_subject = subject;
        m_modal = modal;

        connect(subject, TQT_SIGNAL(notifyProgress(int)), this, TQT_SLOT(update(int)));
        connect(subject, TQT_SIGNAL(notifyProgressStage(const TQString&, int)), this, TQT_SLOT(updateStage(const TQString&, int)));
        connect(subject, TQT_SIGNAL(notifyProgressDone()), this, TQT_SLOT(done()));
        connect(subject, TQT_SIGNAL(notifyProgressError()), this, TQT_SLOT(error()));
        connect(subject, TQT_SIGNAL(destroyed()), this, TQT_SLOT(subjectDestroyed()));

        show();

        if (canCancel) {
            if (modal) {
                kdDebug() << "grabbing 1\n";
                m_cancelButton->grabMouse();
                m_cancelButton->grabKeyboard();
            }
        }
        else {
            m_cancelButton->hide();

            if (modal) {
                // Only visible widgets can grab.
                kdDebug() << "grabbing 2\n";
                grabMouse();
                grabKeyboard();
            }
        }

        if (modal) {
            TQApplication::setOverrideCursor(KisCursor::waitCursor());
        }

        m_bar->setValue(0);
    }
}

bool KisLabelProgress::event(TQEvent * e)
{

    if (!e) return false;

    int type = e->type();

    switch (type) {
        case(KisProgress::ProgressEventBase + 1):
            {
                KisProgress::UpdateEvent * ue = dynamic_cast<KisProgress::UpdateEvent*>(e);
                update(ue->m_percent);
                break;
            }
        case(KisProgress::ProgressEventBase + 2):
            {
                KisProgress::UpdateStageEvent * use = dynamic_cast<KisProgress::UpdateStageEvent*>(e);
                updateStage(use->m_stage, use->m_percent);
                break;
            }
        case(KisProgress::ProgressEventBase + 3):
            done();
            break;
        case(KisProgress::ProgressEventBase + 4):
            error();
            break;
        case(KisProgress::ProgressEventBase + 5):
            subjectDestroyed();
            break;
        default:
            return TQLabel::event(e);
    };

    return true;
}

void KisLabelProgress::reset()
{
    if (m_subject) {
        m_subject->disconnect(this);
        m_subject = 0;

        if (m_modal) {
            TQApplication::restoreOverrideCursor();
        }

        m_modal = false;
    }

    releaseMouse();
    releaseKeyboard();
    m_cancelButton->releaseMouse();
    m_cancelButton->releaseKeyboard();
    hide();
}

void KisLabelProgress::update(int percent)
{
    m_bar->setValue(percent);

    TDEApplication *app = TDEApplication::kApplication();

    app->processEvents();
    // The following is safer, but makes cancel impossible:
    //TQApplication::eventLoop()->processEvents(TQEventLoop::ExcludeUserInput |
    //                                         TQEventLoop::ExcludeSocketNotifiers);
}

void KisLabelProgress::updateStage(const TQString&, int percent)
{
    m_bar->setValue(percent);

    TDEApplication *app = TDEApplication::kApplication();
    Q_ASSERT(app);

    app->processEvents();
}

void KisLabelProgress::cancelPressed()
{
    if (m_subject) {
        m_subject->cancel();
        reset();
    }
}

void KisLabelProgress::subjectDestroyed()
{
    reset();
}

void KisLabelProgress::done()
{
    reset();
}

void KisLabelProgress::error()
{
    reset();
}

#include "kis_label_progress.moc"

