diff --git a/code/ryzom/tools/client/ryzom_installer/src/archive.h b/code/ryzom/tools/client/ryzom_installer/src/archive.h deleted file mode 100644 index a442056e1..000000000 --- a/code/ryzom/tools/client/ryzom_installer/src/archive.h +++ /dev/null @@ -1,100 +0,0 @@ -// 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 . - -#ifndef ARCHIVE_H -#define ARCHIVE_H - -/** - * Files copy, decompression, extraction - * - * \author Cedric 'Kervala' OCHS - * \date 2016 - */ -class CArchive : public QObject -{ - Q_OBJECT - -public: - CArchive(QObject *parent = NULL); - virtual ~CArchive(); - - bool extract(const QString &filename, const QString &dest); - bool copyServerFiles(const QString &src, const QString &dst); - bool copyProfileFiles(const QString &src, const QString &dst); - bool cleanServerFiles(const QString &directory); - - void stop(); - bool mustStop(); - -signals: - // emitted when requesting real URL - void extractPrepare(); - - // emitted when we got the initial (local) and total (remote) size of file - void extractInit(qint64 current, qint64 total); - - // emitted when we begin to download - void extractStart(); - - // emitted when the download stopped - void extractStop(); - - // emitted when extracting - void extractProgress(qint64 current, const QString &filename); - - // emitted when the whole file is downloaded - void extractSuccess(qint64 total); - - // emitted when an error occurs - void extractFail(const QString &error); - - // emitted when done and should process next step - void done(); - -protected: - - struct FileToCopy - { - QString filename; - QString src; - QString dst; - qint64 size; - QDateTime date; - }; - - typedef QList FilesToCopy; - - bool extract7z(); - bool extractZip(); - bool extractBnp(); - - bool progress(const std::string &filename, uint32 currentFile, uint32 totalFiles); - - bool copyServerFiles(); - bool copyProfileFiles(); - bool copyFiles(const FilesToCopy &files); - - static void getFilesList(const QString &srcDir, const QString &dstDir, const QStringList &filter, FilesToCopy &files); - - QString m_filename; - QString m_dest; - - QMutex m_mutex; - - bool m_mustStop; -}; - -#endif diff --git a/code/ryzom/tools/client/ryzom_installer/src/configfile.cpp b/code/ryzom/tools/client/ryzom_installer/src/configfile.cpp index d62a58372..29c7ba6e4 100644 --- a/code/ryzom/tools/client/ryzom_installer/src/configfile.cpp +++ b/code/ryzom/tools/client/ryzom_installer/src/configfile.cpp @@ -29,7 +29,7 @@ const CProfile NoProfile; CConfigFile *CConfigFile::s_instance = NULL; -CConfigFile::CConfigFile(QObject *parent):QObject(parent), m_defaultServer(0), m_defaultProfile(0), m_use64BitsClient(false) +CConfigFile::CConfigFile(QObject *parent):QObject(parent), m_defaultServerIndex(0), m_defaultProfileIndex(0), m_use64BitsClient(false) { s_instance = this; @@ -60,7 +60,7 @@ bool CConfigFile::load(const QString &filename) settings.beginGroup("servers"); int serversCount = settings.value("size").toInt(); - m_defaultServer = settings.value("default").toInt(); + m_defaultServerIndex = settings.value("default").toInt(); settings.endGroup(); m_servers.resize(serversCount); @@ -94,7 +94,7 @@ bool CConfigFile::load(const QString &filename) settings.beginGroup("profiles"); int profilesCounts = settings.value("size").toInt(); - m_defaultProfile = settings.value("default").toInt(); + m_defaultProfileIndex = settings.value("default").toInt(); settings.endGroup(); m_profiles.resize(profilesCounts); @@ -134,7 +134,7 @@ bool CConfigFile::save() const settings.beginGroup("servers"); settings.setValue("size", m_servers.size()); - settings.setValue("default", m_defaultServer); + settings.setValue("default", m_defaultServerIndex); settings.endGroup(); for(int i = 0; i < m_servers.size(); ++i) @@ -166,7 +166,7 @@ bool CConfigFile::save() const settings.beginGroup("profiles"); settings.setValue("size", m_profiles.size()); - settings.setValue("default", m_defaultProfile); + settings.setValue("default", m_defaultProfileIndex); settings.endGroup(); for(int i = 0; i < m_profiles.size(); ++i) @@ -203,7 +203,7 @@ int CConfigFile::getServersCount() const const CServer& CConfigFile::getServer(int i) const { - if (i < 0) i = m_defaultServer; + if (i < 0) i = m_defaultServerIndex; if (i >= m_servers.size()) return NoServer; @@ -228,7 +228,7 @@ int CConfigFile::getProfilesCount() const CProfile CConfigFile::getProfile(int i) const { - if (i < 0) i = m_defaultProfile; + if (i < 0) i = m_defaultProfileIndex; if (i >= m_profiles.size()) return NoProfile; @@ -259,14 +259,24 @@ bool CConfigFile::has64bitsOS() return QSysInfo::currentCpuArchitecture() == "x86_64"; } -int CConfigFile::getDefaultProfile() const +int CConfigFile::getDefaultServerIndex() const { - return m_defaultProfile; + return m_defaultServerIndex; } -int CConfigFile::getDefaultServer() const +void CConfigFile::setDefaultServerIndex(int index) { - return m_defaultServer; + m_defaultServerIndex = index; +} + +int CConfigFile::getDefaultProfileIndex() const +{ + return m_defaultProfileIndex; +} + +void CConfigFile::setDefaultProfileIndex(int index) +{ + m_defaultProfileIndex = index; } bool CConfigFile::isRyzomInstallerConfigured() const @@ -601,33 +611,3 @@ CConfigFile::InstallationStep CConfigFile::getNextStep() const return Done; } - -bool CConfigFile::createDefaultProfile() -{ - CServer server = getServer(getDefaultServer()); - - CProfile profile; - - profile.id = 0; - profile.executable = 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 - profile.desktopShortcut = QFile::exists(QStandardPaths::writableLocation(QStandardPaths::DesktopLocation) + "/Ryzom.lnk"); -#endif - - // TODO - // profile.menuShortcut - - addProfile(profile); - save(); - - return true; -} - -bool CConfigFile::createDefaultShortcuts() -{ - return true; -} diff --git a/code/ryzom/tools/client/ryzom_installer/src/configfile.h b/code/ryzom/tools/client/ryzom_installer/src/configfile.h index 3426681bc..e225fcc59 100644 --- a/code/ryzom/tools/client/ryzom_installer/src/configfile.h +++ b/code/ryzom/tools/client/ryzom_installer/src/configfile.h @@ -119,8 +119,11 @@ public: int addProfile(const CProfile &profile); void removeProfile(int i); - int getDefaultServer() const; - int getDefaultProfile() const; + int getDefaultServerIndex() const; + void setDefaultServerIndex(int index); + + int getDefaultProfileIndex() const; + void setDefaultProfileIndex(int index); bool isRyzomInstallerConfigured() const; @@ -162,12 +165,9 @@ public: InstallationStep getNextStep() const; - bool createDefaultProfile(); - bool createDefaultShortcuts(); - private: - int m_defaultServer; - int m_defaultProfile; + int m_defaultServerIndex; + int m_defaultProfileIndex; CServers m_servers; CProfiles m_profiles; diff --git a/code/ryzom/tools/client/ryzom_installer/src/filescleaner.cpp b/code/ryzom/tools/client/ryzom_installer/src/filescleaner.cpp new file mode 100644 index 000000000..4b66b437b --- /dev/null +++ b/code/ryzom/tools/client/ryzom_installer/src/filescleaner.cpp @@ -0,0 +1,79 @@ +// 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 "filescleaner.h" +#include "operation.h" +#include "utils.h" + +#include "nel/misc/big_file.h" +#include "nel/misc/callback.h" +#include "nel/misc/file.h" +#include "nel/misc/path.h" + +#include "7z.h" +#include "7zAlloc.h" +#include "7zBuf.h" +#include "7zCrc.h" + +#include "qzipreader.h" + +#include + +#ifdef DEBUG_NEW + #define new DEBUG_NEW +#endif + +CFilesCleaner::CFilesCleaner(IOperationProgressListener *listener):m_listener(listener) +{ +} + +CFilesCleaner::~CFilesCleaner() +{ +} + +void CFilesCleaner::setDirectory(const QString &src) +{ + m_directory = src; +} + +bool CFilesCleaner::exec() +{ + QDir dir(m_directory); + + // directory doesn't exist + if (!dir.exists()) return false; + + if (!dir.cd("data") && dir.exists()) return false; + + // temporary files + QStringList files = dir.entryList(QStringList() << "*.string_cache" << "*.packed_sheets" << "*.packed" << "*.pem", QDir::Files); + + foreach(const QString &file, files) + { + dir.remove(file); + } + + // fonts directory is not needed anymore + if (dir.cd("fonts") && dir.exists()) + { + dir.removeRecursively(); + } + + if (m_listener) m_listener->operationFinish(); + + return true; +} diff --git a/code/ryzom/tools/client/ryzom_installer/src/filescleaner.h b/code/ryzom/tools/client/ryzom_installer/src/filescleaner.h new file mode 100644 index 000000000..6458b5742 --- /dev/null +++ b/code/ryzom/tools/client/ryzom_installer/src/filescleaner.h @@ -0,0 +1,45 @@ +// 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 . + +#ifndef FILESCLEANER_H +#define FILESCLEANER_H + +class IOperationProgressListener; + +/** + * Files cleaner + * + * \author Cedric 'Kervala' OCHS + * \date 2016 + */ +class CFilesCleaner +{ +public: + CFilesCleaner(IOperationProgressListener *listener); + virtual ~CFilesCleaner(); + + void setDirectory(const QString &src); + + bool exec(); + +protected: + + IOperationProgressListener *m_listener; + + QString m_directory; +}; + +#endif diff --git a/code/ryzom/tools/client/ryzom_installer/src/filescopier.cpp b/code/ryzom/tools/client/ryzom_installer/src/filescopier.cpp new file mode 100644 index 000000000..8c8cfabb4 --- /dev/null +++ b/code/ryzom/tools/client/ryzom_installer/src/filescopier.cpp @@ -0,0 +1,188 @@ +// 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 "filescopier.h" +#include "utils.h" +#include "operation.h" + +#include "nel/misc/path.h" + +#ifdef DEBUG_NEW + #define new DEBUG_NEW +#endif + +CFilesCopier::CFilesCopier(IOperationProgressListener *listener):m_listener(listener) +{ +} + +CFilesCopier::~CFilesCopier() +{ +} + +void CFilesCopier::setSourceDirectory(const QString &src) +{ + m_sourceDirectory = src; +} + +void CFilesCopier::setDesinationDirectory(const QString &dst) +{ + m_destinationDirectory = dst; +} + +void CFilesCopier::setIncludeFilter(const QStringList &filter) +{ + m_includeFilter = filter; +} + +void CFilesCopier::setExcludeFilter(const QStringList &filter) +{ + m_excludeFilter = filter; +} + +bool CFilesCopier::exec() +{ + if (m_sourceDirectory.isEmpty() || m_destinationDirectory.isEmpty()) return false; + + if (m_listener) m_listener->operationPrepare(); + + QDir().mkpath(m_destinationDirectory); + + FilesToCopy files; + + CFilesCopier::getFilesList(files); + + return copyFiles(files); +} + +void CFilesCopier::getFilesList(FilesToCopy &files) +{ + QDir dir(m_sourceDirectory); + + QFileInfoList entries = dir.entryInfoList(m_includeFilter); + + foreach(const QFileInfo &entry, entries) + { + QString fullPath = entry.absoluteFilePath(); + + QString dstPath = m_destinationDirectory + "/" + dir.relativeFilePath(fullPath); + + if (entry.isDir()) + { + QDir().mkpath(dstPath); + + QDir subDir(fullPath); + + QDirIterator it(subDir, QDirIterator::Subdirectories); + + while (it.hasNext()) + { + fullPath = it.next(); + + if (it.fileName().startsWith('.')) continue; + + QFileInfo fileInfo = it.fileInfo(); + + dstPath = m_destinationDirectory + "/" + dir.relativeFilePath(fullPath); + + if (fileInfo.isDir()) + { + QDir().mkpath(dstPath); + } + else + { + FileToCopy file; + file.filename = it.fileName(); + file.src = it.filePath(); + file.dst = dstPath; + file.size = it.fileInfo().size(); + file.date = it.fileInfo().lastModified().toTime_t(); + + files << file; + } + } + } + else + { + FileToCopy file; + file.filename = entry.fileName(); + file.src = entry.filePath(); + file.dst = dstPath; + file.size = entry.size(); + file.date = entry.lastModified().toTime_t(); + + files << file; + } + } +} + +bool CFilesCopier::copyFiles(const FilesToCopy &files) +{ + qint64 totalSize = 0; + + foreach(const FileToCopy &file, files) + { + totalSize += file.size; + } + + if (m_listener) + { + m_listener->operationInit(0, totalSize); + m_listener->operationStart(); + } + + qint64 processedSize = 0; + + foreach(const FileToCopy &file, files) + { + if (m_listener && m_listener->operationShouldStop()) + { + m_listener->operationStop(); + return true; + } + + if (m_listener) m_listener->operationProgress(processedSize, file.filename); + + QFileInfo dstFileInfo(file.dst); + + if (dstFileInfo.size() != file.size || dstFileInfo.lastModified().toTime_t() != file.date) + { + // force deleting previous file since it was incomplete + QFile::remove(file.dst); + + if (!QFile::copy(file.src, file.dst)) + { + if (m_listener) m_listener->operationFail(QApplication::tr("Unable to copy file %1").arg(file.src)); + return false; + } + + if (!NLMISC::CFile::setFileModificationDate(qToUtf8(file.dst), file.date)) + { + qDebug() << "Unable to change date of " << file.dst; + } + } + + processedSize += file.size; + } + + if (m_listener) + { + m_listener->operationSuccess(totalSize); + m_listener->operationFinish(); + } + + return true; +} diff --git a/code/ryzom/tools/client/ryzom_installer/src/filescopier.h b/code/ryzom/tools/client/ryzom_installer/src/filescopier.h new file mode 100644 index 000000000..0148bfdaf --- /dev/null +++ b/code/ryzom/tools/client/ryzom_installer/src/filescopier.h @@ -0,0 +1,67 @@ +// 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 . + +#ifndef FILESCOPIER_H +#define FILESCOPIER_H + +class IOperationProgressListener; + +/** + * Files copier + * + * \author Cedric 'Kervala' OCHS + * \date 2016 + */ +class CFilesCopier +{ +public: + CFilesCopier(IOperationProgressListener *listener); + virtual ~CFilesCopier(); + + void setSourceDirectory(const QString &src); + void setDesinationDirectory(const QString &src); + + void setIncludeFilter(const QStringList &filter); + void setExcludeFilter(const QStringList &filter); + + bool exec(); + +protected: + + struct FileToCopy + { + QString filename; + QString src; + QString dst; + qint64 size; + uint date; + }; + + typedef QList FilesToCopy; + + void getFilesList(FilesToCopy &files); + bool copyFiles(const FilesToCopy &files); + + IOperationProgressListener *m_listener; + + QString m_sourceDirectory; + QString m_destinationDirectory; + + QStringList m_includeFilter; + QStringList m_excludeFilter; +}; + +#endif diff --git a/code/ryzom/tools/client/ryzom_installer/src/archive.cpp b/code/ryzom/tools/client/ryzom_installer/src/filesextractor.cpp similarity index 60% rename from code/ryzom/tools/client/ryzom_installer/src/archive.cpp rename to code/ryzom/tools/client/ryzom_installer/src/filesextractor.cpp index 425e4f379..222add173 100644 --- a/code/ryzom/tools/client/ryzom_installer/src/archive.cpp +++ b/code/ryzom/tools/client/ryzom_installer/src/filesextractor.cpp @@ -15,7 +15,8 @@ // along with this program. If not, see . #include "stdpch.h" -#include "archive.h" +#include "filesextractor.h" +#include "operation.h" #include "utils.h" #include "nel/misc/big_file.h" @@ -32,10 +33,6 @@ #include -#ifdef Q_OS_WIN -#include -#endif - #ifndef FILE_ATTRIBUTE_READONLY #define FILE_ATTRIBUTE_READONLY 0x1 #endif @@ -244,20 +241,31 @@ public: } }; -CArchive::CArchive(QObject *parent):QObject(parent), m_mustStop(false) +CFilesExtractor::CFilesExtractor(IOperationProgressListener *listener):m_listener(listener) +{ +} + +CFilesExtractor::~CFilesExtractor() +{ +} + +void CFilesExtractor::setSourceFile(const QString &src) { + m_sourceFile = src; } -CArchive::~CArchive() +void CFilesExtractor::setDesinationDirectory(const QString &dst) { + m_destinationDirectory = dst; } -bool CArchive::extract(const QString &filename, const QString &dest) +bool CFilesExtractor::exec() { - m_filename = filename; - m_dest = dest; + if (m_sourceFile.isEmpty() || m_destinationDirectory.isEmpty()) return false; - QFile file(m_filename); + if (m_listener) m_listener->operationPrepare(); + + QFile file(m_sourceFile); // open archive file to check format if (!file.open(QFile::ReadOnly)) return false; @@ -270,253 +278,38 @@ bool CArchive::extract(const QString &filename, const QString &dest) // create destination directory QDir dir; - dir.mkpath(dest); - - QFuture future; + dir.mkpath(m_destinationDirectory); // compare to supported formats and call the appropriate decompressor if (header == "7z") { - future = QtConcurrent::run(this, &CArchive::extract7z); - } - else if (header == "PK") - { - future = QtConcurrent::run(this, &CArchive::extractZip); - } - else if (QFileInfo(filename).suffix().toLower() == "bnp") - { - future = QtConcurrent::run(this, &CArchive::extractBnp); - } - else - { - qDebug() << "Unsupported format"; - return false; - } - - return true; -} - -void CArchive::getFilesList(const QString &srcDir, const QString &dstDir, const QStringList &filter, FilesToCopy &files) -{ - QDir dir(srcDir); - - QFileInfoList entries = dir.entryInfoList(filter); - - foreach(const QFileInfo &entry, entries) - { - QString fullPath = entry.absoluteFilePath(); - - QString dstPath = dstDir + "/" + dir.relativeFilePath(fullPath); - - if (entry.isDir()) - { - QDir().mkpath(dstPath); - - QDir subDir(fullPath); - - QDirIterator it(subDir, QDirIterator::Subdirectories); - - while (it.hasNext()) - { - fullPath = it.next(); - - if (it.fileName().startsWith('.')) continue; - - QFileInfo fileInfo = it.fileInfo(); - - dstPath = dstDir + "/" + dir.relativeFilePath(fullPath); - - if (fileInfo.isDir()) - { - QDir().mkpath(dstPath); - } - else - { - FileToCopy file; - file.filename = it.fileName(); - file.src = it.filePath(); - file.dst = dstPath; - file.size = it.fileInfo().size(); - file.date = it.fileInfo().lastModified(); - - files << file; - } - } - } - else - { - FileToCopy file; - file.filename = entry.fileName(); - file.src = entry.filePath(); - file.dst = dstPath; - file.size = entry.size(); - file.date = entry.lastModified(); - - files << file; - } - } -} - -bool CArchive::copyServerFiles() -{ - emit extractPrepare(); - - FilesToCopy files; - - QStringList serverFiles; - serverFiles << "cfg"; - serverFiles << "data"; - serverFiles << "examples"; - serverFiles << "patch"; - serverFiles << "unpack"; - serverFiles << "client_default.cfg"; - - CArchive::getFilesList(m_filename, m_dest, serverFiles, files); - - return copyFiles(files); -} - -bool CArchive::copyProfileFiles() -{ - emit extractPrepare(); - - FilesToCopy files; - - QStringList configFiles; - configFiles << "cache"; - configFiles << "save"; - configFiles << "user"; - configFiles << "screenshots"; - configFiles << "client.cfg"; - configFiles << "*.log"; - - CArchive::getFilesList(m_filename, m_dest, configFiles, files); - - return copyFiles(files); -} - -bool CArchive::cleanServerFiles(const QString &directory) -{ - QDir dir(directory); - - // directory doesn't exist - if (!dir.exists()) return false; - - if (!dir.cd("data") && dir.exists()) return false; - - // temporary files - QStringList files = dir.entryList(QStringList() << "*.string_cache" << "*.packed_sheets" << "*.packed" << "*.pem", QDir::Files); - - foreach(const QString &file, files) - { - dir.remove(file); - } - - // fonts directory is not needed anymore - if (dir.cd("fonts") && dir.exists()) - { - dir.removeRecursively(); + return extract7z(); } - emit done(); - - return true; -} - -bool CArchive::copyServerFiles(const QString &src, const QString &dst) -{ - if (src.isEmpty() || dst.isEmpty()) return false; - - m_filename = src; - m_dest = dst; - - // create destination directory - QDir().mkpath(dst); - - QFuture future = QtConcurrent::run(this, &CArchive::copyServerFiles); - - return true; -} - -bool CArchive::copyProfileFiles(const QString &src, const QString &dst) -{ - if (src.isEmpty() || dst.isEmpty()) return false; - - m_filename = src; - m_dest = dst; - - // create destination directory - QDir().mkpath(dst); - - QFuture future = QtConcurrent::run(this, &CArchive::copyProfileFiles); - - return true; -} - -bool CArchive::copyFiles(const FilesToCopy &files) -{ - qint64 totalSize = 0; - - foreach(const FileToCopy &file, files) + if (header == "PK") { - totalSize += file.size; - - qDebug() << file.filename; + return extractZip(); } - emit extractInit(0, totalSize); - - emit extractStart(); - - qint64 processedSize = 0; - - foreach(const FileToCopy &file, files) + if (QFileInfo(m_sourceFile).suffix().toLower() == "bnp") { - if (mustStop()) - { - emit extractStop(); - return true; - } - - emit extractProgress(processedSize, file.filename); - - QFileInfo dstFileInfo(file.dst); - - if (dstFileInfo.size() != file.size || dstFileInfo.lastModified() != file.date) - { - if (!QFile::copy(file.src, file.dst)) - { - emit extractFail(tr("Unable to copy file %1").arg(file.src)); - return false; - } - - if (!NLMISC::CFile::setFileModificationDate(qToUtf8(file.dst), file.date.toTime_t())) - { - qDebug() << "Unable to change date"; - } - } - - processedSize += file.size; + return extractBnp(); } - emit extractSuccess(totalSize); - emit done(); - - return true; + qDebug() << "Unsupported format"; + return false; } -bool CArchive::extract7z() +bool CFilesExtractor::extract7z() { - Q7zFile inFile(m_filename); + Q7zFile inFile(m_sourceFile); if (!inFile.open()) { - emit extractFail(tr("Unable to open %1").arg(m_filename)); + if (m_listener) m_listener->operationFail(QApplication::tr("Unable to open %1").arg(m_sourceFile)); return false; } - emit extractPrepare(); - UInt16 *temp = NULL; size_t tempSize = 0; @@ -558,9 +351,11 @@ bool CArchive::extract7z() if (!isDir) total += SzArEx_GetFileSize(&db, i); } - emit extractInit(0, total); - - emit extractStart(); + if (m_listener) + { + m_listener->operationInit(0, total); + m_listener->operationStart(); + } // variables used for decompression UInt32 blockIndex = 0xFFFFFFFF; @@ -570,7 +365,7 @@ bool CArchive::extract7z() // process each file in archive for (UInt32 i = 0; i < db.NumFiles; ++i) { - if (mustStop()) + if (m_listener && m_listener->operationShouldStop()) { res = SZ_ERROR_INTERRUPTED; break; @@ -602,7 +397,7 @@ bool CArchive::extract7z() if (!isDir) { - emit extractProgress(totalUncompressed, filename); + if (m_listener) m_listener->operationProgress(totalUncompressed, filename); res = SzArEx_Extract(&db, &lookStream.s, i, &blockIndex, &outBuffer, &outBufferSize, &offset, &outSizeProcessed, &allocImp, &allocTempImp); @@ -610,7 +405,7 @@ bool CArchive::extract7z() if (res != SZ_OK) break; } - QString destPath = m_dest + '/' + path; + QString destPath = m_destinationDirectory + '/' + path; QDir dir; @@ -626,7 +421,7 @@ bool CArchive::extract7z() if (!outFile.open(QFile::WriteOnly)) { - error = tr("Unable to open output file"); + error = QApplication::tr("Unable to open output file"); res = SZ_ERROR_FAIL; break; } @@ -635,7 +430,7 @@ bool CArchive::extract7z() if (processedSize != outSizeProcessed) { - error = tr("Unable to write output file"); + error = QApplication::tr("Unable to write output file"); res = SZ_ERROR_FAIL; break; } @@ -644,7 +439,7 @@ bool CArchive::extract7z() totalUncompressed += SzArEx_GetFileSize(&db, i); - emit extractProgress(totalUncompressed, filename); + if (m_listener) m_listener->operationProgress(totalUncompressed, filename); if (SzBitWithVals_Check(&db.Attribs, i)) Set7zFileAttrib(destPath, db.Attribs.Vals[i]); @@ -659,24 +454,27 @@ bool CArchive::extract7z() switch(res) { case SZ_OK: - emit extractSuccess(totalUncompressed); - emit done(); + if (m_listener) + { + m_listener->operationSuccess(totalUncompressed); + m_listener->operationFinish(); + } return true; case SZ_ERROR_INTERRUPTED: - emit extractStop(); + if (m_listener) m_listener->operationStop(); return true; case SZ_ERROR_UNSUPPORTED: - error = tr("7zip decoder doesn't support this archive"); + error = QApplication::tr("7zip decoder doesn't support this archive"); break; case SZ_ERROR_MEM: - error = tr("Unable to allocate memory"); + error = QApplication::tr("Unable to allocate memory"); break; case SZ_ERROR_CRC: - error = tr("7zip decoder doesn't support this archive"); + error = QApplication::tr("7zip decoder doesn't support this archive"); break; case SZ_ERROR_FAIL: @@ -684,21 +482,19 @@ bool CArchive::extract7z() break; default: - error = tr("Error %1").arg(res); + error = QApplication::tr("Error %1").arg(res); } - emit extractFail(error); + if (m_listener) m_listener->operationFail(error); return false; } -bool CArchive::extractZip() +bool CFilesExtractor::extractZip() { - emit extractPrepare(); - - QZipReader reader(m_filename); + QZipReader reader(m_sourceFile); - QDir baseDir(m_dest); + QDir baseDir(m_destinationDirectory); // create directories first QList allFiles = reader.fileInfoList(); @@ -709,17 +505,17 @@ bool CArchive::extractZip() { if (fi.isDir) { - const QString absPath = m_dest + QDir::separator() + fi.filePath; + const QString absPath = m_destinationDirectory + QDir::separator() + fi.filePath; if (!baseDir.mkpath(fi.filePath)) { - emit extractFail(tr("Unable to create directory %1").arg(absPath)); + if (m_listener) m_listener->operationFail(QApplication::tr("Unable to create directory %1").arg(absPath)); return false; } if (!QFile::setPermissions(absPath, fi.permissions)) { - emit extractFail(tr("Unable to set permissions of %1").arg(absPath)); + if (m_listener) m_listener->operationFail(QApplication::tr("Unable to set permissions of %1").arg(absPath)); return false; } } @@ -727,20 +523,23 @@ bool CArchive::extractZip() totalSize += fi.size; } - emit extractInit(0, totalSize); - emit extractStart(); + if (m_listener) + { + m_listener->operationInit(0, totalSize); + m_listener->operationStart(); + } // client won't use symbolic links so don't process them foreach (const QZipReader::FileInfo &fi, allFiles) { - const QString absPath = m_dest + QDir::separator() + fi.filePath; + const QString absPath = m_destinationDirectory + QDir::separator() + fi.filePath; if (fi.isFile) { - if (mustStop()) + if (m_listener && m_listener->operationShouldStop()) { - emit extractStop(); + m_listener->operationStop(); return true; } @@ -748,7 +547,7 @@ bool CArchive::extractZip() if (!f.open(QIODevice::WriteOnly)) { - emit extractFail(tr("Unable to open %1").arg(absPath)); + if (m_listener) m_listener->operationFail(QApplication::tr("Unable to open %1").arg(absPath)); return false; } @@ -757,58 +556,65 @@ bool CArchive::extractZip() f.setPermissions(fi.permissions); f.close(); - emit extractProgress(currentSize, QFileInfo(absPath).fileName()); + if (m_listener) m_listener->operationProgress(currentSize, QFileInfo(absPath).fileName()); } } - emit extractSuccess(totalSize); - emit done(); + if (m_listener) + { + m_listener->operationSuccess(totalSize); + m_listener->operationFinish(); + } return true; } -bool CArchive::progress(const std::string &filename, uint32 currentSize, uint32 totalSize) +bool CFilesExtractor::progress(const std::string &filename, uint32 currentSize, uint32 totalSize) { - if (mustStop()) + if (m_listener && m_listener->operationShouldStop()) { - emit extractStop(); + m_listener->operationStop(); return false; } if (currentSize == 0) { - emit extractInit(0, (qint64)totalSize); - emit extractStart(); + if (m_listener) + { + m_listener->operationInit(0, (qint64)totalSize); + m_listener->operationStart(); + } } - emit extractProgress((qint64)currentSize, qFromUtf8(filename)); + if (m_listener) m_listener->operationProgress((qint64)currentSize, qFromUtf8(filename)); if (currentSize == totalSize) { - emit extractSuccess((qint64)totalSize); - emit done(); + if (m_listener) + { + m_listener->operationSuccess((qint64)totalSize); + m_listener->operationFinish(); + } } return true; } -bool CArchive::extractBnp() +bool CFilesExtractor::extractBnp() { QString error; - emit extractPrepare(); - - NLMISC::CBigFile::TUnpackProgressCallback cbMethod = NLMISC::CBigFile::TUnpackProgressCallback(this, &CArchive::progress); + NLMISC::CBigFile::TUnpackProgressCallback cbMethod = NLMISC::CBigFile::TUnpackProgressCallback(this, &CFilesExtractor::progress); try { - if (NLMISC::CBigFile::unpack(qToUtf8(m_filename), qToUtf8(m_dest), &cbMethod)) + if (NLMISC::CBigFile::unpack(qToUtf8(m_sourceFile), qToUtf8(m_destinationDirectory), &cbMethod)) { return true; } - if (mustStop()) + if (m_listener && m_listener->operationShouldStop()) { // stopped @@ -819,37 +625,22 @@ bool CArchive::extractBnp() } catch(const NLMISC::EDiskFullError &e) { - error = tr("disk full"); + error = QApplication::tr("disk full"); } catch(const NLMISC::EWriteError &e) { - error = tr("unable to write %1").arg(qFromUtf8(e.Filename)); + error = QApplication::tr("unable to write %1").arg(qFromUtf8(e.Filename)); } catch(const NLMISC::EReadError &e) { - error = tr("unable to read %1").arg(qFromUtf8(e.Filename)); + error = QApplication::tr("unable to read %1").arg(qFromUtf8(e.Filename)); } catch(const std::exception &e) { - error = tr("failed (%1)").arg(qFromUtf8(e.what())); + error = QApplication::tr("failed (%1)").arg(qFromUtf8(e.what())); } - emit extractFail(tr("Unable to unpack %1 to %2: %3").arg(m_filename).arg(m_dest).arg(error)); + if (m_listener) m_listener->operationFail(QApplication::tr("Unable to unpack %1 to %2: %3").arg(m_sourceFile).arg(m_destinationDirectory).arg(error)); return false; } - -void CArchive::stop() -{ - QMutexLocker locker(&m_mutex); - - m_mustStop = true; -} - -bool CArchive::mustStop() -{ - QMutexLocker locker(&m_mutex); - - return m_mustStop; -} - diff --git a/code/ryzom/tools/client/ryzom_installer/src/filesextractor.h b/code/ryzom/tools/client/ryzom_installer/src/filesextractor.h new file mode 100644 index 000000000..276e4a847 --- /dev/null +++ b/code/ryzom/tools/client/ryzom_installer/src/filesextractor.h @@ -0,0 +1,53 @@ +// 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 . + +#ifndef FILEXTRACTOR_H +#define FILEXTRACTOR_H + +class IOperationProgressListener; + +/** + * Files extractor + * + * \author Cedric 'Kervala' OCHS + * \date 2016 + */ +class CFilesExtractor +{ +public: + CFilesExtractor(IOperationProgressListener *listener); + virtual ~CFilesExtractor(); + + void setSourceFile(const QString &src); + void setDesinationDirectory(const QString &src); + + bool exec(); + +protected: + + bool extract7z(); + bool extractZip(); + bool extractBnp(); + + bool progress(const std::string &filename, uint32 currentFile, uint32 totalFiles); + + IOperationProgressListener *m_listener; + + QString m_sourceFile; + QString m_destinationDirectory; +}; + +#endif diff --git a/code/ryzom/tools/client/ryzom_installer/src/main.cpp b/code/ryzom/tools/client/ryzom_installer/src/main.cpp index d4ee9926e..fe837335c 100644 --- a/code/ryzom/tools/client/ryzom_installer/src/main.cpp +++ b/code/ryzom/tools/client/ryzom_installer/src/main.cpp @@ -18,6 +18,7 @@ #include "mainwindow.h" #include "configfile.h" #include "wizarddialog.h" +#include "operationdialog.h" #include "nel/misc/path.h" #include "nel/misc/ucstring.h" @@ -98,10 +99,27 @@ int main(int argc, char *argv[]) if (displayMainWindow) { - CMainWindow mainWindow; - mainWindow.show(); + step = config.getNextStep(); - return QApplication::exec(); + if (step != CConfigFile::Done) + { + COperationDialog dialog; + + if (!dialog.exec()) displayMainWindow = false; + } + } + + if (displayMainWindow) + { + step = config.getNextStep(); + + if (step == CConfigFile::Done) + { + CMainWindow mainWindow; + mainWindow.show(); + + return QApplication::exec(); + } } return 0; diff --git a/code/ryzom/tools/client/ryzom_installer/src/mainwindow.cpp b/code/ryzom/tools/client/ryzom_installer/src/mainwindow.cpp index f8d6b6ed6..0ead4615e 100644 --- a/code/ryzom/tools/client/ryzom_installer/src/mainwindow.cpp +++ b/code/ryzom/tools/client/ryzom_installer/src/mainwindow.cpp @@ -17,59 +17,25 @@ #include "stdpch.h" #include "mainwindow.h" #include "downloader.h" -#include "archive.h" #include "wizarddialog.h" #include "profilesdialog.h" #include "configfile.h" #include "config.h" #include "profilesmodel.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 -CMainWindow::CMainWindow():QMainWindow(), m_archive(NULL), m_statusLabel(NULL) +CMainWindow::CMainWindow():QMainWindow(), m_statusLabel(NULL) { setupUi(this); -#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(onDownloadPrepare())); - connect(m_downloader, SIGNAL(downloadInit(qint64, qint64)), SLOT(onDownloadInit(qint64, qint64))); - connect(m_downloader, SIGNAL(downloadStart()), SLOT(onDownloadStart())); - connect(m_downloader, SIGNAL(downloadStop()), SLOT(onDownloadStop())); - connect(m_downloader, SIGNAL(downloadProgress(qint64)), SLOT(onDownloadProgress(qint64))); - connect(m_downloader, SIGNAL(downloadSuccess(qint64)), SLOT(onDownloadSuccess(qint64))); - connect(m_downloader, SIGNAL(downloadFail(QString)), SLOT(onDownloadFail(QString))); connect(m_downloader, SIGNAL(htmlPageContent(QString)), SLOT(onHtmlPageContent(QString))); - // archive - m_archive = new CArchive(this); - - connect(m_archive, SIGNAL(extractPrepare()), SLOT(onExtractPrepare())); - connect(m_archive, SIGNAL(extractInit(qint64, qint64)), SLOT(onExtractInit(qint64, qint64))); - connect(m_archive, SIGNAL(extractStart()), SLOT(onExtractStart())); - connect(m_archive, SIGNAL(extractStop()), SLOT(onExtractStop())); - connect(m_archive, SIGNAL(extractProgress(qint64, QString)), SLOT(onExtractProgress(qint64, QString))); - connect(m_archive, SIGNAL(extractSuccess(qint64)), SLOT(onExtractSuccess(qint64))); - connect(m_archive, SIGNAL(extractFail(QString)), SLOT(onExtractFail(QString))); - connect(m_archive, SIGNAL(done()), SLOT(onDone())); - connect(actionProfiles, SIGNAL(triggered()), SLOT(onProfiles())); connect(playButton, SIGNAL(clicked()), SLOT(onPlayClicked())); @@ -78,10 +44,14 @@ CMainWindow::CMainWindow():QMainWindow(), m_archive(NULL), m_statusLabel(NULL) connect(actionAboutQt, SIGNAL(triggered()), SLOT(onAboutQt())); connect(actionAbout, SIGNAL(triggered()), SLOT(onAbout())); + connect(profilesComboBox, SIGNAL(currentIndexChanged(int)), SLOT(onProfileChanged(int))); + m_statusLabel = new QLabel(); statusBar()->addWidget(m_statusLabel); + updateProfiles(); + // setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Maximum); } @@ -89,119 +59,9 @@ CMainWindow::~CMainWindow() { } -void CMainWindow::processNextStep() -{ - CConfigFile *config = CConfigFile::getInstance(); - - // default server - const CServer &server = config->getServer(); - - // default profile - const CProfile &configuration = config->getProfile(); - - switch(CConfigFile::getInstance()->getNextStep()) - { - case CConfigFile::DisplayNoServerError: - break; - - case CConfigFile::ShowWizard: - break; - - case CConfigFile::DownloadData: - displayProgressBar(); - m_downloader->prepareFile(config->expandVariables(server.dataDownloadUrl), config->getInstallationDirectory() + "/" + config->expandVariables(server.dataDownloadFilename) + ".part"); - break; - - case CConfigFile::ExtractDownloadedData: - displayProgressBar(); - break; - - case CConfigFile::DownloadClient: - displayProgressBar(); - m_downloader->prepareFile(config->expandVariables(server.clientDownloadUrl), config->getInstallationDirectory() + "/" + config->expandVariables(server.clientDownloadFilename) + ".part"); - break; - - case CConfigFile::ExtractDownloadedClient: - displayProgressBar(); - // TODO - break; - - case CConfigFile::CopyServerFiles: - displayProgressBar(); - m_archive->copyServerFiles(config->getSrcServerDirectory(), config->getInstallationDirectory() + "/" + server.id); - break; - - case CConfigFile::CopyProfileFiles: - displayProgressBar(); - m_archive->copyProfileFiles(config->getSrcProfileDirectory(), config->getProfileDirectory() + "/0"); - break; - - case CConfigFile::ExtractBnpClient: - displayProgressBar(); - m_archive->extract(config->getSrcServerClientBNPFullPath(), config->getInstallationDirectory() + "/" + server.id); - break; - - case CConfigFile::CleanFiles: - hideProgressBar(); - m_archive->cleanServerFiles(config->getInstallationDirectory() + "/" + server.id); - break; - - case CConfigFile::CreateProfile: - hideProgressBar(); - config->createDefaultProfile(); - onDone(); - break; - - case CConfigFile::CreateShortcuts: - hideProgressBar(); - config->createDefaultShortcuts(); - onDone(); - break; - - default: - // cases already managed in main.cpp - displayConfigurationsChoices(); - break; - } - - m_downloader->getHtmlPageContent(config->expandVariables(server.displayUrl)); -} - -void CMainWindow::displayProgressBar() -{ - downloadFrame->setVisible(true); - configurationFrame->setVisible(false); - - resumeButton->setVisible(true); - stopButton->setVisible(false); -} - -void CMainWindow::hideProgressBar() -{ - downloadFrame->setVisible(false); - configurationFrame->setVisible(false); - - resumeButton->setVisible(false); - stopButton->setVisible(false); -} - -void CMainWindow::displayConfigurationsChoices() -{ - downloadFrame->setVisible(false); - configurationFrame->setVisible(true); - - profilesComboBox->setModel(new CProfilesModel(this)); -} - void CMainWindow::showEvent(QShowEvent *e) { -#if defined(Q_OS_WIN32) && defined(QT_WINEXTRAS_LIB) - m_button->setWindow(windowHandle()); -#endif - e->accept(); - - processNextStep(); } void CMainWindow::closeEvent(QCloseEvent *e) @@ -211,28 +71,9 @@ void CMainWindow::closeEvent(QCloseEvent *e) e->accept(); } -void CMainWindow::onResumeClicked() +void CMainWindow::updateProfiles() { - m_downloader->getFile(); -} - -void CMainWindow::onStopClicked() -{ - 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; - } - - m_downloader->stop(); - } - else - { - m_archive->stop(); - } + profilesComboBox->setModel(new CProfilesModel(this)); } void CMainWindow::onPlayClicked() @@ -251,6 +92,8 @@ void CMainWindow::onPlayClicked() arguments << profile.arguments; bool started = QProcess::startDetached(profile.executable, arguments); + + CConfigFile::getInstance()->setDefaultProfileIndex(profileIndex); } void CMainWindow::onConfigureClicked() @@ -261,7 +104,10 @@ void CMainWindow::onProfiles() { CProfilesDialog dialog; - dialog.exec(); + if (dialog.exec()) + { + updateProfiles(); + } } void CMainWindow::onAbout() @@ -270,7 +116,7 @@ void CMainWindow::onAbout() QMessageBox::about(this, tr("About %1").arg("Ryzom Installer"), - QString("Ryzom Installer") + QApplication::applicationVersion() + br + + QString("Ryzom Installer %1").arg(QApplication::applicationVersion()) + br + tr("Program to install, download and manage Ryzom configurations.") + br+br+ tr("Author: %1").arg("Cedric 'Kervala' OCHS") + br + @@ -283,166 +129,20 @@ void CMainWindow::onAboutQt() QMessageBox::aboutQt(this); } -void CMainWindow::onDownloadPrepare() -{ - progressBar->setFormat(tr("%p% (%v/%m KiB)")); - - progressBar->setMinimum(0); - progressBar->setMaximum(0); - progressBar->setValue(0); - - resumeButton->setVisible(false); - stopButton->setVisible(false); -} - -void CMainWindow::onDownloadInit(qint64 current, qint64 total) -{ - resumeButton->setVisible(true); - stopButton->setVisible(false); - - progressBar->setMinimum(0); - progressBar->setMaximum(total / 1024); - progressBar->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 CMainWindow::onDownloadStart() -{ - resumeButton->setVisible(false); - stopButton->setVisible(true); - -#if defined(Q_OS_WIN32) && defined(QT_WINEXTRAS_LIB) - m_button->progress()->show(); -#endif -} - -void CMainWindow::onDownloadStop() -{ - resumeButton->setVisible(true); - stopButton->setVisible(false); - -#if defined(Q_OS_WIN32) && defined(QT_WINEXTRAS_LIB) - m_button->progress()->hide(); -#endif -} - -void CMainWindow::onDownloadProgress(qint64 current) -{ - progressBar->setValue(current / 1024); - -#if defined(Q_OS_WIN32) && defined(QT_WINEXTRAS_LIB) - m_button->progress()->setValue(current / 1024); -#endif -} - -void CMainWindow::onDownloadSuccess(qint64 total) -{ - progressBar->setValue(total / 1024); - -#if defined(Q_OS_WIN32) && defined(QT_WINEXTRAS_LIB) - m_button->progress()->hide(); -#endif - - resumeButton->setVisible(false); - stopButton->setVisible(false); -} - -void CMainWindow::onDownloadFail(const QString &error) -{ - resumeButton->setVisible(true); - stopButton->setVisible(false); -} - void CMainWindow::onHtmlPageContent(const QString &html) { htmlTextEdit->setHtml(html); } -void CMainWindow::onExtractPrepare() +void CMainWindow::onProfileChanged(int profileIndex) { - progressBar->setFormat("%p%"); - - progressBar->setMinimum(0); - progressBar->setMaximum(0); - progressBar->setValue(0); - - resumeButton->setVisible(false); - stopButton->setVisible(false); -} - -void CMainWindow::onExtractInit(qint64 current, qint64 total) -{ - resumeButton->setVisible(true); - stopButton->setVisible(false); - - progressBar->setMinimum(0); - progressBar->setMaximum(total / 1024); - progressBar->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 CMainWindow::onExtractStart() -{ - resumeButton->setVisible(false); - stopButton->setVisible(true); - -#if defined(Q_OS_WIN32) && defined(QT_WINEXTRAS_LIB) - m_button->progress()->show(); -#endif -} - -void CMainWindow::onExtractStop() -{ - resumeButton->setVisible(true); - stopButton->setVisible(false); - -#if defined(Q_OS_WIN32) && defined(QT_WINEXTRAS_LIB) - m_button->progress()->hide(); -#endif -} - -void CMainWindow::onExtractProgress(qint64 current, const QString &filename) -{ - m_statusLabel->setText(tr("Extracting %1...").arg(filename)); - - progressBar->setValue(current / 1024); - -#if defined(Q_OS_WIN32) && defined(QT_WINEXTRAS_LIB) - m_button->progress()->setValue(current / 1024); -#endif -} - -void CMainWindow::onExtractSuccess(qint64 total) -{ - m_statusLabel->setText(tr("Extraction done")); - - progressBar->setValue(total / 1024); - -#if defined(Q_OS_WIN32) && defined(QT_WINEXTRAS_LIB) - m_button->progress()->hide(); -#endif + if (profileIndex < 0) return; - resumeButton->setVisible(false); - stopButton->setVisible(false); -} + CConfigFile *config = CConfigFile::getInstance(); -void CMainWindow::onDone() -{ - processNextStep(); -} + CProfile profile = config->getProfile(profileIndex); + CServer server = config->getServer(profile.server); -void CMainWindow::onExtractFail(const QString &error) -{ - resumeButton->setVisible(true); - stopButton->setVisible(false); + // load changelog + m_downloader->getHtmlPageContent(config->expandVariables(server.displayUrl)); } diff --git a/code/ryzom/tools/client/ryzom_installer/src/mainwindow.h b/code/ryzom/tools/client/ryzom_installer/src/mainwindow.h index aa2be5659..89ff52313 100644 --- a/code/ryzom/tools/client/ryzom_installer/src/mainwindow.h +++ b/code/ryzom/tools/client/ryzom_installer/src/mainwindow.h @@ -38,9 +38,6 @@ public: virtual ~CMainWindow(); public slots: - void onResumeClicked(); - void onStopClicked(); - void onPlayClicked(); void onConfigureClicked(); @@ -48,40 +45,18 @@ public slots: void onAbout(); void onAboutQt(); - void onDownloadPrepare(); - void onDownloadInit(qint64 current, qint64 total); - void onDownloadStart(); - void onDownloadStop(); - void onDownloadProgress(qint64 current); - void onDownloadSuccess(qint64 total); - void onDownloadFail(const QString &error); - void onHtmlPageContent(const QString &html); - void onExtractPrepare(); - void onExtractInit(qint64 current, qint64 total); - void onExtractStart(); - void onExtractStop(); - void onExtractProgress(qint64 current, const QString &filename); - void onExtractSuccess(qint64 total); - void onExtractFail(const QString &error); - - void onDone(); + void onProfileChanged(int index); protected: void showEvent(QShowEvent *e); void closeEvent(QCloseEvent *e); - void processNextStep(); - - void displayProgressBar(); - void hideProgressBar(); - - void displayConfigurationsChoices(); + void updateProfiles(); QWinTaskbarButton *m_button; CDownloader *m_downloader; - CArchive *m_archive; QLabel *m_statusLabel; }; diff --git a/code/ryzom/tools/client/ryzom_installer/src/operation.h b/code/ryzom/tools/client/ryzom_installer/src/operation.h new file mode 100644 index 000000000..b8cfeea34 --- /dev/null +++ b/code/ryzom/tools/client/ryzom_installer/src/operation.h @@ -0,0 +1,37 @@ +// 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 . + +#ifndef OPERATION_H +#define OPERATION_H + +class IOperationProgressListener +{ +public: + virtual ~IOperationProgressListener() {} + + virtual void operationPrepare() =0; + virtual void operationInit(qint64 current, qint64 total) =0; + virtual void operationStart() =0; + virtual void operationStop() =0; + virtual void operationProgress(qint64 current, const QString &filename) =0; + virtual void operationSuccess(qint64 total) =0; + virtual void operationFail(const QString &error) =0; + virtual void operationFinish() =0; + + virtual bool operationShouldStop() =0; +}; + +#endif diff --git a/code/ryzom/tools/client/ryzom_installer/src/operationdialog.cpp b/code/ryzom/tools/client/ryzom_installer/src/operationdialog.cpp new file mode 100644 index 000000000..88656a68a --- /dev/null +++ b/code/ryzom/tools/client/ryzom_installer/src/operationdialog.cpp @@ -0,0 +1,431 @@ +// 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); + +#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))); + + 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: + m_downloader->prepareFile(config->expandVariables(server.dataDownloadUrl), config->getInstallationDirectory() + "/" + config->expandVariables(server.dataDownloadFilename) + ".part"); + break; + + case CConfigFile::ExtractDownloadedData: + // TODO + break; + + case CConfigFile::DownloadClient: + m_downloader->prepareFile(config->expandVariables(server.clientDownloadUrl), config->getInstallationDirectory() + "/" + config->expandVariables(server.clientDownloadFilename) + ".part"); + 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() +{ + processNextStep(); +} + +void COperationDialog::copyServerFiles() +{ + CConfigFile *config = CConfigFile::getInstance(); + + // default server + const CServer &server = config->getServer(); + + // default profile + const CProfile &configuration = config->getProfile(); + + QStringList serverFiles; + serverFiles << "cfg"; + serverFiles << "data"; + serverFiles << "examples"; + serverFiles << "patch"; + serverFiles << "unpack"; + serverFiles << "client_default.cfg"; + + m_currentOperation = QApplication::tr("Copying client files needed for server %1...").arg(server.name); + m_currentOperationProgressFormat = QApplication::tr("Copying %1..."); + + CFilesCopier copier(this); + copier.setSourceDirectory(config->getSrcServerDirectory()); + copier.setDesinationDirectory(config->getInstallationDirectory() + "/" + server.id); + copier.setIncludeFilter(serverFiles); + + if (copier.exec()) + { + } + else + { + } +} + +void COperationDialog::copyProfileFiles() +{ + CConfigFile *config = CConfigFile::getInstance(); + + // default server + const CServer &server = config->getServer(); + + // default profile + const CProfile &profile = config->getProfile(); + + 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 + { + } +} + +void COperationDialog::extractBnpClient() +{ + CConfigFile *config = CConfigFile::getInstance(); + + // default server + const CServer &server = config->getServer(); + + // default profile + const CProfile &profile = config->getProfile(); + + CFilesExtractor extractor(this); + extractor.setSourceFile(config->getSrcServerClientBNPFullPath()); + extractor.setDesinationDirectory(config->getInstallationDirectory() + "/" + server.id); + extractor.exec(); +} + +void COperationDialog::cleanFiles() +{ + CConfigFile *config = CConfigFile::getInstance(); + + // default server + const CServer &server = config->getServer(); + + // default profile + const CProfile &profile = config->getProfile(); + + CFilesCleaner cleaner(this); + cleaner.setDirectory(config->getInstallationDirectory() + "/" + server.id); + cleaner.exec(); +} + +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); +} + +void COperationDialog::operationFinish() +{ + emit done(); +} + +bool COperationDialog::operationShouldStop() +{ + QMutexLocker locker(&m_abortingMutex); + + return m_aborting; +} + +bool COperationDialog::createDefaultProfile() +{ + CConfigFile *config = CConfigFile::getInstance(); + + CServer server = config->getServer(config->getDefaultServerIndex()); + + 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 + profile.desktopShortcut = QFile::exists(QStandardPaths::writableLocation(QStandardPaths::DesktopLocation) + "/Ryzom.lnk"); +#endif + + // TODO + // profile.menuShortcut + + config->addProfile(profile); + config->save(); + + onDone(); + + return true; +} + +bool COperationDialog::createDefaultShortcuts() +{ + onDone(); + + return true; +} diff --git a/code/ryzom/tools/client/ryzom_installer/src/operationdialog.h b/code/ryzom/tools/client/ryzom_installer/src/operationdialog.h new file mode 100644 index 000000000..b4004988b --- /dev/null +++ b/code/ryzom/tools/client/ryzom_installer/src/operationdialog.h @@ -0,0 +1,114 @@ +// 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 . + +#ifndef OPERATIONDIALOG_H +#define OPERATIONDIALOG_H + +#include "ui_operationdialog.h" +#include "operation.h" + +class QWinTaskbarButton; +class CDownloader; +class CArchive; + +/** + * Main window + * + * \author Cedric 'Kervala' OCHS + * \date 2016 + */ +class COperationDialog : public QDialog, public Ui::OperationDialog, public IOperationProgressListener +{ + Q_OBJECT + +public: + COperationDialog(); + virtual ~COperationDialog(); + +public slots: + void onAbortClicked(); + + void onProgressPrepare(); + void onProgressInit(qint64 current, qint64 total); + void onProgressStart(); + void onProgressStop(); + void onProgressProgress(qint64 current, const QString &filename); + void onProgressSuccess(qint64 total); + void onProgressFail(const QString &error); + void onDone(); + +signals: + // emitted when requesting real URL + void prepare(); + + // emitted when we got the initial (local) and total (remote) size of file + void init(qint64 current, qint64 total); + + // emitted when we begin to download + void start(); + + // emitted when the download stopped + void stop(); + + // emitted when extracting + void progress(qint64 current, const QString &filename); + + // emitted when the whole file is downloaded + void success(qint64 total); + + // emitted when an error occurs + void fail(const QString &error); + + // emitted when done and should process next step + void done(); + +protected: + void showEvent(QShowEvent *e); + void closeEvent(QCloseEvent *e); + + void processNextStep(); + + // operations + void copyServerFiles(); + void copyProfileFiles(); + void extractBnpClient(); + void cleanFiles(); + bool createDefaultProfile(); + bool createDefaultShortcuts(); + + // from CFilesCopier + virtual void operationPrepare(); + virtual void operationInit(qint64 current, qint64 total); + virtual void operationStart(); + virtual void operationStop(); + virtual void operationProgress(qint64 current, const QString &filename); + virtual void operationSuccess(qint64 total); + virtual void operationFail(const QString &error); + virtual void operationFinish(); + + virtual bool operationShouldStop(); + + QWinTaskbarButton *m_button; + CDownloader *m_downloader; + + QString m_currentOperation; + QString m_currentOperationProgressFormat; + + QMutex m_abortingMutex; + bool m_aborting; +}; + +#endif diff --git a/code/ryzom/tools/client/ryzom_installer/src/profilesdialog.cpp b/code/ryzom/tools/client/ryzom_installer/src/profilesdialog.cpp index ff42f12ec..c83447d47 100644 --- a/code/ryzom/tools/client/ryzom_installer/src/profilesdialog.cpp +++ b/code/ryzom/tools/client/ryzom_installer/src/profilesdialog.cpp @@ -38,7 +38,7 @@ CProfilesDialog::CProfilesDialog():QDialog(), m_currentProfileIndex(-1) profilesListView->setModel(m_model); serverComboBox->setModel(m_serversModel); - int index = m_model->getIndexFromProfileID(CConfigFile::getInstance()->getDefaultProfile()); + int index = m_model->getIndexFromProfileID(CConfigFile::getInstance()->getDefaultProfileIndex()); profilesListView->setCurrentIndex(m_model->index(index, 0)); displayProfile(index); diff --git a/code/ryzom/tools/client/ryzom_installer/src/stdpch.h b/code/ryzom/tools/client/ryzom_installer/src/stdpch.h index 5d64b580f..4ebe147f0 100644 --- a/code/ryzom/tools/client/ryzom_installer/src/stdpch.h +++ b/code/ryzom/tools/client/ryzom_installer/src/stdpch.h @@ -25,6 +25,7 @@ #undef realloc #endif +#ifdef _WIN32 #include #include #include @@ -32,17 +33,12 @@ #include #include #include +#endif #ifndef _DEBUG #define QT_NO_DEBUG_OUTPUT #endif -#include - -#ifdef Q_COMPILER_RVALUE_REFS -#undef Q_COMPILER_RVALUE_REFS -#endif - #include #include #include diff --git a/code/ryzom/tools/client/ryzom_installer/ui/mainwindow.ui b/code/ryzom/tools/client/ryzom_installer/ui/mainwindow.ui index 644a3a2c2..8ed606d37 100644 --- a/code/ryzom/tools/client/ryzom_installer/ui/mainwindow.ui +++ b/code/ryzom/tools/client/ryzom_installer/ui/mainwindow.ui @@ -7,7 +7,7 @@ 0 0 627 - 539 + 479 @@ -43,60 +43,6 @@ p, li { white-space: pre-wrap; } - - - - QFrame::StyledPanel - - - QFrame::Raised - - - - 0 - - - 0 - - - 0 - - - 0 - - - - - 0 - - - 0 - - - Qt::AlignCenter - - - %p% - - - - - - - Resume - - - - - - - Stop - - - - - - diff --git a/code/ryzom/tools/client/ryzom_installer/ui/operationdialog.ui b/code/ryzom/tools/client/ryzom_installer/ui/operationdialog.ui new file mode 100644 index 000000000..104cdd200 --- /dev/null +++ b/code/ryzom/tools/client/ryzom_installer/ui/operationdialog.ui @@ -0,0 +1,52 @@ + + + OperationDialog + + + + 0 + 0 + 400 + 106 + + + + Dialog + + + + + + TextLabel + + + + + + + TextLabel + + + + + + + 24 + + + Qt::AlignCenter + + + + + + + QDialogButtonBox::Abort + + + + + + + +