From 61f5549578711152a3abc8906ae2c1c7226c66ad Mon Sep 17 00:00:00 2001 From: Kai Koehne Date: Mon, 4 Mar 2013 13:31:45 +0100 Subject: Clean up Qt 5 build rules Change-Id: I2e494d5f91d1cb740c6254544cf92daaae236f1a Reviewed-by: Niels Weber Reviewed-by: Karsten Heimrich Reviewed-by: Tim Jenssen --- examples/testapp/testapp.pro | 4 ++++ installerfw.pri | 7 ++++--- src/libs/installer/installer.pro | 7 ++++++- src/sdk/sdk.pro | 7 ++++++- tools/archivegen/archivegen.pro | 2 +- tools/binarycreator/binarycreator.pro | 2 +- tools/repogen/repogen.pro | 2 +- 7 files changed, 23 insertions(+), 8 deletions(-) diff --git a/examples/testapp/testapp.pro b/examples/testapp/testapp.pro index 418d582ca..4b2e622df 100644 --- a/examples/testapp/testapp.pro +++ b/examples/testapp/testapp.pro @@ -4,6 +4,10 @@ TARGET = testapp include(../../installerfw.pri) +isEqual(QT_MAJOR_VERSION, 5) { + QT += widgets +} + !static { warning("You can use this example only with a static build of Qt and IFW!") } diff --git a/installerfw.pri b/installerfw.pri index bec36d95f..0dcc1b5e4 100644 --- a/installerfw.pri +++ b/installerfw.pri @@ -86,9 +86,10 @@ isEqual(QT_MAJOR_VERSION, 4) { QT += script network xml } } else { - QT += uitools xml - contains(QT, gui): QT += widgets - contains(QT, core): QT += concurrent core-private + QT += uitools core-private + CONFIG(static, static|shared) { + QT += concurrent network script xml + } } CONFIG += depend_includepath diff --git a/src/libs/installer/installer.pro b/src/libs/installer/installer.pro index 322c3551c..f4f416cbc 100644 --- a/src/libs/installer/installer.pro +++ b/src/libs/installer/installer.pro @@ -11,10 +11,15 @@ DLLDESTDIR = $$IFW_APP_PATH DEFINES += BUILD_LIB_INSTALLER -QT += script \ +QT += \ + script \ network \ xml +isEqual(QT_MAJOR_VERSION, 5) { + QT += concurrent widgets core-private +} + HEADERS += packagemanagercore.h \ packagemanagercore_p.h \ packagemanagergui.h \ diff --git a/src/sdk/sdk.pro b/src/sdk/sdk.pro index d376535b0..a986b41ef 100644 --- a/src/sdk/sdk.pro +++ b/src/sdk/sdk.pro @@ -4,7 +4,12 @@ TARGET = installerbase include(../../installerfw.pri) -QT += network script +QT += network script xml + +isEqual(QT_MAJOR_VERSION, 5) { + QT += widgets +} + DESTDIR = $$IFW_APP_PATH if (exists($$LRELEASE)) { diff --git a/tools/archivegen/archivegen.pro b/tools/archivegen/archivegen.pro index 5f5ad3c46..f6a40da4f 100644 --- a/tools/archivegen/archivegen.pro +++ b/tools/archivegen/archivegen.pro @@ -5,7 +5,7 @@ INCLUDEPATH += . .. ../common include(../../installerfw.pri) QT -= gui -QT += script +QT += script xml CONFIG += console DESTDIR = $$IFW_APP_PATH diff --git a/tools/binarycreator/binarycreator.pro b/tools/binarycreator/binarycreator.pro index 22c052fd4..342cde286 100644 --- a/tools/binarycreator/binarycreator.pro +++ b/tools/binarycreator/binarycreator.pro @@ -5,7 +5,7 @@ INCLUDEPATH += . .. rcc ../common include(../../installerfw.pri) QT -= gui -QT += script +QT += script xml CONFIG += console DESTDIR = $$IFW_APP_PATH diff --git a/tools/repogen/repogen.pro b/tools/repogen/repogen.pro index 760161c82..20566d600 100644 --- a/tools/repogen/repogen.pro +++ b/tools/repogen/repogen.pro @@ -5,7 +5,7 @@ INCLUDEPATH += . .. ../common include(../../installerfw.pri) QT -= gui -QT += script +QT += script xml CONFIG += console DESTDIR = $$IFW_APP_PATH -- cgit v1.2.3 From b78a3d149b5121862cacedd04fd176dc65247b90 Mon Sep 17 00:00:00 2001 From: Niels Weber Date: Fri, 8 Mar 2013 10:37:17 +0100 Subject: Make the testapp config a bit more sensible. Change-Id: Ieb047a2ce1308f3ad692415108e640f9d77947b9 Reviewed-by: Karsten Heimrich --- examples/testapp/config/config.xml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/examples/testapp/config/config.xml b/examples/testapp/config/config.xml index 7a71e15b5..e49ab7337 100644 --- a/examples/testapp/config/config.xml +++ b/examples/testapp/config/config.xml @@ -3,18 +3,18 @@ Test App 1.0.0 Test App_Hurra - Nokia - http://qt.nokia.com + Digia + http://qt.digia.com qticon watermark.png TestAppUninstaller - http://www.xxxx.com/repository + http://www.example.com/repository - @rootDir@/testinstall + @homeDir@/testinstall -- cgit v1.2.3 From 1acc2e0b11292b03a27d45f821791915a54ba583 Mon Sep 17 00:00:00 2001 From: Niels Weber Date: Fri, 8 Mar 2013 11:22:02 +0100 Subject: Fallback to Name if no DisplayName is provided Task-number: QTIFW-186 Change-Id: I0ad1bb5c28a40cba98850aba2d45b622891bcae6 Reviewed-by: Karsten Heimrich --- tools/common/repositorygen.cpp | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/tools/common/repositorygen.cpp b/tools/common/repositorygen.cpp index 4ca7867af..dcf6b6133 100644 --- a/tools/common/repositorygen.cpp +++ b/tools/common/repositorygen.cpp @@ -172,6 +172,7 @@ void QInstallerTools::generateMetaDataDirectory(const QString &outDir, const QSt bool foundDefault = false; bool foundVirtual = false; + bool foundDisplayName = false; const QDomNodeList childNodes = package.childNodes(); for (int i = 0; i < childNodes.count(); ++i) { const QDomNode node = childNodes.at(i); @@ -181,6 +182,8 @@ void QInstallerTools::generateMetaDataDirectory(const QString &outDir, const QSt foundDefault = true; if (key == QLatin1String("Virtual")) foundVirtual = true; + if (key == QLatin1String("DisplayName")) + foundDisplayName = true; if (node.isComment() || blackList.contains(key)) continue; // just skip comments and some tags... @@ -198,6 +201,13 @@ void QInstallerTools::generateMetaDataDirectory(const QString &outDir, const QSt "mutually exclusive. File: '%0'").arg(packageXmlPath)); } + if (!foundDisplayName) { + qWarning() << "No DisplayName tag found, using component Name instead."; + QDomElement displayNameElement = doc.createElement(QLatin1String("DisplayName")); + displayNameElement.appendChild(doc.createTextNode(it->name)); + update.appendChild(displayNameElement); + } + // get the size of the data quint64 componentSize = 0; quint64 compressedComponentSize = 0; -- cgit v1.2.3 From 9e4194a90026cfc9fce2d59256813193e54859d6 Mon Sep 17 00:00:00 2001 From: Tim Jenssen Date: Tue, 5 Mar 2013 12:18:37 +0100 Subject: added first version of a product key checker API This is more temporary solution to be able to use the 1.3 for new Qt releases. Change-Id: Ic28c75547da7d4d0c2efcca08cdbd76f4a0ad9f6 Reviewed-by: Karsten Heimrich Reviewed-by: Iikka Eklund Reviewed-by: Tim Jenssen --- src/libs/installer/applyproductkeyoperation.cpp | 66 ++++++++++++++++++++ src/libs/installer/applyproductkeyoperation.h | 51 ++++++++++++++++ src/libs/installer/component.cpp | 6 ++ src/libs/installer/init.cpp | 2 + src/libs/installer/installer.pro | 19 +++++- src/libs/installer/packagemanagercore.cpp | 7 +++ src/libs/installer/packagemanagercore_p.cpp | 14 ++++- src/libs/installer/productkeycheck.cpp | 80 +++++++++++++++++++++++++ src/libs/installer/productkeycheck.h | 62 +++++++++++++++++++ src/sdk/installerbasecommons.cpp | 6 +- src/sdk/tabcontroller.cpp | 6 ++ 11 files changed, 315 insertions(+), 4 deletions(-) create mode 100644 src/libs/installer/applyproductkeyoperation.cpp create mode 100644 src/libs/installer/applyproductkeyoperation.h create mode 100644 src/libs/installer/productkeycheck.cpp create mode 100644 src/libs/installer/productkeycheck.h diff --git a/src/libs/installer/applyproductkeyoperation.cpp b/src/libs/installer/applyproductkeyoperation.cpp new file mode 100644 index 000000000..4556df743 --- /dev/null +++ b/src/libs/installer/applyproductkeyoperation.cpp @@ -0,0 +1,66 @@ +/************************************************************************** +** +** Copyright (c) 2012 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of Installer Framework +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +**************************************************************************/ + +#include "applyproductkeyoperation.h" +#include "productkeycheck.h" + +using namespace QInstaller; + +ApplyProductKeyOperation::ApplyProductKeyOperation() +{ + setName(QLatin1String("ApplyProductKey")); +} + +void ApplyProductKeyOperation::backup() +{ +} + +bool ApplyProductKeyOperation::performOperation() +{ + if (!ProductKeyCheck::instance()->applyKey(arguments())) { + setError(UserDefinedError); + setErrorString(ProductKeyCheck::instance()->lastErrorString()); + } + return true; +} + +bool ApplyProductKeyOperation::undoOperation() +{ + return true; +} + +bool ApplyProductKeyOperation::testOperation() +{ + return true; +} + +Operation *ApplyProductKeyOperation::clone() const +{ + return new ApplyProductKeyOperation(); +} diff --git a/src/libs/installer/applyproductkeyoperation.h b/src/libs/installer/applyproductkeyoperation.h new file mode 100644 index 000000000..9761492a1 --- /dev/null +++ b/src/libs/installer/applyproductkeyoperation.h @@ -0,0 +1,51 @@ +/************************************************************************** +** +** Copyright (c) 2012 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of Installer Framework +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +**************************************************************************/ + +#ifndef APPLYPRODUCTKEYOPERATION_H +#define APPLYPRODUCTKEYOPERATION_H + +#include "qinstallerglobal.h" + +namespace QInstaller { + +class INSTALLER_EXPORT ApplyProductKeyOperation : public Operation +{ +public: + ApplyProductKeyOperation(); + + void backup(); + bool performOperation(); + bool undoOperation(); + bool testOperation(); + Operation *clone() const; +}; + +} // namespace + +#endif // APPLYPRODUCTKEYOPERATION_H diff --git a/src/libs/installer/component.cpp b/src/libs/installer/component.cpp index 0bdb36bff..f9e809565 100644 --- a/src/libs/installer/component.cpp +++ b/src/libs/installer/component.cpp @@ -51,6 +51,8 @@ #include #include +#include + #include #include @@ -499,6 +501,10 @@ void Component::loadLicenses(const QString &directory, const QHash::const_iterator it; for (it = licenseHash.begin(); it != licenseHash.end(); ++it) { const QString &fileName = it.value().toString(); + + if (!ProductKeyCheck::instance()->isValidLicense(fileName)) + continue; + QFileInfo fileInfo(fileName); QFile file(QString::fromLatin1("%1%2_%3.%4").arg(directory, fileInfo.baseName(), QLocale().name().toLower(), fileInfo.completeSuffix())); diff --git a/src/libs/installer/init.cpp b/src/libs/installer/init.cpp index 3b1f7dd32..e0c51a2f3 100644 --- a/src/libs/installer/init.cpp +++ b/src/libs/installer/init.cpp @@ -58,6 +58,7 @@ #include "linereplaceoperation.h" #include "minimumprogressoperation.h" #include "licenseoperation.h" +#include "applyproductkeyoperation.h" // QtSDK specific #include "qtpatchoperation.h" @@ -240,6 +241,7 @@ void QInstaller::init() factory.registerUpdateOperation(QLatin1String("LineReplace")); factory.registerUpdateOperation(QLatin1String("MinimumProgress")); factory.registerUpdateOperation(QLatin1String("License")); + factory.registerUpdateOperation(QLatin1String("ApplyProductKey")); // QtSDK specific factory.registerUpdateOperation(QLatin1String("RegisterQtInCreatorQNX")); diff --git a/src/libs/installer/installer.pro b/src/libs/installer/installer.pro index f4f416cbc..3308876fb 100644 --- a/src/libs/installer/installer.pro +++ b/src/libs/installer/installer.pro @@ -6,6 +6,19 @@ include(../7zip/7zip.pri) include(../kdtools/kdtools.pri) include(../../../installerfw.pri) +# productkeycheck API +# call qmake "PRODUCTKEYCHECK_PRI_FILE=" +# content of that pri file needs to be: +# SOURCES += $$PWD/productkeycheck.cpp +# ... +# your files if needed +HEADERS += productkeycheck.h +!isEmpty(PRODUCTKEYCHECK_PRI_FILE) { + include($$PRODUCTKEYCHECK_PRI_FILE) +} else { + SOURCES += productkeycheck.cpp +} + DESTDIR = $$IFW_LIB_PATH DLLDESTDIR = $$IFW_APP_PATH @@ -90,7 +103,8 @@ HEADERS += packagemanagercore.h \ lib7z_facade.h \ link.h \ createlinkoperation.h \ - packagemanagercoredata.h + packagemanagercoredata.h \ + applyproductkeyoperation.h SOURCES += packagemanagercore.cpp \ packagemanagercore_p.cpp \ @@ -158,7 +172,8 @@ HEADERS += packagemanagercore.h \ lib7z_facade.cpp \ link.cpp \ createlinkoperation.cpp \ - packagemanagercoredata.cpp + packagemanagercoredata.cpp \ + applyproductkeyoperation.cpp RESOURCES += resources/patch_file_lists.qrc \ resources/installer.qrc diff --git a/src/libs/installer/packagemanagercore.cpp b/src/libs/installer/packagemanagercore.cpp index a87b56177..cb957f9aa 100644 --- a/src/libs/installer/packagemanagercore.cpp +++ b/src/libs/installer/packagemanagercore.cpp @@ -58,6 +58,8 @@ #include "settings.h" #include "utils.h" +#include + #include #include #include @@ -703,6 +705,11 @@ bool PackageManagerCore::fetchRemotePackagesTree() return false; } + if (!ProductKeyCheck::instance()->hasValidKey()) { + d->setStatus(Failure, ProductKeyCheck::instance()->lastErrorString()); + return false; + } + const LocalPackagesHash installedPackages = d->localInstalledPackages(); if (!isInstaller() && status() == Failure) return false; diff --git a/src/libs/installer/packagemanagercore_p.cpp b/src/libs/installer/packagemanagercore_p.cpp index 3bdb73ae0..e5fd39eaf 100644 --- a/src/libs/installer/packagemanagercore_p.cpp +++ b/src/libs/installer/packagemanagercore_p.cpp @@ -60,7 +60,9 @@ #include "kdupdaterupdateoperationfactory.h" #include "kdupdaterupdatefinder.h" -#include +#include + +#include #include #include #include @@ -555,6 +557,16 @@ QString PackageManagerCorePrivate::installReason(Component *component) void PackageManagerCorePrivate::initialize(const QHash ¶ms) { + if (!ProductKeyCheck::instance()->hasValidKey()) { + if (m_core->isInstaller()) { + setStatus(PackageManagerCore::Failure, ProductKeyCheck::instance()->lastErrorString()); + } else { + MessageBoxHandler::warning(MessageBoxHandler::currentBestSuitParent(), + QLatin1String("ProductKeyCheckError"), ProductKeyCheck::instance()->lastErrorString(), + ProductKeyCheck::instance()->maintainanceToolDetailErrorNotice(), QMessageBox::Ok); + } + } + m_coreCheckedHash.clear(); m_data = PackageManagerCoreData(params); m_componentsToInstallCalculated = false; diff --git a/src/libs/installer/productkeycheck.cpp b/src/libs/installer/productkeycheck.cpp new file mode 100644 index 000000000..f975db821 --- /dev/null +++ b/src/libs/installer/productkeycheck.cpp @@ -0,0 +1,80 @@ +/************************************************************************** +** +** Copyright (c) 2012 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of Installer Framework +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +**************************************************************************/ + +#include + + +class ProductKeyCheckPrivate +{ +}; + + +ProductKeyCheck::ProductKeyCheck() + : d(new ProductKeyCheckPrivate()) +{ +} + +ProductKeyCheck::~ProductKeyCheck() +{ + delete d; +} + +ProductKeyCheck *ProductKeyCheck::instance() +{ + static ProductKeyCheck *instance = 0; + if (instance == 0) + instance = new ProductKeyCheck(); + return instance; +} + +bool ProductKeyCheck::hasValidKey() +{ + return true; +} + +bool ProductKeyCheck::applyKey(const QStringList &/*arguments*/) +{ + return true; +} + +QString ProductKeyCheck::lastErrorString() +{ + return QString(); +} + +QString ProductKeyCheck::maintainanceToolDetailErrorNotice() +{ + return QString(); +} + +// to filter none valid licenses +bool ProductKeyCheck::isValidLicense(const QString &/*fileName*/) +{ + return true; +} diff --git a/src/libs/installer/productkeycheck.h b/src/libs/installer/productkeycheck.h new file mode 100644 index 000000000..1ecffc3d2 --- /dev/null +++ b/src/libs/installer/productkeycheck.h @@ -0,0 +1,62 @@ +/************************************************************************** +** +** Copyright (c) 2012 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of Installer Framework +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +**************************************************************************/ + +#ifndef PRODUCTKEYCHECK_H +#define PRODUCTKEYCHECK_H + +#include "qinstallerglobal.h" + +#include +#include + +class ProductKeyCheckPrivate; + +class INSTALLER_EXPORT ProductKeyCheck +{ +public: + ~ProductKeyCheck(); + static ProductKeyCheck *instance(); + + // was validLicense + bool hasValidKey(); + QString lastErrorString(); + QString maintainanceToolDetailErrorNotice(); + + //is used in the generic ApplyProductKeyOperation, for example to patch things + bool applyKey(const QStringList &arguments); + + // to filter none valid licenses + bool isValidLicense(const QString &fileName); + +private: + ProductKeyCheck(); + ProductKeyCheckPrivate *const d; +}; + +#endif // PRODUCTKEYCHECK_H diff --git a/src/sdk/installerbasecommons.cpp b/src/sdk/installerbasecommons.cpp index 6ae1ddc3a..5a08d20d3 100644 --- a/src/sdk/installerbasecommons.cpp +++ b/src/sdk/installerbasecommons.cpp @@ -45,6 +45,8 @@ #include #include +#include + #include #include #include @@ -112,6 +114,8 @@ IntroductionPageImpl::IntroductionPageImpl(QInstaller::PackageManagerCore *core) connect(core, SIGNAL(metaJobInfoMessage(QString)), this, SLOT(setMessage(QString))); connect(core, SIGNAL(coreNetworkSettingsChanged()), this, SLOT(onCoreNetworkSettingsChanged())); + + m_updateComponents->setEnabled(ProductKeyCheck::instance()->hasValidKey()); } int IntroductionPageImpl::nextId() const @@ -230,7 +234,7 @@ void IntroductionPageImpl::showMaintenanceTools() void IntroductionPageImpl::setMaintenanceToolsEnabled(bool enable) { m_packageManager->setEnabled(enable); - m_updateComponents->setEnabled(enable); + m_updateComponents->setEnabled(enable && ProductKeyCheck::instance()->hasValidKey()); m_removeAllComponents->setEnabled(enable); } diff --git a/src/sdk/tabcontroller.cpp b/src/sdk/tabcontroller.cpp index ad9b1db13..95b6298ee 100644 --- a/src/sdk/tabcontroller.cpp +++ b/src/sdk/tabcontroller.cpp @@ -45,6 +45,8 @@ #include +#include + #include #include @@ -123,6 +125,10 @@ void TabController::setManagerParams(const QHash ¶ms) int TabController::init() { + if (!ProductKeyCheck::instance()->hasValidKey() && d->m_core->isInstaller()) { + return PackageManagerCore::Failure; + } + if (!d->m_init) { d->m_init = true; // this should called as early as possible, to handle error message boxes for example -- cgit v1.2.3