控制器脚本

对于每个安装程序,您可以为交互某些安装程序UI或功能的部分指定控制脚本。控制脚本可以向向导中添加和删除页面,更改现有页面,执行其他检查,并通过模拟用户点击与UI交互。这允许例如无人值守安装。

脚本格式必须与 QJSEngine 兼容。

本节描述了实现此类控制脚本调用的函数。它还提供了安装程序页面和每个页面上的可用小部件的概述,例如推送按钮、单选按钮和行编辑。

编写控制脚本

一个有效脚本至少需要一个构造函数,其可能如下所示

function Controller()
{
}

以下示例展示了更高级的脚本,该脚本使用 gui JavaScript 全局对象方法设置新页面标题和欢迎消息,并在目标目录页面上自动点击 下一步 按钮。

function Controller()
{
}

Controller.prototype.IntroductionPageCallback = function()
{
    var widget = gui.currentPageWidget(); // get the current wizard page
    if (widget != null) {
        widget.title = "New title."; // set the page title
        widget.MessageLabel.setText("New Message."); // set the welcome text
    }
}

Controller.prototype.TargetDirectoryPageCallback = function()
{
    gui.clickButton(buttons.NextButton); // automatically click the Next button
}

有关在控制脚本中可用的 JavaScript 全局对象的更多信息,请参阅 脚本 API

除了预定义的全局对象外,脚本 API 还支持与其他从 QObject 派生的对象进行操作。在上述代码示例中,gui.currentPageWidget() 方法返回一个类型为 QWidget 的组件。

脚本 API 利用 Qt 的对象树。从 QObject 派生的组件将它们的命名子对象作为属性导出为 JavaScript 对象,其中属性的名称与子对象的 QObject::objectName 相同。从 QObject 派生的对象的默认属性及其访问函数也可以在脚本中使用。

例如,在上面的代码中,MessageLabel 对象来自 QLabel 类。其 setText() 是其 QLabel::text 属性的设置器访问函数。

除了属性之外,从 QObject 派生的对象的信号和公共槽可以在控制器和组件脚本中同时使用。

预定义安装程序页面

QInstaller JavaScript 对象提供了对以下预定义安装程序页面的访问

  • 简介
  • 目标目录
  • 组件选择
  • 许可检查
  • 开始菜单选择
  • 准备安装
  • 执行安装
  • 安装完成

按钮 JavaScript 对象提供了一组可在安装程序页面上使用的按钮。

以下部分描述了您可以实现的用于与安装程序页面和小部件进行交互的函数,以及在每个页面上可用的按钮。

简介页面

实现Controller.prototype.IntroductionPageCallback()函数,以与介绍页面的小部件交互。

向导按钮

  • NextButton
  • CancelButton
小部件简要描述
ErrorLabel显示错误信息。
MessageLabel显示消息。默认情况下,显示“欢迎使用 设置”消息。
InformationLabel显示进度信息。
单选按钮简要描述
PackageManagerRadioButton运行维护工具时显示在页面上的包管理器单选按钮。
UpdaterRadioButton运行维护工具时显示在页面上的更新程序单选按钮。
UninstallerRadioButton运行维护工具时显示在页面上的卸载程序单选按钮。默认选中。
进度条简要描述
InformationProgressBar在获取远程软件包时显示的进度条。
Qt 核心功能简要描述
packageManagerCoreTypeChanged()如果您希望在维护工具类型更改时收到通知,请连接到此信号。

注意:此信号仅在用户已启动二进制文件作为所谓的维护工具(安装后)并在单选按钮之间切换时发出。

示例代码

function Controller()
{
    var widget = gui.pageById(QInstaller.Introduction); // get the introduction wizard page
    if (widget != null)
        widget.packageManagerCoreTypeChanged.connect(onPackageManagerCoreTypeChanged);
}

onPackageManagerCoreTypeChanged = function()
{
    console.log("Is Updater: " + installer.isUpdater());
    console.log("Is Uninstaller: " + installer.isUninstaller());
    console.log("Is Package Manager: " + installer.isPackageManager());
}

许可协议页面

实现Controller.prototype.LicenseAgreementPageCallback()函数,以与许可协议页面的小部件交互。

向导按钮

  • NextButton
  • CancelButton
  • BackButton
小部件简要描述
LicenseListWidget列出可用许可。
LicenseTextBrowser显示所选许可文件的内容。
AcceptLicenseLabel显示位于接受许可复选框旁边的文本。
AcceptLicenseCheckBox接受许可协议。

目标目录页面

实现Controller.prototype.TargetDirectoryPageCallback()函数,以与目标目录选择页的小部件交互。

向导按钮

  • NextButton
  • CancelButton
  • BackButton
小部件简要描述
MessageLabel显示消息。
TargetDirectoryLineEdit显示安装的目标目录的值。
WarningLabel显示警告。

组件选择页面

实现Controller.prototype.ComponentSelectionPageCallback()函数,以与组件选择页的小部件交互。

向导按钮

  • NextButton
  • CancelButton
  • BackButton
方法简要描述
selectAll()如果可能,选择所有可用的软件包。
deselectAll()如果可能,取消选择所有可用的软件包。
selectDefault()将可用的软件包的选中状态重置为其初始状态。
selectComponent(id)选择id(字符串)的软件包。
deselectComponent(id)取消选择id(字符串)的软件包。
推送按钮简要描述
SelectAllComponentsButton如果可能,选择所有可用的软件包。
DeselectAllComponentsButton如果可能,取消选择所有可用的软件包。
SelectDefaultComponentsButton将可用的软件包的选中状态重置为其初始状态。
ResetComponentsButton重置为已安装的组件。
FetchCategoryButton从类别获取组件。
小部件简要描述
CategoryGroupBox包含选择仓库类别的复选框。

Installer Framework 3.1引入了仓库类别作为一项新功能。当您使用包含仓库类别的安装程序时,您可以通过其显示名称选择一个类别,获取其内容,然后选择包含的组件以进行安装。

您可以按照以下方式从类别获取组件

Controller.prototype.ComponentSelectionPageCallback = function()
{
    var page = gui.pageWidgetByObjectName("ComponentSelectionPage");

    // if CategoryGroupBox is visible, check one of the checkboxes
    // and click fetch button before selecting any components
    var groupBox = gui.findChild(page, "CategoryGroupBox");
    if (groupBox) {
        console.log("groupBox found");
        // findChild second argument is the display name of the checkbox
        var checkBox = gui.findChild(page, "Archive");
        if (checkBox) {
            console.log("checkBox found");
            console.log("checkBox name: " + checkBox.text);
            if (checkBox.checked == false) {
                checkBox.click();
                var fetchButton = gui.findChild(page, "FetchCategoryButton");
                if (fetchButton) {
                    console.log("fetchButton found");
                    fetchButton.click();
                } else {
                    console.log("fetchButton NOT found");
                }
            }
        } else {
            console.log("checkBox NOT found");
        }
    } else {
        console.log("groupBox NOT found");
    }
    // you can now select components from the fetched category
}

启动菜单目录页面

实现Controller.prototype.StartMenuDirectoryPageCallback()函数,以与准备安装页面上的小部件交互。

向导按钮

  • NextButton
  • CancelButton
  • BackButton
小部件简要描述
StartMenuPathLineEdit显示创建程序快捷方式的目录。

准备安装页面

实现 Controller.prototype.ReadyForInstallationPageCallback() 函数以与准备安装页面上的小部件交互。

向导按钮

  • 提交按钮
  • CancelButton
  • BackButton
小部件简要描述
MessageLabel显示消息。
任务详情浏览器显示有关安装的一些更详细的信息。

执行安装页面

实现 Controller.prototype.PerformInstallationPageCallback() 函数以与执行安装页面上的小部件交互。

向导按钮

  • 提交按钮
  • CancelButton

完成页面

实现 Controller.prototype.FinishedPageCallback() 函数以与安装完成页面上的小部件交互。

向导按钮

  • 提交按钮
  • CancelButton
  • 完成按钮
小部件简要描述
MessageLabel显示消息。
运行它复选框文本字段,通知用户在安装过程完成后可以启动应用程序。

自定义页面

自定义页面注册为 Dynamic${ObjectName},其中 ${ObjectName} 是在 UI 文件中设置的对象名称。因此,会调用 Dynamic${ObjectName}Callback() 函数。可以使用小部件的对象名称(从 UI 文件)进行寻址。

示例代码

function Component()
{
    // add page with widget \c SomePageWidget before the target directory page
    installer.addWizardPage(component, "SomePageWidget", QInstaller.TargetDirectory)
}

Component.prototype.DynamicSomePageWidgetCallback = function()
{
    var page = gui.pageWidgetByObjectName("DynamicSomePageWidget");
    page.myButton.click, //direct child of the UI file's widget
    page.someFancyWidget.subWidget.setText("foobar") // nested widget
}

消息框

在执行安装应用程序时,例如,应用程序可能会显示有关发生的错误的消息框。当在最终用户系统上运行应用程序时,这是正常的,但它可能会破坏自动化测试套件。为了克服这个问题,Qt 安装框架显示的所有消息框都可以通过一个特定的标识符进行寻址。

标识符可能答案描述
OverwriteTargetDirectory是,否确认是否使用已存在的目录作为安装目标目录。
installationErrorOK,重试,忽略执行安装时发生了一个致命错误。
installationErrorWithRetry重试,忽略,取消安装过程中发生了一个错误。最终用户可以选择 重试 重新尝试。
AuthorizationError中止,OK无法获得提升的权限。
OperationDoesNotExistError中止,忽略尝试执行一个操作时发生了一个错误,但该操作不存在。
isAutoDependOnErrorOK在调用包脚本时发生了一个错误。无法评估该包是否有自动依赖其他包。
isDefaultErrorOK在调用包脚本时发生了一个错误。无法评估该包是否会默认安装。
DownloadError重试,取消从远程仓库下载存档哈希时发生了一个错误。最终用户可以选择 重试 再次尝试。
archiveDownloadError重试,取消从远程仓库下载存档时发生了一个错误。最终用户可以选择 重试 再次尝试。
WriteErrorOK在写入维护工具时发生了一个错误。
ElevationErrorOK无法获得提升的权限。
unknownOK在删除某包时发生了一个未知错误。
ErrorOK通用错误。
stopProcessesForUpdates重试,忽略,取消在更新一个包时发生了一个错误。在执行更新之前,需要退出一些正在运行的应用程序或进程。最终用户在选择中止后可以选择 重试
Installer_Needs_To_Be_Local_ErrorOK安装器二进制文件是从网络位置启动的,但不支持通过网络安装。
TargetDirectoryInUse安装的目标目录已包含一个安装。
WrongTargetDirectoryOK安装的目标目录是一个文件或符号链接。
正在运行OK另一个应用程序实例正在运行。

示例代码

function Controller()
{
    installer.autoRejectMessageBoxes;
    installer.setMessageBoxAutomaticAnswer("OverwriteTargetDirectory", QMessageBox.Yes);
    installer.setMessageBoxAutomaticAnswer("stopProcessesForUpdates", QMessageBox.Ignore);
}

版权所有® 2021 The Qt Company Ltd. 上述文档贡献的版权属于各自的拥有者。提供的文档是根据自由软件基金会发布的 GNU自由文档许可协议第1.3版许可的。Qt Company,Qt及其相关标志是芬兰以及其他国家的商标。所有其他商标均为各自所有者的财产。