/****************************************************************************
** Dooble - The Secure Internet Web Browser
**
** Copyright (c) 2008, 2009, 2010 Alexis Megas,
** Gunther van Dooble, and the Dooble Team.
** All rights reserved.
**
** License: GPL2 only:
** 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; version 2 of the License only.
**
** 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
** or see here: http://www.gnu.org/licenses/gpl.html
**
** For the WebKit library, please see: http://webkit.org.
**
** THE CODE IS PROVIDED BY THE AUTHORS ''AS IS'' AND ANY
** EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
** IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
** PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
** ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
** DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
** GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
** INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
** IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
** ARISING IN ANY WAY OUT OF THE USE OF THIS APPLICATION, EVEN IF ADVISED
** OF THE POSSIBILITY OF SUCH DAMAGE.
**
** Please report all praise, requests, bugs, and problems to the project
** team and administrators: http://sf.net/projects/dooble.
**
** You can find us listed at our project page. New team members are welcome.
** The name of the authors should not be used to endorse or promote products
** derived from Dooble without specific prior written permission.
** If you use this code for other projects, please let us know.
**
** Web sites:
**   http://sf.net/projects/dooble
**   http://dooble.sf.net
****************************************************************************/

#include <QUrl>
#include <QFile>
#include <QPrinter>
#include <QSettings>
#include <QCloseEvent>
#include <QFileDialog>
#include <QTextStream>
#include <QPrintDialog>
#include <QDesktopServices>
#include <QPrintPreviewDialog>

#include "dooble.h"
#include "dpagesourcewindow.h"

dpagesourcewindow::dpagesourcewindow(const QUrl &url,
				     const QString &html):QMainWindow()
{
  ui.setupUi(this);
#ifdef Q_WS_MAC
  setAttribute(Qt::WA_MacMetalStyle, false);
  statusBar()->setSizeGripEnabled(false);
#endif
  ui.textBrowser->setPlainText(html);
  connect(ui.actionPrint, SIGNAL(triggered(void)), this,
	  SLOT(slotPrint(void)));
  connect(ui.actionPrint_Preview, SIGNAL(triggered(void)), this,
	  SLOT(slotPrintPreview(void)));
  connect(ui.actionClose, SIGNAL(triggered(void)), this,
	  SLOT(slotClose(void)));
  connect(ui.actionFind, SIGNAL(triggered(void)), this,
	  SLOT(slotShowFind(void)));
  connect(ui.actionSave_As, SIGNAL(triggered(void)), this,
	  SLOT(slotSavePageAs(void)));
  connect(ui.hideFindToolButton, SIGNAL(clicked(void)), this,
	  SLOT(slotHideFind(void)));
  connect(ui.findLineEdit, SIGNAL(returnPressed(void)), this,
	  SLOT(slotNextFind(void)));
  connect(ui.findLineEdit, SIGNAL(textEdited(const QString &)), this,
	  SLOT(slotNextFind(const QString &)));
  connect(ui.actionWrap_Lines, SIGNAL(toggled(bool)),
	  this, SLOT(slotWrapLines(bool)));
  connect(ui.nextToolButton, SIGNAL(clicked(void)),
	  this, SLOT(slotNextFind(void)));
  connect(ui.previousToolButton, SIGNAL(clicked(void)),
	  this, SLOT(slotPreviousFind(void)));

  if(!url.isEmpty())
    setWindowTitle(tr("Dooble Web Browser - Page Source (") +
		   url.toString(QUrl::StripTrailingSlash) + tr(")"));
  else
    setWindowTitle(tr("Dooble Web Browser - Page Source"));

  if(url.path().isEmpty() || url.path() == "/")
    fileName = "source";
  else if(url.path().contains("/"))
    {
      fileName = url.path();
      fileName = fileName.mid(fileName.lastIndexOf("/") + 1);
    }
  else
    fileName = url.path();

  ui.actionWrap_Lines->setChecked
    (dooble::s_settings.value("pageSource/wrapLines", false).toBool());
  slotWrapLines(ui.actionWrap_Lines->isChecked());
  slotSetIcons();
  slotHideFind();
  show();
}

dpagesourcewindow::~dpagesourcewindow()
{
}

void dpagesourcewindow::slotClose(void)
{
  close();
}

void dpagesourcewindow::closeEvent(QCloseEvent *event)
{
  deleteLater();
  QMainWindow::closeEvent(event);
}

void dpagesourcewindow::slotPrint(void)
{
  QPrinter printer;
  QPrintDialog printDialog(&printer, this);

#ifdef Q_WS_MAC
  printDialog.setAttribute(Qt::WA_MacMetalStyle, false);
#endif

  if(printDialog.exec() == QDialog::Accepted)
    ui.textBrowser->print(&printer);
}

void dpagesourcewindow::slotPrintPreview(void)
{
  QPrinter printer;
  QPrintPreviewDialog printDialog(&printer, this);

#ifdef Q_WS_MAC
  printDialog.setAttribute(Qt::WA_MacMetalStyle, false);
#endif
  printDialog.setWindowModality(Qt::WindowModal);
  connect(&printDialog,
	  SIGNAL(paintRequested(QPrinter *)),
	  this,
	  SLOT(slotTextEditPrintPreview(QPrinter *)));

  if(printDialog.exec() == QDialog::Accepted)
    ui.textBrowser->print(&printer);
}

void dpagesourcewindow::slotTextEditPrintPreview(QPrinter *printer)
{
  if(printer)
    ui.textBrowser->print(printer);
}

void dpagesourcewindow::slotHideFind(void)
{
  ui.findFrame->setVisible(false);
}

void dpagesourcewindow::slotShowFind(void)
{
  ui.findFrame->setVisible(true);
  ui.findLineEdit->setFocus();
  ui.findLineEdit->selectAll();

#ifdef Q_WS_MAC
  static int fixed = 0;

  if(!fixed)
    {
      QColor color(255, 255, 255);
      QPalette palette(ui.findLineEdit->palette());

      palette.setColor(ui.findLineEdit->backgroundRole(), color);
      ui.findLineEdit->setPalette(palette);
      fixed = 1;
    }
#endif
}

void dpagesourcewindow::keyPressEvent(QKeyEvent *event)
{
  if(event && event->key() == Qt::Key_Escape)
    ui.findFrame->setVisible(false);

  QMainWindow::keyPressEvent(event);
}

void dpagesourcewindow::slotNextFind(void)
{
  slotNextFind(ui.findLineEdit->text());
}

void dpagesourcewindow::slotNextFind(const QString &text)
{
  static QPalette lineEditPalette(ui.findLineEdit->palette());
  QTextDocument::FindFlags findFlags = 0;

  if(ui.matchCaseCheckBox->isChecked())
    findFlags |= QTextDocument::FindCaseSensitively;

  if(ui.textBrowser->find(text, findFlags) || text.isEmpty())
    {
      ui.findLineEdit->setPalette(lineEditPalette);

      if(text.isEmpty())
	ui.textBrowser->moveCursor(QTextCursor::PreviousCharacter);
    }
  else
    {
      if(ui.textBrowser->textCursor().anchor() ==
	 ui.textBrowser->textCursor().position())
	{
	  if(!ui.textBrowser->textCursor().atEnd())
	    {
	      QColor color(240, 128, 128); // Light Coral
	      QPalette palette(ui.findLineEdit->palette());

	      palette.setColor(ui.findLineEdit->backgroundRole(), color);
	      ui.findLineEdit->setPalette(palette);
	    }
	  else
	    ui.textBrowser->moveCursor(QTextCursor::Start);
	}
      else
	{
	  ui.textBrowser->moveCursor(QTextCursor::Start);
	  slotNextFind(text);
	}
    }
}

void dpagesourcewindow::slotPreviousFind(void)
{
  slotPreviousFind(ui.findLineEdit->text());
}

void dpagesourcewindow::slotPreviousFind(const QString &text)
{
  static QPalette lineEditPalette(ui.findLineEdit->palette());
  QTextDocument::FindFlags findFlags = QTextDocument::FindBackward;

  if(ui.matchCaseCheckBox->isChecked())
    findFlags |= QTextDocument::FindCaseSensitively;

  if(ui.textBrowser->find(text, findFlags) || text.isEmpty())
    ui.findLineEdit->setPalette(lineEditPalette);
  else
    {
      if(ui.textBrowser->textCursor().anchor() ==
	 ui.textBrowser->textCursor().position())
	{
	  QColor color(240, 128, 128); // Light Coral
	  QPalette palette(ui.findLineEdit->palette());

	  palette.setColor(ui.findLineEdit->backgroundRole(), color);
	  ui.findLineEdit->setPalette(palette);
	}
      else
	{
	  ui.textBrowser->moveCursor(QTextCursor::End);
	  slotPreviousFind(text);
	}
    }
}

void dpagesourcewindow::slotSavePageAs(void)
{
  QString path(dooble::s_settings.value("settingsWindow/myRetrievedFiles",
					"").toString());
  QFileInfo fileInfo(path);
  QFileDialog fileDialog(this);

  if(!fileInfo.isReadable() || !fileInfo.isWritable())
    path = QDesktopServices::storageLocation
      (QDesktopServices::DesktopLocation);

#ifdef Q_WS_MAC
  fileDialog.setAttribute(Qt::WA_MacMetalStyle, false);
#endif
  fileDialog.setWindowTitle(tr("Dooble Web Browser: Save Page Source As"));
  fileDialog.setFileMode(QFileDialog::AnyFile);
  fileDialog.setDirectory(path);
  fileDialog.setLabelText(QFileDialog::Accept, tr("&Save"));
  fileDialog.setAcceptMode(QFileDialog::AcceptSave);
  fileDialog.selectFile(fileName);

  if(fileDialog.exec() == QDialog::Accepted)
    {
      QStringList list(fileDialog.selectedFiles());

      if(!list.isEmpty())
	{
	  QFile file(list.at(0));

	  if(file.open(QIODevice::WriteOnly | QIODevice::Text))
	    {
	      QTextStream out(&file);

	      out << ui.textBrowser->toPlainText();
	      file.close();
	    }
	}
    }
}

void dpagesourcewindow::slotWrapLines(bool checked)
{
  QSettings settings;

  settings.setValue("pageSource/wrapLines", checked);
  dooble::s_settings["pageSource/wrapLines"] = checked;

  if(checked)
    ui.textBrowser->setLineWrapMode(QTextEdit::WidgetWidth);
  else
    ui.textBrowser->setLineWrapMode(QTextEdit::NoWrap);
}

void dpagesourcewindow::slotSetIcons(void)
{
  QSettings settings
    (dooble::s_settings.value("iconSet").toString(), QSettings::IniFormat);

  settings.beginGroup("pageSourceWindow");
  ui.actionPrint->setIcon(QIcon(settings.value("actionPrint").toString()));
  ui.actionPrint_Preview->setIcon
    (QIcon(settings.value("actionPrint_Preview").toString()));
  ui.actionClose->setIcon(QIcon(settings.value("actionClose").toString()));
  ui.actionFind->setIcon(QIcon(settings.value("actionFind").toString()));
  ui.actionSave_As->setIcon
    (QIcon(settings.value("actionSave_As").toString()));
  ui.hideFindToolButton->setIcon
    (QIcon(settings.value("hideFindToolButton").toString()));
  ui.nextToolButton->setIcon
    (QIcon(settings.value("nextToolButton").toString()));
  ui.previousToolButton->setIcon
    (QIcon(settings.value("previousToolButton").toString()));
  setWindowIcon(QIcon(settings.value("windowIcon").toString()));
}
