/***************************************************************************
                          sq_previewwidget.cpp  -  description
                             -------------------
    begin                : ??? Mar 13 2007
    copyright            : (C) 2007 by Baryshev Dmitry
    email                : ksquirrel.iv@gmail.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.                                   *
 *                                                                         *
 ***************************************************************************/

#ifdef HAVE_CONFIG_H
#include "config.h"
#endif

#include <tqsize.h>
#include <tqimage.h>
#include <tqpainter.h>

#include <tdelocale.h>
#include <tdefileitem.h>
#include <tdepopupmenu.h>
#include <kcolordialog.h>
#include <tdeio/global.h>

#include <ksquirrel-libs/fmt_defs.h>

#include "ksquirrel.h"
#include "sq_previewwidget.h"
#include "sq_iconloader.h"
#include "sq_imageloader.h"
#include "sq_libraryhandler.h"
#include "sq_config.h"
#include "sq_downloader.h"
#include "sq_utils.h"

#ifdef SQ_HAVE_KEXIF
#include <libkexif/kexifdata.h>
#include <algorithm>
#include "sq_utils.h"
#endif

SQ_PreviewWidget * SQ_PreviewWidget::m_inst = 0;

SQ_PreviewWidget::SQ_PreviewWidget(TQWidget *parent, const char *name)
    : TQWidget(parent, name, TQt::WNoAutoErase), all(0), small(0), m_ignore(true)
{
    m_inst = this;

    rereadColor();

    down = new SQ_Downloader(this);
    connect(down, TQ_SIGNAL(result(const KURL &)), this, TQ_SLOT(slotDownloadResult(const KURL &)));
    connect(down, TQ_SIGNAL(percents(int)), this, TQ_SLOT(slotDownloadPercents(int)));

    popup = new TDEPopupMenu;
    popup->insertItem(i18n("Background color..."), this, TQ_SLOT(slotBackground()));
    popup->insertItem(i18n("Text color..."), this, TQ_SLOT(slotText()));
    popup->insertSeparator();
    popup->insertItem(i18n("Go to first image")+"\tHome", this, TQ_SIGNAL(first()));
    popup->insertItem(i18n("Next image")+"\tSpace", this, TQ_SIGNAL(next()));
    popup->insertItem(i18n("Previous image")+"\tBackSpace", this, TQ_SIGNAL(previous()));
    popup->insertItem(i18n("Go to last image")+"\tEnd", this, TQ_SIGNAL(last()));
    popup->insertSeparator();
    popup->insertItem(i18n("Execute")+"\tEnter", this, TQ_SIGNAL(execute()));

    multi_pix = SQ_IconLoader::instance()->loadIcon("application-vnd.tde.tdemultiple", TDEIcon::Desktop, TDEIcon::SizeSmall);

    setMinimumHeight(20);
    setFocusPolicy(TQWidget::WheelFocus);
}

SQ_PreviewWidget::~SQ_PreviewWidget()
{
    delete popup;
    delete small;
    delete all;
}

void SQ_PreviewWidget::load(const KURL &_url)
{
    if(SQ_LibraryHandler::instance()->maybeSupported(_url) == SQ_LibraryHandler::No)
        return;

    if(!percentString.isEmpty())
    {
        percentString = TQString();
        update();
    }

    down->kill();

    if(m_forceignore || m_ignore)
    {
        pending = m_url = _url;
        return;
    }
    else
        pending = KURL();

    m_url = _url;

    if(m_url.isLocalFile())
        slotDownloadResult(m_url);
    else
    {
        KFileItem fi(KFileItem::Unknown, KFileItem::Unknown, m_url);
        down->start(&fi);
    }
}

void SQ_PreviewWidget::fitAndConvert()
{
    if(!m_ignore && fit())
        pixmap.convertFromImage(small?*small:*all);
}

void SQ_PreviewWidget::resizeEvent(TQResizeEvent *)
{
    fitAndConvert();
}

void SQ_PreviewWidget::paintEvent(TQPaintEvent *)
{
    TQPainter p(this);

    p.fillRect(rect(), color);

    int x = 4;

    if(!percentString.isEmpty())
    {
        TQFont fnt = p.font();
        fnt.setBold(true);
        p.setFont(fnt);
        p.setPen(colorText);
        p.drawText(x, 4, width(), height(), TQt::AlignLeft, percentString);
    }

    if(!m_ignore && !pixmap.isNull())
    {
        p.drawPixmap((width() - pixmap.width()) / 2, (height() - pixmap.height()) / 2, pixmap);

        if(multi)
        {
            x = x + multi_pix.width() + 4;
            p.drawPixmap(4, 4, multi_pix);
        }

        if(dim)
        {
            TQFont fnt = p.font();
            fnt.setBold(true);
            p.setFont(fnt);
            p.setPen(colorText);
            p.drawText(x, 4, width(), height(), TQt::AlignLeft, dimstring);
        }
    }
}

bool SQ_PreviewWidget::fit()
{
    if(!all)
        return false;

    // image is bigger than preview widget -
    // scale it down
    if(width() < 2 || height() < 2)
        return false;

    delete small;
    small = 0;

    if(all->width() > width() || all->height() > height())
    {
        small = new TQImage();

        *small = SQ_Utils::scale(*all, width(), height(), SQ_Utils::SMOOTH_FAST, TQImage::ScaleMin);
    }

    return true;
}

void SQ_PreviewWidget::saveValues()
{
    SQ_Config::instance()->setGroup("Sidebar");
    SQ_Config::instance()->writeEntry("preview_background", color.name());
    SQ_Config::instance()->writeEntry("preview_text", colorText.name());
}

void SQ_PreviewWidget::rereadColor()
{
    SQ_Config::instance()->setGroup("Sidebar");
    bool b = SQ_Config::instance()->readBoolEntry("preview", true);
    m_forceignore = !b;
    setShown(b);
    color.setNamedColor(SQ_Config::instance()->readEntry("preview_background", "#4e4e4e"));
    dim = SQ_Config::instance()->readBoolEntry("preview_text_enable", true);
    colorText.setNamedColor(SQ_Config::instance()->readEntry("preview_text", "#ffffff"));
    m_delay = SQ_Config::instance()->readNumEntry("preview_delay", 400);
    m_cancel = SQ_Config::instance()->readBoolEntry("preview_dont", true);

    if(m_delay < 50 || m_delay > 2000)
        m_delay = 400;
}


void SQ_PreviewWidget::slotBackground()
{
    KColorDialog dlg(KSquirrel::app(), 0, true);

    dlg.setColor(color);

    if(dlg.exec() == TQDialog::Accepted)
    {
        color = dlg.color();
        saveValues();
        update();
    }
}

void SQ_PreviewWidget::slotText()
{
    KColorDialog dlg(KSquirrel::app(), 0, true);

    dlg.setColor(colorText);

    if(dlg.exec() == TQDialog::Accepted)
    {
        colorText = dlg.color();
        saveValues();
        update();
    }
}

void SQ_PreviewWidget::mousePressEvent(TQMouseEvent *e)
{
    e->accept();

    if(e->button() == TQt::RightButton)
        popup->exec(e->globalPos());
}

void SQ_PreviewWidget::loadPending()
{
    if(pending.isValid())
    {
        KURL tmp = pending;
        load(tmp);
    }
}

void SQ_PreviewWidget::slotDownloadResult(const KURL &url)
{
    percentString = TQString();
    TQString path = url.path();
    fmt_info *finfo;
    RGBA *bits;

    // load first page
    bool b = SQ_ImageLoader::instance()->loadImage(path, SQ_CodecSettings::ImageViewer, true, 2);

    finfo = SQ_ImageLoader::instance()->info();
    bits = SQ_ImageLoader::instance()->bits();

    // memory allocation failed in SQ_ImageLoader::loadImage()
    if(!b || !bits || !finfo->image.size())
        return;

    delete small;
    delete all;
    all = small = 0;
    pixmap = TQPixmap();

    int w = finfo->image[0].w;
    int h = finfo->image[0].h;
    dimstring = TQString::fromLatin1("%1x%2").arg(w).arg(h);

    const int wh = w * h;
    unsigned char t;

    for(int i = 0;i < wh;i++)
    {
        t = (bits+i)->r;
        (bits+i)->r = (bits+i)->b;
        (bits+i)->b = t;
    }

    all = new TQImage((uchar *)bits, w, h, 32, 0, 0, TQImage::LittleEndian);
    all->setAlphaBuffer(true);

#ifdef SQ_HAVE_KEXIF
    KExifData data;
    data.readFromFile(path);
    int O = data.getImageQt::Orientation();

    if(O != KExifData::UNSPECIFIED && O != KExifData::NORMAL)
    {
        // copy original image
        TQImage img = *all;

        // rotate image
        SQ_Utils::exifRotate(TQString(), img, O);

        // transfer back
        *all = img;
    }
    else
#endif
    *all = all->copy();

    multi = finfo->image.size() > 1;

    SQ_ImageLoader::instance()->cleanup();

    fitAndConvert();
    update();
}

void SQ_PreviewWidget::keyPressEvent(TQKeyEvent *e)
{
    e->accept();

    int key = e->key();

    if(key == TQt::Key_PageDown || key == TQt::Key_Space)
        emit next();
    else if(key == TQt::Key_PageUp || key == TQt::Key_BackSpace)
        emit previous();
    else if(key == TQt::Key_Return || key == TQt::Key_Enter)
        emit execute();
    else if(key == TQt::Key_Home)
        emit first();
    else if(key == TQt::Key_End)
        emit last();
}

void SQ_PreviewWidget::wheelEvent(TQWheelEvent *e)
{
    if(e->delta() < 0)
        emit next();
    else
        emit previous();
}

void SQ_PreviewWidget::mouseDoubleClickEvent(TQMouseEvent *e)
{
    e->accept();
    emit execute();
}

void SQ_PreviewWidget::slotDownloadPercents(int p)
{
    percentString = i18n("Downloading...") + ' ' + TDEIO::convertSize(p);
    update();
}

#include "sq_previewwidget.moc"
