1 // Ryzom - MMORPG Framework <http://dev.ryzom.com/projects/ryzom/>
2 // Copyright (C) 2010-2020 Winch Gate Property Limited
4 // This program is free software: you can redistribute it and/or modify
5 // it under the terms of the GNU Affero General Public License as
6 // published by the Free Software Foundation, either version 3 of the
7 // License, or (at your option) any later version.
9 // This program is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 // GNU Affero General Public License for more details.
14 // You should have received a copy of the GNU Affero General Public License
15 // along with this program. If not, see <http://www.gnu.org/licenses/>.
18 #include "operationdialog.h"
19 #include "downloader.h"
20 #include "profilesdialog.h"
21 #include "configfile.h"
23 #include "profilesmodel.h"
25 #include "nel/misc/path.h"
27 #include "filescopier.h"
28 #include "filesextractor.h"
29 #include "filescleaner.h"
31 #include "nel/misc/seven_zip.h"
33 #if defined(Q_OS_WIN32) && defined(QT_WINEXTRAS_LIB)
34 #include <QtWinExtras/QWinTaskbarProgress>
35 #include <QtWinExtras/QWinTaskbarButton>
46 COperationDialog::COperationDialog(QWidget
*parent
):QDialog(parent
), m_aborting(false), m_operation(OperationNone
),
47 m_operationStep(DisplayNoServerError
), m_operationStepCounter(0)
51 setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint
);
53 #if defined(Q_OS_WIN32) && defined(QT_WINEXTRAS_LIB)
54 m_button
= new QWinTaskbarButton(this);
58 m_downloader
= new CDownloader(this, this);
60 connect(m_downloader
, SIGNAL(downloadPrepared()), SLOT(onDownloadPrepared()));
61 connect(m_downloader
, SIGNAL(downloadDone()), SLOT(onDownloadDone()));
63 connect(operationButtonBox
, SIGNAL(clicked(QAbstractButton
*)), SLOT(onAbortClicked()));
66 connect(this, SIGNAL(prepare()), SLOT(onProgressPrepare()));
67 connect(this, SIGNAL(init(qint64
, qint64
)), SLOT(onProgressInit(qint64
, qint64
)));
68 connect(this, SIGNAL(start()), SLOT(onProgressStart()));
69 connect(this, SIGNAL(stop()), SLOT(onProgressStop()));
70 connect(this, SIGNAL(progress(qint64
, QString
)), SLOT(onProgressProgress(qint64
, QString
)));
71 connect(this, SIGNAL(success(qint64
)), SLOT(onProgressSuccess(qint64
)));
72 connect(this, SIGNAL(fail(QString
)), SLOT(onProgressFail(QString
)));
73 connect(this, SIGNAL(operationDone()), SLOT(onDone()));
78 setFixedHeight(height());
83 COperationDialog::~COperationDialog()
87 void COperationDialog::setOperation(OperationType operation
)
89 m_operation
= operation
;
92 void COperationDialog::setUninstallComponents(const SComponents
&components
)
94 m_removeComponents
= components
;
97 void COperationDialog::processNextStep()
99 if (operationShouldStop())
107 case OperationMigrate
:
108 case OperationInstall
:
109 processInstallNextStep();
112 case OperationUpdateProfiles
:
113 processUpdateProfilesNextStep();
116 case OperationUninstall
:
117 processUninstallNextStep();
125 void COperationDialog::processInstallNextStep()
127 CConfigFile
*config
= CConfigFile::getInstance();
129 // long operations are done in a thread
130 OperationStep step
= config
->getInstallNextStep();
132 if (step
== m_operationStep
)
134 ++m_operationStepCounter
;
138 m_operationStep
= step
;
139 m_operationStepCounter
= 0;
142 if (m_operationStepCounter
> 10)
144 nlwarning("Possible infinite loop, step %s %d times", Q2C(stepToString(m_operationStep
)), m_operationStepCounter
);
153 case ExtractDownloadedData
:
154 QtConcurrent::run(this, &COperationDialog::extractDownloadedData
);
161 case ExtractDownloadedClient
:
162 QtConcurrent::run(this, &COperationDialog::extractDownloadedClient
);
166 QtConcurrent::run(this, &COperationDialog::copyDataFiles
);
169 case CopyProfileFiles
:
170 QtConcurrent::run(this, &COperationDialog::copyProfileFiles
);
174 QtConcurrent::run(this, &COperationDialog::cleanFiles
);
177 case ExtractBnpClient
:
178 QtConcurrent::run(this, &COperationDialog::extractBnpClient
);
182 QtConcurrent::run(this, &COperationDialog::copyInstaller
);
185 case UninstallOldClient
:
186 uninstallOldClient();
190 createDefaultProfile();
193 case CreateProfileShortcuts
:
194 createProfileShortcuts(0);
197 case CreateAddRemoveEntry
:
198 createAddRemoveEntry();
202 case LaunchInstalledInstaller
:
207 // cases already managed in main.cpp
208 nlwarning("Shouldn't happen, step %s", Q2C(stepToString(step
)));
214 void COperationDialog::updateAddRemoveComponents()
216 QStringList serversToUpdate
;
218 QStringList profilesToDelete
;
219 QStringList profilesToAdd
;
221 CConfigFile
*config
= CConfigFile::getInstance();
223 foreach(const CProfile
&profile
, config
->getProfiles())
225 // append all new profiles
226 profilesToAdd
<< profile
.id
;
229 foreach(const CProfile
&profile
, config
->getBackupProfiles())
231 // append all old profiles
232 profilesToDelete
<< profile
.id
;
234 // remove profiles that didn't exist
235 profilesToAdd
.removeAll(profile
.id
);
237 // delete all shortcuts, we'll recreate them later
238 profile
.deleteShortcuts();
241 const CServer
&defaultServer
= config
->getServer();
243 foreach(const CProfile
&profile
, config
->getProfiles())
245 const CServer
&server
= config
->getServer(profile
.server
);
247 QString serverDirectory
= server
.getDirectory();
249 // check if Ryzom is installed in new server directory
250 if (server
.id
!= defaultServer
.id
&& !config
->isRyzomInstalledIn(serverDirectory
) && serversToUpdate
.indexOf(server
.id
) == -1)
252 serversToUpdate
<< server
.id
;
255 // remove profiles that still exist
256 profilesToDelete
.removeAll(profile
.id
);
258 // delete all shortcuts, they'll be recreated later
259 profile
.deleteShortcuts();
262 // update components to remove
263 m_removeComponents
.profiles
<< profilesToDelete
;
264 m_removeComponents
.installer
= false;
265 m_removeComponents
.downloadedFiles
= false;
267 // update components to add
268 m_addComponents
.profiles
<< profilesToAdd
;
269 m_addComponents
.servers
<< serversToUpdate
;
270 m_addComponents
.installer
= false;
271 m_addComponents
.downloadedFiles
= false;
274 void COperationDialog::processUpdateProfilesNextStep()
276 m_currentOperation
= tr("Updating profiles...");
278 // for "update profiles" operations, we set installer to false when components are updated,
279 // since we're not using this variable
280 if (m_addComponents
.installer
&& m_removeComponents
.installer
)
282 updateAddRemoveComponents();
285 // TODO: check all servers are downloaded
286 // TODO: delete profiles directories that are not used anymore
288 if (!m_removeComponents
.profiles
.isEmpty())
290 // delete profiles in another thread
291 QtConcurrent::run(this, &COperationDialog::deleteComponentsProfiles
);
295 if (!m_addComponents
.profiles
.isEmpty())
297 // add profiles in another thread
298 QtConcurrent::run(this, &COperationDialog::addComponentsProfiles
);
302 CConfigFile
*config
= CConfigFile::getInstance();
304 if (!m_addComponents
.servers
.isEmpty())
306 const CServer
&defaultServer
= config
->getServer();
308 // servers files to download/update
309 foreach(const QString
&serverId
, m_addComponents
.servers
)
311 const CServer
&server
= config
->getServer(serverId
);
314 if (!config
->areRyzomDataInstalledIn(server
.getDirectory()))
316 QString dataFile
= config
->getInstallationDirectory() + "/" + server
.dataDownloadFilename
;
318 // archive already downloaded
319 if (QFile::exists(dataFile
))
321 // make server current
322 m_currentServerId
= server
.id
;
325 QtConcurrent::run(this, &COperationDialog::extractDownloadedData
);
329 // data download URLs are different, can't copy data from default server
330 if (server
.dataDownloadUrl
!= defaultServer
.dataDownloadUrl
)
345 if (!config
->isRyzomClientInstalledIn(server
.getDirectory()))
347 // client download URLs are different, can't copy client from default server
348 if (server
.clientDownloadUrl
== defaultServer
.clientDownloadUrl
)
350 if (QFile::exists(""))
359 QString clientFile
= config
->getInstallationDirectory() + "/" + config
->expandVariables(server
.clientDownloadFilename
);
364 // recreate all shortcuts
365 foreach(const CProfile
&profile
, config
->getProfiles())
367 profile
.createShortcuts();
370 updateAddRemoveEntry();
375 void COperationDialog::processUninstallNextStep()
377 CConfigFile
*config
= CConfigFile::getInstance();
379 if (!m_removeComponents
.servers
.isEmpty())
381 QtConcurrent::run(this, &COperationDialog::deleteComponentsServers
);
383 else if (!m_removeComponents
.profiles
.isEmpty())
385 QtConcurrent::run(this, &COperationDialog::deleteComponentsProfiles
);
387 else if (m_removeComponents
.downloadedFiles
)
389 QtConcurrent::run(this, &COperationDialog::deleteComponentsDownloadedFiles
);
391 else if (m_removeComponents
.installer
)
393 QtConcurrent::run(this, &COperationDialog::deleteComponentsInstaller
);
402 void COperationDialog::showEvent(QShowEvent
*e
)
404 #if defined(Q_OS_WIN32) && defined(QT_WINEXTRAS_LIB)
405 m_button
->setWindow(windowHandle());
413 void COperationDialog::closeEvent(QCloseEvent
*e
)
415 if (e
->spontaneous())
423 void COperationDialog::onAbortClicked()
425 if (m_downloader
->isDownloading())
427 if (!m_downloader
->supportsResume())
429 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?"));
431 if (res
!= QMessageBox::Yes
) return;
435 QMutexLocker
locker(&m_abortingMutex
);
439 void COperationDialog::onDownloadPrepared()
441 // actually download the file
442 m_downloader
->getFile();
445 void COperationDialog::onDownloadDone()
449 emit
operationDone();
452 void COperationDialog::onProgressPrepare()
454 operationProgressBar
->setFormat(tr("%p% (%v/%m KiB)"));
456 operationProgressBar
->setMinimum(0);
457 operationProgressBar
->setMaximum(0);
458 operationProgressBar
->setValue(0);
460 operationLabel
->setText(m_currentOperation
);
463 void COperationDialog::onProgressInit(qint64 current
, qint64 total
)
465 operationProgressBar
->setMinimum(0);
466 operationProgressBar
->setMaximum(total
/ 1024);
467 operationProgressBar
->setValue(current
/ 1024);
469 #if defined(Q_OS_WIN32) && defined(QT_WINEXTRAS_LIB)
470 m_button
->progress()->setMinimum(0);
471 m_button
->progress()->setMaximum(total
/ 1024);
472 m_button
->progress()->setValue(current
/ 1024);
476 void COperationDialog::onProgressStart()
478 #if defined(Q_OS_WIN32) && defined(QT_WINEXTRAS_LIB)
479 m_button
->progress()->show();
483 void COperationDialog::onProgressStop()
485 #if defined(Q_OS_WIN32) && defined(QT_WINEXTRAS_LIB)
486 m_button
->progress()->hide();
492 void COperationDialog::onProgressProgress(qint64 current
, const QString
&filename
)
494 operationProgressLabel
->setText(filename
);
496 operationProgressBar
->setValue(current
/ 1024);
498 #if defined(Q_OS_WIN32) && defined(QT_WINEXTRAS_LIB)
499 m_button
->progress()->setValue(current
/ 1024);
503 void COperationDialog::onProgressSuccess(qint64 total
)
505 operationProgressBar
->setValue(total
/ 1024);
507 #if defined(Q_OS_WIN32) && defined(QT_WINEXTRAS_LIB)
508 m_button
->progress()->hide();
512 void COperationDialog::onProgressFail(const QString
&error
)
514 QMessageBox::critical(this, tr("Error"), error
);
517 QMutexLocker
locker(&m_abortingMutex
);
524 void COperationDialog::onDone()
529 void COperationDialog::downloadData()
531 CConfigFile
*config
= CConfigFile::getInstance();
533 const CServer
&server
= config
->getServer(m_currentServerId
);
535 m_currentOperation
= tr("Downloading data required by server %1...").arg(server
.name
);
537 m_downloader
->prepareFile(config
->expandVariables(server
.dataDownloadUrl
), config
->getInstallationDirectory() + "/" + config
->expandVariables(server
.dataDownloadFilename
) + ".part");
540 void COperationDialog::extractDownloadedData()
542 CConfigFile
*config
= CConfigFile::getInstance();
544 const CServer
&server
= config
->getServer(m_currentServerId
);
546 m_currentOperation
= tr("Extracting data required by server %1...").arg(server
.name
);
548 QString dest
= server
.getDirectory();
551 // under OS X, data should be uncompressed in Ryzom.app/Contents/Resources
552 dest
+= "/Ryzom.app/Contents/Resources";
555 CFilesExtractor
extractor(this);
556 extractor
.setSourceFile(config
->getInstallationDirectory() + "/" + server
.dataDownloadFilename
);
557 extractor
.setDestinationDirectory(dest
);
559 if (!extractor
.exec()) return;
561 emit
operationDone();
564 void COperationDialog::downloadClient()
566 CConfigFile
*config
= CConfigFile::getInstance();
568 const CServer
&server
= config
->getServer(m_currentServerId
);
570 m_currentOperation
= tr("Downloading client required by server %1...").arg(server
.name
);
572 m_downloader
->prepareFile(config
->expandVariables(server
.clientDownloadUrl
), config
->getInstallationDirectory() + "/" + config
->expandVariables(server
.clientDownloadFilename
) + ".part");
575 void COperationDialog::extractDownloadedClient()
577 CConfigFile
*config
= CConfigFile::getInstance();
579 const CServer
&server
= config
->getServer(m_currentServerId
);
581 m_currentOperation
= tr("Extracting client required by server %1...").arg(server
.name
);
583 QString destinationDirectory
= server
.getDirectory();
585 CFilesExtractor
extractor(this);
586 extractor
.setSourceFile(config
->getInstallationDirectory() + "/" + config
->expandVariables(server
.clientDownloadFilename
));
587 extractor
.setDestinationDirectory(destinationDirectory
);
589 if (!extractor
.exec()) return;
591 launchUpgradeScript(destinationDirectory
, server
.clientFilename
);
593 emit
operationDone();
596 void COperationDialog::copyDataFiles()
598 CConfigFile
*config
= CConfigFile::getInstance();
601 const CServer
&server
= config
->getServer(m_currentServerId
);
603 m_currentOperation
= tr("Copying data required by server %1...").arg(server
.name
);
605 QStringList serverFiles
;
606 serverFiles
<< "cfg";
607 serverFiles
<< "data";
608 serverFiles
<< "examples";
609 serverFiles
<< "patch";
610 serverFiles
<< "unpack";
612 CFilesCopier
copier(this);
613 copier
.setSourceDirectory(config
->getSrcServerDirectory());
614 copier
.setDestinationDirectory(server
.getDirectory());
615 copier
.setIncludeFilter(serverFiles
);
617 if (!copier
.exec()) return;
619 emit
operationDone();
622 void COperationDialog::copyProfileFiles()
624 CConfigFile
*config
= CConfigFile::getInstance();
627 const CServer
&server
= config
->getServer();
630 const CProfile
&profile
= config
->getProfile();
632 m_currentOperation
= tr("Copying old profile to new location...");
634 QStringList profileFiles
;
635 profileFiles
<< "cache";
636 profileFiles
<< "save";
637 profileFiles
<< "user";
638 profileFiles
<< "screenshots";
639 profileFiles
<< "client.cfg";
640 profileFiles
<< "*.log";
642 CFilesCopier
copier(this);
643 copier
.setSourceDirectory(config
->getSrcProfileDirectory());
644 copier
.setDestinationDirectory(profile
.getDirectory());
645 copier
.setIncludeFilter(profileFiles
);
647 if (!copier
.exec()) return;
649 // correct path to client_default.cfg
650 profile
.createClientConfig();
652 emit
operationDone();
655 void COperationDialog::extractBnpClient()
657 CConfigFile
*config
= CConfigFile::getInstance();
660 const CServer
&server
= config
->getServer();
662 m_currentOperation
= tr("Extracting client to new location...");
664 QString destinationDirectory
= server
.getDirectory();
666 CFilesExtractor
extractor(this);
667 extractor
.setSourceFile(config
->getSrcServerClientBNPFullPath());
668 extractor
.setDestinationDirectory(destinationDirectory
);
670 if (!extractor
.exec()) return;
672 launchUpgradeScript(destinationDirectory
, server
.clientFilename
);
674 emit
operationDone();
677 void COperationDialog::launchUpgradeScript(const QString
&directory
, const QString
&executable
)
679 QString upgradeScript
= directory
+ "/upgd_nl.";
682 upgradeScript
+= "bat";
684 upgradeScript
+= "sh";
687 if (QFile::exists(upgradeScript
))
691 QProcessEnvironment env
= QProcessEnvironment::systemEnvironment();
692 env
.insert("RYZOM_CLIENT", QDir::toNativeSeparators(directory
+ "/" + executable
));
693 env
.insert("UNPACKPATH", QDir::toNativeSeparators(directory
+ "/unpack"));
694 env
.insert("ROOTPATH", QDir::toNativeSeparators(directory
));
695 env
.insert("STARTUPPATH", "");
696 process
.setProcessEnvironment(env
);
698 // permissions to execute script
699 QFileDevice::Permissions permissions
;
700 permissions
|= QFileDevice::ExeOther
;
701 permissions
|= QFileDevice::ExeOwner
;
702 permissions
|= QFileDevice::ExeUser
;
703 permissions
|= QFileDevice::ReadOther
;
704 permissions
|= QFileDevice::ReadOwner
;
705 permissions
|= QFileDevice::ReadUser
;
706 permissions
|= QFileDevice::WriteOwner
;
708 if (!QFile::setPermissions(upgradeScript
, permissions
))
710 nlwarning("Unable to set executable flag to %s", Q2C(upgradeScript
));
713 process
.start(upgradeScript
);
715 while (process
.waitForFinished())
717 nlwarning("Waiting end of %s", Q2C(upgradeScript
));
723 void COperationDialog::copyInstaller()
725 CConfigFile
*config
= CConfigFile::getInstance();
727 m_currentOperation
= tr("Copying installer to new location...");
729 QString newInstallerFullPath
= config
->getInstallerInstalledFilePath();
731 if (!newInstallerFullPath
.isEmpty())
733 QString destinationDirectory
= config
->getInstallationDirectory();
734 QString oldInstallerFullPath
= config
->getInstallerCurrentFilePath();
735 QString srcDir
= config
->getInstallerCurrentDirPath();
737 // always copy new installers
738 CFilesCopier
copier(this);
739 copier
.setIncludeFilter(config
->getInstallerRequiredFiles());
741 copier
.addFile(oldInstallerFullPath
);
743 copier
.setSourceDirectory(srcDir
);
744 copier
.setDestinationDirectory(config
->getInstallationDirectory());
746 if (!copier
.exec()) return;
750 oldInstallerFullPath
= config
->getInstallationDirectory() + "/" + QFileInfo(oldInstallerFullPath
).fileName();
752 // rename old filename if different
753 if (oldInstallerFullPath
!= newInstallerFullPath
)
755 // delete previous installer
756 QFile::remove(newInstallerFullPath
);
758 // rename new installer with final name
759 QFile::rename(oldInstallerFullPath
, newInstallerFullPath
);
763 // create menu directory if defined
764 QString path
= config
->getMenuDirectory();
766 if (!path
.isEmpty() && !QDir().mkpath(path
))
768 nlwarning("Unable to create directory %s", Q2C(path
));
771 // create installer link in menu
772 QString executable
= newInstallerFullPath
;
773 QString shortcut
= config
->getInstallerMenuShortcutFullPath();
774 QString name
= "Ryzom Installer";
778 // under Windows, icon is included in executable
780 #elif defined(Q_OS_MAC)
781 // everything is in bundle
783 // icon is in the same directory as installer
784 icon
= config
->getInstallationDirectory() + "/ryzom_installer.png";
786 // create icon if not exists
787 if (!QFile::exists(icon
) && !writeResource(":/icons/ryzom.png", icon
))
789 nlwarning("Unable to create icon %s", Q2C(icon
));
793 createShortcut(shortcut
, name
, executable
, "", icon
, "");
795 // installer already copied, don't need to copy it again
796 config
->setInstallerCopied(true);
799 emit
operationDone();
802 void COperationDialog::uninstallOldClient()
807 // use WOW6432Node in 64 bits (64 bits OS and 64 bits Installer) because Ryzom old installer was in 32 bits
808 QSettings
settings("HKEY_LOCAL_MACHINE\\SOFTWARE\\WOW6432Node\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\Ryzom", QSettings::NativeFormat
);
810 QSettings
settings("HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\Ryzom", QSettings::NativeFormat
);
813 // check if Ryzom 2.1.0 is installed
814 if (settings
.contains("UninstallString"))
816 QString uninstaller
= settings
.value("UninstallString").toString();
818 if (!uninstaller
.isEmpty() && QFile::exists(uninstaller
))
820 QMessageBox::StandardButtons button
= QMessageBox::question(this, tr("Uninstall old client"), tr("An old version of Ryzom has been detected on this system, would you like to uninstall it to save space disk?"));
822 if (button
== QMessageBox::Yes
)
825 CConfigFile::getInstance()->setUninstallingOldClient(true);
827 // remember the choice
828 CConfigFile::getInstance()->setShouldUninstallOldClient(true);
830 // launch old uninstaller
831 QDesktopServices::openUrl(QUrl::fromLocalFile(uninstaller
));
835 // don't ask this question anymore
836 CConfigFile::getInstance()->setShouldUninstallOldClient(false);
840 CConfigFile::getInstance()->save();
845 emit
operationDone();
848 void COperationDialog::cleanFiles()
850 CConfigFile
*config
= CConfigFile::getInstance();
853 const CServer
&server
= config
->getServer();
855 m_currentOperation
= tr("Cleaning obsolete files...");
857 CFilesCleaner
cleaner(this);
858 cleaner
.setDirectory(server
.getDirectory());
861 emit
operationDone();
864 bool COperationDialog::createDefaultProfile()
866 CConfigFile
*config
= CConfigFile::getInstance();
868 CServer server
= config
->getServer();
870 m_currentOperation
= tr("Creating default profile...");
875 profile
.name
= QString("Ryzom (%1)").arg(server
.name
);
876 profile
.server
= server
.id
;
877 profile
.comments
= "Default profile created by Ryzom Installer";
878 profile
.desktopShortcut
= false;
879 profile
.menuShortcut
= false;
880 // default use locale
881 profile
.language
= config
->getLanguage();
889 paths
<< "C:/Documents and Settings/All Users/Desktop";
890 // since Windows Vista
891 paths
<< "C:/Users/Public/Desktop";
893 paths
<< QStandardPaths::writableLocation(QStandardPaths::DesktopLocation
);
895 foreach(const QString
&path
, paths
)
897 if (QFile::exists(path
+ "/Ryzom.lnk")) profile
.desktopShortcut
= true;
905 paths
<< "C:/Documents and Settings/All Users/Start Menu/Programs";
906 // since Windows Vista
907 paths
<< "C:/ProgramData/Microsoft/Windows/Start Menu/Programs";
909 paths
<< QStandardPaths::writableLocation(QStandardPaths::ApplicationsLocation
);
911 foreach(const QString
&path
, paths
)
913 if (QFile::exists(path
+ "/Ryzom/Ryzom.lnk")) profile
.menuShortcut
= true;
917 config
->addProfile(profile
);
920 emit
operationDone();
925 bool COperationDialog::createProfileShortcuts(const QString
&profileId
)
927 CConfigFile
*config
= CConfigFile::getInstance();
929 const CProfile
&profile
= config
->getProfile(profileId
);
932 if (profile
.id
.isEmpty()) return false;
934 m_currentOperation
= tr("Creating shortcuts for profile %1...").arg(profile
.id
);
936 profile
.createShortcuts();
938 emit
operationDone();
943 bool COperationDialog::createAddRemoveEntry()
945 CConfigFile
*config
= CConfigFile::getInstance();
947 QString newInstallerFullPath
= config
->getInstallerInstalledFilePath();
949 if (!newInstallerFullPath
.isEmpty() && QFile::exists(newInstallerFullPath
))
952 QSettings
settings("HKEY_CURRENT_USER\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\Ryzom", QSettings::NativeFormat
);
954 QString nativeFullPath
= QDir::toNativeSeparators(newInstallerFullPath
);
956 settings
.setValue("Comments", config
->getProductComments());
957 settings
.setValue("DisplayIcon", nativeFullPath
+ ",0");
958 settings
.setValue("DisplayName", QApplication::applicationName());
959 settings
.setValue("InstallDate", QDateTime::currentDateTime().toString("Ymd"));
960 settings
.setValue("InstallLocation", config
->getInstallationDirectory());
961 settings
.setValue("NoModify", 0);
962 settings
.setValue("NoRemove", 0);
963 settings
.setValue("NoRepair", 0);
964 if (!config
->getProductPublisher().isEmpty()) settings
.setValue("Publisher", config
->getProductPublisher());
965 settings
.setValue("QuietUninstallString", nativeFullPath
+ " -u -s");
966 settings
.setValue("UninstallString", nativeFullPath
+ " -u");
967 if (!config
->getProductUpdateUrl().isEmpty()) settings
.setValue("URLUpdateInfo", config
->getProductUpdateUrl());
968 if (!config
->getProductAboutUrl().isEmpty()) settings
.setValue("URLInfoAbout", config
->getProductAboutUrl());
969 if (!config
->getProductHelpUrl().isEmpty()) settings
.setValue("HelpLink", config
->getProductHelpUrl());
974 updateAddRemoveEntry();
976 emit
operationDone();
981 bool COperationDialog::updateAddRemoveEntry()
983 CConfigFile
*config
= CConfigFile::getInstance();
985 QString newInstallerFullPath
= config
->getInstallerInstalledFilePath();
987 if (!newInstallerFullPath
.isEmpty() && QFile::exists(newInstallerFullPath
))
989 QString newInstallerFilename
= config
->getInstallerFilename();
992 QSettings
settings("HKEY_CURRENT_USER\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\Ryzom", QSettings::NativeFormat
);
994 QString version
= QApplication::applicationVersion();
996 settings
.setValue("DisplayVersion", version
);
997 settings
.setValue("EstimatedSize", (quint32
)(getDirectorySize(config
->getInstallationDirectory(), true) / 1024)); // size if in KiB
999 QStringList versionTokens
= version
.split('.');
1000 settings
.setValue("MajorVersion", versionTokens
[0].toInt());
1001 settings
.setValue("MinorVersion", versionTokens
[1].toInt());
1008 bool COperationDialog::deleteAddRemoveEntry()
1011 QSettings
settings("HKEY_CURRENT_USER\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\Ryzom", QSettings::NativeFormat
);
1012 settings
.remove("");
1018 void COperationDialog::deleteComponentsServers()
1020 m_currentOperation
= tr("Deleting client...");
1023 emit
init(0, m_removeComponents
.servers
.size());
1026 CConfigFile
*config
= CConfigFile::getInstance();
1030 foreach(const QString
&serverId
, m_removeComponents
.servers
)
1032 if (operationShouldStop())
1038 const CServer
&server
= config
->getServer(serverId
);
1040 emit
progress(i
++, server
.name
);
1042 QString path
= server
.getDirectory();
1044 if (!path
.isEmpty())
1048 if (dir
.exists() && !dir
.removeRecursively())
1050 emit
fail(tr("Unable to delete files for client %1").arg(server
.name
));
1055 // delete all links to clients
1056 for (int i
= 0; i
< config
->getProfilesCount(); ++i
)
1058 const CProfile
&profile
= config
->getProfile(i
);
1060 if (profile
.server
== serverId
)
1062 profile
.deleteShortcuts();
1067 emit
success(m_removeComponents
.servers
.size());
1069 // clear list of all servers to uninstall
1070 m_removeComponents
.servers
.clear();
1072 // delete Ryzom directory if all files have been deleted
1073 if (isDirectoryEmpty(config
->getInstallationDirectory(), true)) QDir(config
->getInstallationDirectory()).removeRecursively();
1075 emit
operationDone();
1078 void COperationDialog::addComponentsProfiles()
1080 m_currentOperation
= tr("Adding profiles...");
1082 CConfigFile
*config
= CConfigFile::getInstance();
1084 foreach(const QString
&profileId
, m_addComponents
.profiles
)
1086 const CProfile
&profile
= config
->getProfile(profileId
);
1089 if (profile
.id
.isEmpty()) continue;
1091 profile
.createShortcuts();
1092 profile
.createClientConfig();
1095 // clear list of all servers to uninstall
1096 m_addComponents
.profiles
.clear();
1098 emit
operationDone();
1101 void COperationDialog::deleteComponentsProfiles()
1103 m_currentOperation
= tr("Deleting profiles...");
1106 emit
init(0, m_removeComponents
.servers
.size());
1108 CConfigFile
*config
= CConfigFile::getInstance();
1110 // some profiles have been removed, use backup profiles
1111 bool useBackup
= !config
->getBackupProfiles().isEmpty();
1115 foreach(const QString
&profileId
, m_removeComponents
.profiles
)
1117 if (operationShouldStop())
1123 // only search in backup profiles, because they are already deleted in profiles
1124 const CProfile
&profile
= useBackup
? config
->getBackupProfile(profileId
):config
->getProfile(profileId
);
1126 // already deleted profile
1127 if (profile
.id
.isEmpty()) continue;
1129 emit
progress(i
++, profile
.name
);
1131 QString path
= profile
.getDirectory();
1133 if (!path
.isEmpty())
1137 if (dir
.exists() && !dir
.removeRecursively())
1139 emit
fail(tr("Unable to delete files for profile %1").arg(profile
.name
));
1144 profile
.deleteShortcuts();
1146 // delete profile if still used
1147 if (!useBackup
) config
->removeProfile(profileId
);
1150 emit
success(m_removeComponents
.profiles
.size());
1152 // clear list of all profiles to uninstall
1153 m_removeComponents
.profiles
.clear();
1155 // delete profiles directory if all files have been deleted
1156 if (isDirectoryEmpty(config
->getProfileDirectory(), true)) QDir(config
->getProfileDirectory()).removeRecursively();
1158 emit
operationDone();
1161 void COperationDialog::deleteComponentsInstaller()
1163 m_currentOperation
= tr("Deleting installer...");
1165 CConfigFile
*config
= CConfigFile::getInstance();
1167 deleteAddRemoveEntry();
1170 QString path
= config
->getMenuDirectory();
1172 if (!path
.isEmpty())
1176 dir
.removeRecursively();
1179 path
= config
->getInstallerInstalledDirPath();
1180 QStringList files
= config
->getInstallerRequiredFiles();
1182 foreach(const QString
&file
, files
)
1184 QString fullPath
= path
+ "/" + file
;
1187 if (QFile::exists(fullPath
) && !QFile::remove(fullPath
))
1190 // under Windows, a running executable is locked, so we need to delete it later
1191 MoveFileExW(qToWide(QDir::toNativeSeparators(fullPath
)), NULL
, MOVEFILE_DELAY_UNTIL_REBOOT
);
1196 // delete installer shortcuts
1197 removeShortcut(config
->getInstallerMenuShortcutFullPath());
1198 removeShortcut(config
->getInstallerDesktopShortcutFullPath());
1200 // delete configuration file
1203 // reset it once it's done
1204 m_removeComponents
.installer
= false;
1206 // delete Ryzom directory if all files have been deleted
1207 if (isDirectoryEmpty(config
->getInstallationDirectory(), true)) QDir(config
->getInstallationDirectory()).removeRecursively();
1210 emit
operationDone();
1213 void COperationDialog::deleteComponentsDownloadedFiles()
1215 m_currentOperation
= tr("Deleting downloaded files...");
1217 CConfigFile
*config
= CConfigFile::getInstance();
1219 QString path
= config
->getInstallationDirectory();
1229 filter
<< "ryzom_installer_uninstalling_old_client";
1231 QStringList files
= dir
.entryList(filter
, QDir::Files
);
1233 foreach(const QString
&file
, files
)
1235 if (!QFile::remove(dir
.filePath(file
)))
1237 nlwarning("Unable to delete file %s", Q2C(file
));
1241 // reset it once it's done
1242 m_removeComponents
.downloadedFiles
= false;
1244 // delete Ryzom directory if all files have been deleted
1245 if (isDirectoryEmpty(config
->getInstallationDirectory(), true)) QDir(config
->getInstallationDirectory()).removeRecursively();
1248 emit
operationDone();
1251 void COperationDialog::operationPrepare()
1256 void COperationDialog::operationInit(qint64 current
, qint64 total
)
1258 emit
init(current
, total
);
1261 void COperationDialog::operationStart()
1266 void COperationDialog::operationStop()
1271 void COperationDialog::operationProgress(qint64 current
, const QString
&filename
)
1273 emit
progress(current
, filename
);
1276 void COperationDialog::operationSuccess(qint64 total
)
1278 emit
success(total
);
1281 void COperationDialog::operationFail(const QString
&error
)
1286 void COperationDialog::operationContinue()
1288 emit
operationDone();
1291 bool COperationDialog::operationShouldStop()
1293 QMutexLocker
locker(&m_abortingMutex
);
1298 void COperationDialog::renamePartFile()
1300 QString partFile
= m_downloader
->getFileFullPath();
1302 QString finalFile
= partFile
;
1303 finalFile
.remove(".part");
1305 if (partFile
!= finalFile
)
1307 QFile::rename(partFile
, finalFile
);
1311 void COperationDialog::acceptDelayed()
1313 // wait 500ms before to call accept()
1314 QTimer::singleShot(500, this, SLOT(accept()));
1317 void COperationDialog::rejectDelayed()
1319 // wait 500ms before to call reject()
1320 QTimer::singleShot(500, this, SLOT(reject()));