// Ryzom - MMORPG Framework
// Copyright (C) 2010 Winch Gate Property Limited
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as
// published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see .
#include "stdpch.h"
#include "operationdialog.h"
#include "downloader.h"
#include "wizarddialog.h"
#include "profilesdialog.h"
#include "configfile.h"
#include "config.h"
#include "profilesmodel.h"
#include "filescopier.h"
#include "filesextractor.h"
#include "filescleaner.h"
#include "seven_zip.h"
#if defined(Q_OS_WIN32) && defined(QT_WINEXTRAS_LIB)
#include
#include
#endif
#ifdef DEBUG_NEW
#define new DEBUG_NEW
#endif
COperationDialog::COperationDialog():QDialog(), m_aborting(false)
{
setupUi(this);
setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint);
#if defined(Q_OS_WIN32) && defined(QT_WINEXTRAS_LIB)
m_button = new QWinTaskbarButton(this);
#endif
// connect(resumeButton, SIGNAL(clicked()), SLOT(onResumeClicked()));
// connect(stopButton, SIGNAL(clicked()), SLOT(onStopClicked()));
// downloader
m_downloader = new CDownloader(this);
connect(m_downloader, SIGNAL(downloadPrepare()), SLOT(onProgressPrepare()));
connect(m_downloader, SIGNAL(downloadInit(qint64, qint64)), SLOT(onProgressInit(qint64, qint64)));
connect(m_downloader, SIGNAL(downloadStart()), SLOT(onProgressStart()));
connect(m_downloader, SIGNAL(downloadStop()), SLOT(onProgressStop()));
connect(m_downloader, SIGNAL(downloadProgress(qint64)), SLOT(onProgressProgress(qint64)));
connect(m_downloader, SIGNAL(downloadSuccess(qint64)), SLOT(onProgressSuccess(qint64)));
connect(m_downloader, SIGNAL(downloadFail(QString)), SLOT(onProgressFail(QString)));
connect(operationButtonBox, SIGNAL(clicked(QAbstractButton*)), SLOT(onAbortClicked()));
// operations
connect(this, SIGNAL(prepare()), SLOT(onProgressPrepare()));
connect(this, SIGNAL(init(qint64, qint64)), SLOT(onProgressInit(qint64, qint64)));
connect(this, SIGNAL(start()), SLOT(onProgressStart()));
connect(this, SIGNAL(stop()), SLOT(onProgressStop()));
connect(this, SIGNAL(progress(qint64, QString)), SLOT(onProgressProgress(qint64, QString)));
connect(this, SIGNAL(success(qint64)), SLOT(onProgressSuccess(qint64)));
connect(this, SIGNAL(fail(QString)), SLOT(onProgressFail(QString)));
connect(this, SIGNAL(done()), SLOT(onDone()));
setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
}
COperationDialog::~COperationDialog()
{
}
void COperationDialog::processNextStep()
{
CConfigFile *config = CConfigFile::getInstance();
// default server
const CServer &server = config->getServer();
// default profile
const CProfile &configuration = config->getProfile();
switch(config->getNextStep())
{
case CConfigFile::DisplayNoServerError:
break;
case CConfigFile::ShowWizard:
break;
case CConfigFile::DownloadData:
downloadData();
break;
case CConfigFile::ExtractDownloadedData:
// TODO
break;
case CConfigFile::DownloadClient:
downloadClient();
break;
case CConfigFile::ExtractDownloadedClient:
// TODO
break;
case CConfigFile::CopyServerFiles:
QtConcurrent::run(this, &COperationDialog::copyServerFiles);
break;
case CConfigFile::CopyProfileFiles:
QtConcurrent::run(this, &COperationDialog::copyProfileFiles);
break;
case CConfigFile::ExtractBnpClient:
QtConcurrent::run(this, &COperationDialog::extractBnpClient);
break;
case CConfigFile::CleanFiles:
QtConcurrent::run(this, &COperationDialog::cleanFiles);
break;
case CConfigFile::CreateProfile:
createDefaultProfile();
break;
case CConfigFile::CreateShortcuts:
createDefaultShortcuts();
break;
default:
// cases already managed in main.cpp
break;
}
m_downloader->getHtmlPageContent(config->expandVariables(server.displayUrl));
}
void COperationDialog::showEvent(QShowEvent *e)
{
#if defined(Q_OS_WIN32) && defined(QT_WINEXTRAS_LIB)
m_button->setWindow(windowHandle());
#endif
e->accept();
processNextStep();
}
void COperationDialog::closeEvent(QCloseEvent *e)
{
if (e->spontaneous())
{
e->ignore();
onAbortClicked();
}
}
void COperationDialog::onAbortClicked()
{
if (m_downloader->isDownloading())
{
if (!m_downloader->supportsResume())
{
QMessageBox::StandardButton res = QMessageBox::question(this, tr("Confirmation"), tr("Warning, this server doesn't support resume! If you stop download now, you won't be able to resume it later.\nAre you sure to abort download?"));
if (res != QMessageBox::Yes) return;
}
}
QMutexLocker locker(&m_abortingMutex);
m_aborting = true;
}
void COperationDialog::onProgressPrepare()
{
operationProgressBar->setFormat(tr("%p% (%v/%m KiB)"));
operationProgressBar->setMinimum(0);
operationProgressBar->setMaximum(0);
operationProgressBar->setValue(0);
operationLabel->setText(m_currentOperation);
}
void COperationDialog::onProgressInit(qint64 current, qint64 total)
{
operationProgressBar->setMinimum(0);
operationProgressBar->setMaximum(total / 1024);
operationProgressBar->setValue(current / 1024);
#if defined(Q_OS_WIN32) && defined(QT_WINEXTRAS_LIB)
m_button->progress()->setMinimum(0);
m_button->progress()->setMaximum(total / 1024);
m_button->progress()->setValue(current / 1024);
#endif
}
void COperationDialog::onProgressStart()
{
#if defined(Q_OS_WIN32) && defined(QT_WINEXTRAS_LIB)
m_button->progress()->show();
#endif
}
void COperationDialog::onProgressStop()
{
#if defined(Q_OS_WIN32) && defined(QT_WINEXTRAS_LIB)
m_button->progress()->hide();
#endif
close();
}
void COperationDialog::onProgressProgress(qint64 current, const QString &filename)
{
operationProgressLabel->setText(m_currentOperationProgressFormat.arg(filename));
operationProgressBar->setValue(current / 1024);
#if defined(Q_OS_WIN32) && defined(QT_WINEXTRAS_LIB)
m_button->progress()->setValue(current / 1024);
#endif
}
void COperationDialog::onProgressSuccess(qint64 total)
{
operationProgressBar->setValue(total / 1024);
#if defined(Q_OS_WIN32) && defined(QT_WINEXTRAS_LIB)
m_button->progress()->hide();
#endif
}
void COperationDialog::onProgressFail(const QString &error)
{
QMessageBox::critical(this, tr("Error"), error);
}
void COperationDialog::onDone()
{
if (!operationShouldStop()) processNextStep();
}
void COperationDialog::downloadData()
{
CConfigFile *config = CConfigFile::getInstance();
// default server
const CServer &server = config->getServer();
m_currentOperation = QApplication::tr("Download data required for server %1").arg(server.name);
m_currentOperationProgressFormat = QApplication::tr("Downloading %1...");
m_downloader->prepareFile(config->expandVariables(server.dataDownloadUrl), config->getInstallationDirectory() + "/" + config->expandVariables(server.dataDownloadFilename) + ".part");
}
void COperationDialog::downloadClient()
{
CConfigFile *config = CConfigFile::getInstance();
// default server
const CServer &server = config->getServer();
m_currentOperation = QApplication::tr("Download client required for server %1").arg(server.name);
m_currentOperationProgressFormat = QApplication::tr("Downloading %1...");
m_downloader->prepareFile(config->expandVariables(server.clientDownloadUrl), config->getInstallationDirectory() + "/" + config->expandVariables(server.clientDownloadFilename) + ".part");
}
void COperationDialog::copyServerFiles()
{
CConfigFile *config = CConfigFile::getInstance();
// default server
const CServer &server = config->getServer();
m_currentOperation = QApplication::tr("Copy client files needed for server %1").arg(server.name);
m_currentOperationProgressFormat = QApplication::tr("Copying %1...");
QStringList serverFiles;
serverFiles << "cfg";
serverFiles << "data";
serverFiles << "examples";
serverFiles << "patch";
serverFiles << "unpack";
serverFiles << "client_default.cfg";
CFilesCopier copier(this);
copier.setSourceDirectory(config->getSrcServerDirectory());
copier.setDesinationDirectory(config->getInstallationDirectory() + "/" + server.id);
copier.setIncludeFilter(serverFiles);
if (copier.exec())
{
}
else
{
}
emit done();
}
void COperationDialog::copyProfileFiles()
{
CConfigFile *config = CConfigFile::getInstance();
// default server
const CServer &server = config->getServer();
// default profile
const CProfile &profile = config->getProfile();
m_currentOperation = QApplication::tr("Copy old profile to new location");
m_currentOperationProgressFormat = QApplication::tr("Copying %1...");
QStringList profileFiles;
profileFiles << "cache";
profileFiles << "save";
profileFiles << "user";
profileFiles << "screenshots";
profileFiles << "client.cfg";
profileFiles << "*.log";
CFilesCopier copier(this);
copier.setSourceDirectory(config->getSrcProfileDirectory());
copier.setDesinationDirectory(config->getProfileDirectory() + "/" + profile.id);
copier.setIncludeFilter(profileFiles);
if (copier.exec())
{
}
else
{
}
emit done();
}
void COperationDialog::extractBnpClient()
{
CConfigFile *config = CConfigFile::getInstance();
// default server
const CServer &server = config->getServer();
m_currentOperation = QApplication::tr("Extract client to new location");
m_currentOperationProgressFormat = QApplication::tr("Extracting %1...");
QString destinationDirectory = config->getInstallationDirectory() + "/" + server.id;
CFilesExtractor extractor(this);
extractor.setSourceFile(config->getSrcServerClientBNPFullPath());
extractor.setDesinationDirectory(destinationDirectory);
extractor.exec();
QString upgradeScript = destinationDirectory + "/upgd_nl.";
#ifdef Q_OS_WIN
upgradeScript += "bat";
#else
upgradeScript += "sh";
#endif
if (QFile::exists(upgradeScript))
{
QProcess process;
QProcessEnvironment env = QProcessEnvironment::systemEnvironment();
env.insert("RYZOM_CLIENT", QDir::toNativeSeparators(destinationDirectory + "/ryzom_client_r.exe"));
env.insert("UNPACKPATH", QDir::toNativeSeparators(destinationDirectory + "/unpack"));
env.insert("ROOTPATH", QDir::toNativeSeparators(destinationDirectory));
env.insert("STARTUPPATH", "");
process.setProcessEnvironment(env);
process.start(upgradeScript);
while (process.waitForFinished())
{
qDebug() << "waiting";
}
}
emit done();
}
void COperationDialog::cleanFiles()
{
CConfigFile *config = CConfigFile::getInstance();
// default server
const CServer &server = config->getServer();
m_currentOperation = QApplication::tr("Clean obsolete files");
m_currentOperationProgressFormat = QApplication::tr("Deleting %1...");
CFilesCleaner cleaner(this);
cleaner.setDirectory(config->getInstallationDirectory() + "/" + server.id);
cleaner.exec();
emit done();
}
bool COperationDialog::createDefaultProfile()
{
CConfigFile *config = CConfigFile::getInstance();
CServer server = config->getServer(config->getDefaultServerIndex());
m_currentOperation = QApplication::tr("Create default profile");
m_currentOperationProgressFormat = QApplication::tr("Deleting %1...");
CProfile profile;
profile.id = "0";
profile.executable = config->getClientFullPath();
profile.name = QString("Ryzom (%1)").arg(server.name);
profile.server = server.id;
profile.comments = "Default profile created by Ryzom Installer";
#ifdef Q_OS_WIN32
// C:\Users\Public\Desktop
profile.desktopShortcut = QFile::exists(QStandardPaths::writableLocation(QStandardPaths::DesktopLocation) + "/Ryzom.lnk");
#endif
// TODO
// profile.menuShortcut
config->addProfile(profile);
config->save();
emit done();
return true;
}
bool COperationDialog::createDefaultShortcuts()
{
emit done();
return true;
}
void COperationDialog::operationPrepare()
{
emit prepare();
}
void COperationDialog::operationInit(qint64 current, qint64 total)
{
emit init(current, total);
}
void COperationDialog::operationStart()
{
emit start();
}
void COperationDialog::operationStop()
{
emit stop();
}
void COperationDialog::operationProgress(qint64 current, const QString &filename)
{
emit progress(current, filename);
}
void COperationDialog::operationSuccess(qint64 total)
{
emit success(total);
}
void COperationDialog::operationFail(const QString &error)
{
emit fail(error);
}
bool COperationDialog::operationShouldStop()
{
QMutexLocker locker(&m_abortingMutex);
return m_aborting;
}