blob: 0b8cc0c7bf9ae642914c73a0125a77bc9524adcd [file] [log] [blame]
/****************************************************************************
**
** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the Qt Assistant of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** GNU Lesser General Public License Usage
** This file may be used under the terms of the GNU Lesser General Public
** License version 2.1 as published by the Free Software Foundation and
** appearing in the file LICENSE.LGPL included in the packaging of this
** file. Please review the following information to ensure the GNU Lesser
** General Public License version 2.1 requirements will be met:
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU General
** Public License version 3.0 as published by the Free Software Foundation
** and appearing in the file LICENSE.GPL included in the packaging of this
** file. Please review the following information to ensure the GNU General
** Public License version 3.0 requirements will be met:
** http://www.gnu.org/copyleft/gpl.html.
**
** Other Usage
** Alternatively, this file may be used in accordance with the terms and
** conditions contained in a signed written agreement between you and Nokia.
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
#include "tracer.h"
#include "installdialog.h"
#include <QtCore/QTimer>
#include <QtCore/QUrl>
#include <QtCore/QBuffer>
#include <QtCore/QDir>
#include <QtCore/QFile>
#include <QtCore/QCryptographicHash>
#include <QtGui/QMessageBox>
#include <QtGui/QFileDialog>
#include <QtHelp/QHelpEngineCore>
#include <QtNetwork/QHttp>
QT_BEGIN_NAMESPACE
#ifndef QT_NO_HTTP
#define QCH_FILENAME 92943
#define QCH_NAMESPACE 92944
#define QCH_CHECKSUM 92945
InstallDialog::InstallDialog(QHelpEngineCore *helpEngine, QWidget *parent,
const QString &host, int port)
: QDialog(parent), m_helpEngine(helpEngine), m_host(host), m_port(port)
{
TRACE_OBJ
m_ui.setupUi(this);
m_ui.installButton->setEnabled(false);
m_ui.cancelButton->setEnabled(false);
m_ui.pathLineEdit->setText(QFileInfo(m_helpEngine->collectionFile()).absolutePath());
m_ui.progressBar->hide();
m_windowTitle = tr("Install Documentation");
m_http = new QHttp(this);
connect(m_http, SIGNAL(requestFinished(int,bool)),
this, SLOT(httpRequestFinished(int,bool)));
connect(m_http, SIGNAL(dataReadProgress(int,int)),
this, SLOT(updateDataReadProgress(int,int)));
connect(m_http, SIGNAL(responseHeaderReceived(QHttpResponseHeader)),
this, SLOT(readResponseHeader(QHttpResponseHeader)));
connect(m_ui.installButton, SIGNAL(clicked()), this, SLOT(install()));
connect(m_ui.cancelButton, SIGNAL(clicked()), this, SLOT(cancelDownload()));
connect(m_ui.browseButton, SIGNAL(clicked()), this, SLOT(browseDirectories()));
connect(m_ui.listWidget, SIGNAL(itemChanged(QListWidgetItem*)),
this, SLOT(updateInstallButton()));
QTimer::singleShot(0, this, SLOT(init()));
}
InstallDialog::~InstallDialog()
{
TRACE_OBJ
}
QStringList InstallDialog::installedDocumentations() const
{
TRACE_OBJ
return m_installedDocumentations;
}
void InstallDialog::init()
{
TRACE_OBJ
m_ui.statusLabel->setText(tr("Downloading documentation info..."));
m_ui.progressBar->show();
QUrl url(QLatin1String("http://qt.nokia.com/doc/assistantdocs/docs.txt"));
m_buffer = new QBuffer();
m_buffer->open(QBuffer::ReadWrite);
if (m_port > -1)
m_http->setProxy(m_host, m_port);
m_http->setHost(url.host());
m_httpAborted = false;
m_docInfoId = m_http->get(url.path(), m_buffer);
m_ui.cancelButton->setEnabled(true);
m_ui.closeButton->setEnabled(false);
}
void InstallDialog::updateInstallButton()
{
TRACE_OBJ
QListWidgetItem *item = 0;
for (int i=0; i<m_ui.listWidget->count(); ++i) {
item = m_ui.listWidget->item(i);
if (item->checkState() == Qt::Checked
&& item->flags() & Qt::ItemIsEnabled) {
m_ui.installButton->setEnabled(true);
return;
}
}
m_ui.installButton->setEnabled(false);
}
void InstallDialog::updateDocItemList()
{
TRACE_OBJ
QStringList registeredDocs = m_helpEngine->registeredDocumentations();
QListWidgetItem *item = 0;
for (int i=0; i<m_ui.listWidget->count(); ++i) {
item = m_ui.listWidget->item(i);
QString ns = item->data(QCH_NAMESPACE).toString();
if (!ns.isEmpty() && registeredDocs.contains(ns)) {
item->setFlags(Qt::ItemIsUserCheckable);
item->setCheckState(Qt::Checked);
}
item->setCheckState(Qt::Unchecked);
}
}
void InstallDialog::cancelDownload()
{
TRACE_OBJ
m_ui.statusLabel->setText(tr("Download canceled."));
m_httpAborted = true;
m_itemsToInstall.clear();
m_http->abort();
m_ui.cancelButton->setEnabled(false);
m_ui.closeButton->setEnabled(true);
updateInstallButton();
}
void InstallDialog::install()
{
TRACE_OBJ
QListWidgetItem *item = 0;
for (int i=0; i<m_ui.listWidget->count(); ++i) {
item = m_ui.listWidget->item(i);
if (item->checkState() == Qt::Checked)
m_itemsToInstall.append(item);
}
m_ui.installButton->setEnabled(false);
downloadNextFile();
}
void InstallDialog::downloadNextFile()
{
TRACE_OBJ
if (!m_itemsToInstall.count()) {
m_ui.cancelButton->setEnabled(false);
m_ui.closeButton->setEnabled(true);
m_ui.statusLabel->setText(tr("Done."));
m_ui.progressBar->hide();
updateDocItemList();
updateInstallButton();
return;
}
QListWidgetItem *item = m_itemsToInstall.dequeue();
m_currentCheckSum = item->data(QCH_CHECKSUM).toString();
QString fileName = item->data(QCH_FILENAME).toString();
QString saveFileName = m_ui.pathLineEdit->text() + QDir::separator()
+ fileName;
if (QFile::exists(saveFileName)
&& QMessageBox::information(this, m_windowTitle,
tr("The file %1 already exists. Do you want to overwrite it?")
.arg(saveFileName), QMessageBox::Yes | QMessageBox::No,
QMessageBox::Yes) == QMessageBox::No) {
installFile(saveFileName);
downloadNextFile();
return;
}
m_file = new QFile(saveFileName);
if (!m_file->open(QIODevice::WriteOnly|QIODevice::Truncate)) {
QMessageBox::information(this, m_windowTitle,
tr("Unable to save the file %1: %2.")
.arg(saveFileName).arg(m_file->errorString()));
delete m_file;
m_file = 0;
downloadNextFile();
return;
}
m_ui.statusLabel->setText(tr("Downloading %1...").arg(fileName));
m_ui.progressBar->show();
QLatin1String urlStr("http://qt.nokia.com/doc/assistantdocs/%1");
QUrl url(QString(urlStr).arg(fileName));
m_httpAborted = false;
m_docId = m_http->get(url.path(), m_file);
m_ui.cancelButton->setEnabled(true);
m_ui.closeButton->setEnabled(false);
}
void InstallDialog::httpRequestFinished(int requestId, bool error)
{
TRACE_OBJ
if (requestId == m_docInfoId && m_buffer) {
m_ui.progressBar->hide();
if (error) {
QMessageBox::information(this, m_windowTitle,
tr("Download failed: %1.")
.arg(m_http->errorString()));
} else if (!m_httpAborted) {
QStringList registeredDocs = m_helpEngine->registeredDocumentations();
m_buffer->seek(0);
while (m_buffer->canReadLine()) {
QByteArray ba = m_buffer->readLine();
QStringList lst = QString::fromAscii(ba.constData()).split(QLatin1Char('|'));
if (lst.count() != 4) {
QMessageBox::information(this, m_windowTitle,
tr("Documentation info file is corrupt!"));
} else {
QListWidgetItem *item = new QListWidgetItem(m_ui.listWidget);
item->setText(lst.at(2).trimmed());
item->setData(QCH_FILENAME, lst.first());
item->setData(QCH_NAMESPACE, lst.at(1));
item->setData(QCH_CHECKSUM, lst.last().trimmed());
}
}
updateDocItemList();
}
if (m_buffer)
m_buffer->close();
delete m_buffer;
m_buffer = 0;
m_ui.statusLabel->setText(tr("Done."));
m_ui.cancelButton->setEnabled(false);
m_ui.closeButton->setEnabled(true);
updateInstallButton();
} else if (requestId == m_docId) {
m_file->close();
if (!m_httpAborted) {
QString checkSum;
if (m_file->open(QIODevice::ReadOnly)) {
QByteArray digest = QCryptographicHash::hash(m_file->readAll(),
QCryptographicHash::Md5);
m_file->close();
checkSum = QString::fromLatin1(digest.toHex());
}
if (error) {
m_file->remove();
QMessageBox::warning(this, m_windowTitle,
tr("Download failed: %1.")
.arg(m_http->errorString()));
} else if (checkSum.isEmpty() || m_currentCheckSum != checkSum) {
m_file->remove();
QMessageBox::warning(this, m_windowTitle,
tr("Download failed: Downloaded file is corrupted."));
} else {
m_ui.statusLabel->setText(tr("Installing documentation %1...")
.arg(QFileInfo(m_file->fileName()).fileName()));
m_ui.progressBar->setMaximum(0);
m_ui.statusLabel->setText(tr("Done."));
installFile(m_file->fileName());
}
} else {
m_file->remove();
}
delete m_file;
m_file = 0;
downloadNextFile();
}
}
void InstallDialog::installFile(const QString &fileName)
{
TRACE_OBJ
if (m_helpEngine->registerDocumentation(fileName)) {
m_installedDocumentations
.append(QHelpEngineCore::namespaceName(fileName));
} else {
QMessageBox::information(this, m_windowTitle,
tr("Error while installing documentation:\n%1")
.arg(m_helpEngine->error()));
}
}
void InstallDialog::readResponseHeader(const QHttpResponseHeader &responseHeader)
{
TRACE_OBJ
if (responseHeader.statusCode() != 200) {
QMessageBox::information(this, m_windowTitle,
tr("Download failed: %1.")
.arg(responseHeader.reasonPhrase()));
m_httpAborted = true;
m_ui.progressBar->hide();
m_http->abort();
return;
}
}
void InstallDialog::updateDataReadProgress(int bytesRead, int totalBytes)
{
TRACE_OBJ
if (m_httpAborted)
return;
m_ui.progressBar->setMaximum(totalBytes);
m_ui.progressBar->setValue(bytesRead);
}
void InstallDialog::browseDirectories()
{
TRACE_OBJ
QString dir = QFileDialog::getExistingDirectory(this, m_windowTitle,
m_ui.pathLineEdit->text());
if (!dir.isEmpty())
m_ui.pathLineEdit->setText(dir);
}
#endif
QT_END_NAMESPACE