/***********************************************************
             gafio.cpp
*  © Yves Ouvrard (Collatinus), 2010
* =======================================================================
    This file is part of Felix 34.

    Felix 34 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 3 of the License, or
    (at your option) any later version.

    Felix 34 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 Felix 34.  If not, see <http://www.gnu.org/licenses/>.

* =======================================================================
*/

#include <QtGui>
#include "gafio.h"
#include "felix.h"

Gxxxiv::Gxxxiv()
{
    cree_incipit ();
    QFrame * conteneur = new QFrame;

    lSaisie = new QLineEdit (this);
    QFont fonte;
    fonte.setPointSize (14);
    lSaisie->setFont (fonte);
    connect(lSaisie, SIGNAL(returnPressed()), this, SLOT(returnPressed()));
    bCh = new QPushButton ();
    bCh->setText ("Chercher");
    connect (bCh, SIGNAL(clicked()), this, SLOT(returnPressed()));
    bPrec = new QPushButton ();
    bPrec->setText ("p. prec. <<");
    connect (bPrec, SIGNAL(clicked()), this, SLOT(pPrec()));
    bSuiv = new QPushButton ();
    bSuiv->setText (">> p. suiv.");
    connect (bSuiv, SIGNAL(clicked()), this, SLOT(pSuiv()));
    commandes = new QWidget ();
    horizontalLayout = new QHBoxLayout (commandes);
    commandes->setLayout (horizontalLayout);
    horizontalLayout->addWidget (lSaisie);
    horizontalLayout->addWidget (bCh);
    horizontalLayout->addWidget (bPrec);
    horizontalLayout->addWidget (bSuiv);

    fleche = new QPushButton ();
    fleche->setMaximumHeight (12);
    fleche->setText ("^^^");
    fleche->hide ();
    connect (fleche, SIGNAL(clicked()), this, SLOT(lVisible ()));

    imageLabel = new QLabel;
    imageLabel->setBackgroundRole(QPalette::Base);
    imageLabel->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
    imageLabel->setScaledContents(true);
    
    scrollArea = new zScrollArea (this);
    scrollArea->setBackgroundRole(QPalette::Dark);
    scrollArea->setWidget(imageLabel);
    scrollArea->setCursor (Qt::OpenHandCursor);

    layout = new QVBoxLayout (conteneur);
    layout->addWidget (commandes);
    layout->addWidget (fleche);
    layout->addWidget(scrollArea);

    setCentralWidget (conteneur);
    setWindowTitle(tr("Felix 34"));
    resize(600, 900);
    folio = 1;
    scaleFactor = 1.0;
    QTimer::singleShot(7, this, SLOT(aide ()));
}

void Gxxxiv::returnPressed ()
{
	message = lSaisie->text ().trimmed ();
    message = message.toLower ();
	if (message.isEmpty ()) return;
    historique << message;
    if (historique.size () > 100) historique.removeFirst ();
    pHist = historique.size ();
    if (message.at (0) == '/')
    {
        if (message == "/aux") aide (); 
        else if (message == "/felix") about ();
        else if (message == "/exeo" || message == "/exit") close ();
        else if (message == "/i") zoomIn ();
        else if (message == "/o") zoomOut ();
        else if (message == "/p") pPrec (); 
        else if (message == "/s") pSuiv (); 
        else if (message == "/t") hauteur ();
        else if (message == "/y") largeur ();
    }
    else {
         
        folio = page_felix (message); 
        open ("tif/" + QString::number (page_felix (message)) + ".tif");
        lCachee ();
    }
    lSaisie->selectAll ();
}


void Gxxxiv::keyPressEvent (QKeyEvent *event)
{
    switch (event->key ())
    {
        case Qt::Key_Backspace: page_haut (); break;
        case Qt::Key_Escape: lCachee (); break;
        case Qt::Key_F: haut (); break;
        case Qt::Key_G: bas (); break;
        case Qt::Key_H: gauche (); break;
        case Qt::Key_Plus:
        case Qt::Key_I: zoomIn (); break;
        case Qt::Key_J: descend (); break;
        case Qt::Key_K: monte (); break;
        case Qt::Key_L: droite (); break;
        case Qt::Key_M: lVisible (); break;
        case Qt::Key_Minus:
        case Qt::Key_O: zoomOut (); break;
        case Qt::Key_P: pPrec (); break;
        case Qt::Key_Q: close (); break;
        case Qt::Key_S: pSuiv (); break;
        case Qt::Key_Space: page_bas (); break;
        case Qt::Key_T: hauteur (); break;
        case Qt::Key_Y: largeur (); break;
        case Qt::Key_Question: aide (); break;
    }
    if (!historique.isEmpty ())
    {
        if (event->key () == Qt::Key_Up && pHist > 0)
        {
            if (!lSaisie->text ().isEmpty ()) --pHist;
            lSaisie->setText (historique[pHist]);
        }
        else if (event->key () == Qt::Key_Down)
        {
            if (pHist < historique.size () - 1)
                lSaisie->setText (historique[++pHist]);
            else lSaisie->clear ();
        }
    }
}


void Gxxxiv::mousePressEvent (QMouseEvent *event)
{
    lastPos = event->pos();
}

void zScrollArea::wheelEvent (QWheelEvent *event)
{
  // 120 semble être la valeur donnée par un « cran » de la molette
  // de ma souris. G.K. le 25/08/2010
  // on zoome-dézoome uniquement quand Ctrl est enfoncé.
  int num = event->delta()/120;
  Qt::KeyboardModifiers mod = qApp->keyboardModifiers ();
  if (mod==Qt::ControlModifier){
    if (num > 0){
      for(int i=0; i<num; i++) mainWindow->zoomIn();
    } else{
      for(int i=0; i<-num; i++) mainWindow->zoomOut();
    }
    event->accept();
  } else {
    QScrollArea::wheelEvent (event);
  }
}

zScrollArea::zScrollArea(Gxxxiv * mainWindow){
  QScrollArea::QScrollArea();
  this->mainWindow=mainWindow;
}

void Gxxxiv::mouseMoveEvent (QMouseEvent *event)
{
    int dx = event->x() - lastPos.x();
    int dy = event->y() - lastPos.y();

    if (event->buttons() & Qt::LeftButton) 
    {
        // déplacer
        scrollArea->horizontalScrollBar()->setValue (scrollArea->horizontalScrollBar()->value () - dx);
        scrollArea->verticalScrollBar()->setValue (scrollArea->verticalScrollBar()->value () - dy);
    } 
    lastPos = event->pos();
}

void Gxxxiv::open (QString fileName)
{
    if (!fileName.isEmpty()) {
        fileName.prepend (qApp->applicationDirPath () + '/');
        QImage image(fileName);
        if (image.isNull()) {
            QMessageBox::information(this, tr("Felix 34"),
                                     tr("Ne puis charger %1.").arg(fileName));
            return;
        }
        pix = QPixmap::fromImage (image).scaledToWidth (scrollArea->width (), Qt::SmoothTransformation);
        imageLabel->setPixmap (pix);
        scaleImage (1.0);
    }
}

void Gxxxiv::pPrec ()
{
    folio--;
    QString fpage;
    QTextStream (&fpage) <<  "tif/" << QString::number (folio) << ".tif";
    open (fpage);
}

void Gxxxiv::pSuiv ()
{
    folio++;
    QString fpage;
    QTextStream (&fpage) << "tif/" << QString::number (folio) << ".tif";
    open (fpage);
}

void Gxxxiv::zoomIn()
{
    scaleImage(1.25);
}

void Gxxxiv::zoomOut()
{
    scaleImage(0.8);
}

void Gxxxiv::hauteur ()
{
    scaleFactor = 1.0;
    imageLabel->setPixmap(pix.scaledToHeight (scrollArea->height (), Qt::SmoothTransformation));
    imageLabel->adjustSize();
}

void Gxxxiv::largeur ()
{
    scaleFactor = 1.0;
    imageLabel->setPixmap(pix.scaledToWidth (scrollArea->width (), Qt::SmoothTransformation));
    imageLabel->adjustSize();
}

void Gxxxiv::lVisible ()
{
    fleche->hide ();
    commandes->show ();
    lSaisie->setFocus ();
}

void Gxxxiv::lCachee ()
{
    commandes->hide ();
    fleche->show ();
}

void Gxxxiv::scaleImage(double factor)
{
    scaleFactor *= factor;
    imageLabel->resize(scaleFactor * imageLabel->pixmap()->size());
    adjustScrollBar(scrollArea->horizontalScrollBar(), factor);
    adjustScrollBar(scrollArea->verticalScrollBar(), factor);
}

void Gxxxiv::adjustScrollBar(QScrollBar *scrollBar, double factor)
{
    scrollBar->setValue(int(factor * scrollBar->value()
                            + ((factor - 1) * scrollBar->pageStep()/2)));
}

void Gxxxiv::descend ()
{
    scrollArea->verticalScrollBar()->setValue (scrollArea->verticalScrollBar()->value () + 30);
}
void Gxxxiv::monte ()
{
    scrollArea->verticalScrollBar()->setValue (scrollArea->verticalScrollBar()->value () - 20);
}
void Gxxxiv::droite ()
{
    scrollArea->horizontalScrollBar()->setValue (scrollArea->horizontalScrollBar()->value () + 30);
}
void Gxxxiv::gauche ()
{
    scrollArea->horizontalScrollBar()->setValue (scrollArea->horizontalScrollBar()->value () - 30);
}

void Gxxxiv::bas ()
{
    scrollArea->verticalScrollBar()->setValue (scrollArea->verticalScrollBar()->maximum ());
}

void Gxxxiv::page_bas ()
{
    scrollArea->verticalScrollBar()->setValue (
          scrollArea->verticalScrollBar()->value () +
          scrollArea->verticalScrollBar()->pageStep ());
}

void Gxxxiv::haut ()
{
    scrollArea->verticalScrollBar()->setValue (scrollArea->verticalScrollBar()->minimum ());
}

void Gxxxiv::page_haut ()
{
    scrollArea->verticalScrollBar()->setValue (
          scrollArea->verticalScrollBar()->value () -
          scrollArea->verticalScrollBar()->pageStep ());
}

void Gxxxiv::about()
{
    QMessageBox::about(this, tr("De Gxxxiv"),
            QString::fromUtf8("<b>felix34</b><br>"
               "© Yves Ouvrard, 2009 - 2010<br>"
               "Licence du logiciel : GNU-GPL 3<br>"
               "Les données sont dans le domaine public. "
               "Merci à <p><b>Félix Gaffiot</b>,<br>"
               "à <b>Gérard Jeanneau</b> qui a scané le Gaffiot<br>"
               "à <b>Georges Khaznadar</b>,<br>"
               "et à <b>Wikimedia commons</b>."));
}

void Gxxxiv::aide ()
{
    open ("tif/0.tif");
}
