Controller Scripting
For each installer, you can specify a control script that interacts with certain parts of the installer's UI or functionality. To add the script to the installer, use the Configuration File element ControlScript
, or from the command line enter --script
<script_file>. The control script can add and remove pages to the wizard, change existing pages, do additional checks, and interact with the UI by simulating user clicks. This allows for example unattended installations.
The script format has to be compatible with QJSEngine.
This section describes the functions that are called to implement such a control script. It also gives an overview of installer pages and the widgets that are available on each page, such as push buttons, radio buttons, and line edits.
Writing Control Scripts
A minimal valid script needs to contain at least a constructor, which can look like this:
function Controller() { }
The following example presents a more advanced script that uses the gui JavaScript global object methods to set a new page title and welcome message on the introduction page and to automatically click the Next button on the target directory page:
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 }
For more information about the JavaScript global objects that you can use in control scripts, see Scripting API.
In addition to the predefined global objects, the scripting API supports working with other objects derived from QObject
. In the above code example the gui.currentPageWidget()
method returns a widget of type QWidget
.
The scripting API makes use of Qt's object trees. Widgets derived from QObject
export their named child objects as properties for the JavaScript object, where the name of the property is the same as the child object's QObject::objectName
. The default properties and their access functions of objects derived from QObject
can also be used in the scripts.
For example, in the above code the MessageLabel
object from class QLabel
is a child of the widget
. The setText()
is the setter access function for its QLabel::text
property.
In addition to properties, the signals and public slots of objects derived from QObject
can be used in both controller and component scripts.
Predefined Installer Pages
The QInstaller JavaScript object provides access to the following predefined installer pages:
Introduction
TargetDirectory
ComponentSelection
LicenseCheck
StartMenuSelection
ReadyForInstallation
PerformInstallation
InstallationFinished
The buttons JavaScript object provides a set of buttons that can be used on installer pages.
The following sections describe the functions that you can implement to interact with installer pages and the widgets that are available on each page.
Introduction Page
Implement the Controller.prototype.IntroductionPageCallback()
function to interact with widgets on the introduction page.
Wizard buttons:
NextButton
CancelButton
Widgets | Brief Description |
---|---|
ErrorLabel | Displays an error message. |
MessageLabel | Displays a message. By default, it displays the "Welcome to the <Name> Setup" message. |
InformationLabel | Displays progress information. |
Radio Buttons | Brief Description |
---|---|
PackageManagerRadioButton | The package manager radio button shown on the page while running as maintenance tool. |
UpdaterRadioButton | The updater radio button shown on the page while running as maintenance tool. |
UninstallerRadioButton | The uninstaller radio button shown on the page while running as maintenance tool. Selected by default. |
Progress Bar | Brief Description |
---|---|
InformationProgressBar | The progress bar shown while fetching remote packages. |
Qt Core Feature | Brief Description |
---|---|
packageManagerCoreTypeChanged() | Connect to this signal if you want to be notified when the type of maintenance tool changes. Note: The signal is only emitted when the user has started the binary as so called maintenance tool (after the installation) and switches between the radio buttons. |
Example code:
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()); }
License Agreement Page
Implement the Controller.prototype.LicenseAgreementPageCallback()
function to interact with widgets on the license agreement page.
Wizard buttons:
NextButton
CancelButton
BackButton
Widgets | Brief Description |
---|---|
LicenseListWidget | Lists the available licenses. |
LicenseTextBrowser | Shows the content of the selected license file. |
AcceptLicenseLabel | Shows the text next to the accept license check box. |
AcceptLicenseCheckBox | Accepts the license agreement. |
Target Directory Page
Implement the Controller.prototype.TargetDirectoryPageCallback()
function to interact with widgets on the target directory selection page.
Wizard buttons:
NextButton
CancelButton
BackButton
Widgets | Brief Description |
---|---|
MessageLabel | Displays a message. |
TargetDirectoryLineEdit | Displays the value of the installation's target directory. |
WarningLabel | Displays a warning. |
Component Selection Page
Implement the Controller.prototype.ComponentSelectionPageCallback()
function to interact with widgets on the component selection page.
Wizard buttons:
NextButton
CancelButton
BackButton
Methods | Brief Description |
---|---|
selectAll() | Selects all available packages if possible. |
deselectAll() | Deselects all available packages if possible. |
selectDefault() | Resets the checked state of available packages to their initial state. |
selectComponent(id) | Selects the package with id (string). |
deselectComponent(id) | Deselects the package with id (string). |
Push Buttons | Brief Description |
---|---|
SelectAllComponentsButton | Selects all available packages if possible. |
DeselectAllComponentsButton | Deselects all available packages if possible. |
SelectDefaultComponentsButton | Resets the checked state of available packages to their initial state. |
ResetComponentsButton | Resets to already installed components. |
FetchCategoryButton | Fetch components from a category. |
Widgets | Brief Description |
---|---|
CategoryGroupBox | Contains checkboxes for selecting repository categories. |
Installer Framework 3.1 introduces repository categories as a new feature. When you use an installer that contains repository categories, you can select a category by its display name, fetch its contents, and then select the included components for installation.
You can fetch the components from a category as follows:
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 }
Start Menu Directory Page
Implement the Controller.prototype.StartMenuDirectoryPageCallback()
function to interact with widgets on the ready for installation page.
Wizard buttons:
NextButton
CancelButton
BackButton
Widgets | Brief Description |
---|---|
StartMenuPathLineEdit | Shows the directory where to create the program's shortcut. |
Ready for Installation Page
Implement the Controller.prototype.ReadyForInstallationPageCallback()
function to interact with widgets on the ready for installation page.
Wizard buttons:
CommitButton
CancelButton
BackButton
Widgets | Brief Description |
---|---|
MessageLabel | Displays a message. |
TaskDetailsBrowser | Displays some more detailed information about the installation. |
Perform Installation Page
Implement the Controller.prototype.PerformInstallationPageCallback()
function to interact with widgets on the perform installation page.
Wizard buttons:
CommitButton
CancelButton
Finished Page
Implement the Controller.prototype.FinishedPageCallback()
function to interact with widgets on the installation finished page.
Wizard buttons:
CommitButton
CancelButton
FinishButton
Widgets | Brief Description |
---|---|
MessageLabel | Displays a message. |
RunItCheckBox | Text field that informs users that they can start an application after the installation process has finished. |
Custom Pages
Custom pages are registered as Dynamic${ObjectName}
, where ${ObjectName}
is the object name set in the UI file. Thus, the Dynamic${ObjectName}Callback()
function is called. Widgets can be addressed using their object names (from the UI file).
Example code:
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 }
Message Boxes
While executing the installer application, for example, the application might show some message boxes about an error that occurred. This is fine while running the application on the end user's system, but it might break automated test suites. To overcome this issue, all message boxes shown by the Qt Installer Framework are addressable by a specific identifier.
Identifier | Possible Answers | Description |
---|---|---|
OverwriteTargetDirectory | Yes, No | Confirmation for using an already existing directory as the target directory for installation. |
installationError | OK, Retry, Ignore | A fatal error occurred while performing the installation. |
installationErrorWithRetry | Retry, Ignore, Cancel | An error occurred while performing the installation. End users can select Retry to try again. |
AuthorizationError | Abort, OK | Elevated permissions could not be acquired. |
OperationDoesNotExistError | Abort, Ignore | An error occurred while trying to perform an operation, but the operation did not exist. |
isAutoDependOnError | OK | An error occurred while calling a package script. It was not possible to evaluate if the package has a auto dependency on other packages. |
isDefaultError | OK | An error occurred while calling a package script. It was not possible to evaluate if the package will be installed by default. |
DownloadError | Retry, Cancel | An error occurred while downloading an archive hash from a remote repository. End users can select Retry to try again. |
archiveDownloadError | Retry, Cancel | An error occurred while downloading a archive from a remote repository. End users can select Retry to try again. |
WriteError | OK | An error occurred while writing the maintenance tool. |
ElevationError | OK | Elevated permissions could not be acquired. |
unknown | OK | An unknown error occurred while removing a certain package. |
Error | OK | Generic error. |
stopProcessesForUpdates | Retry, Ignore, Cancel | An error occurred while updating a package. Some running application or process needs to be quit before the update can be performed. End users can select Retry to try again once they have been stopped. |
Installer_Needs_To_Be_Local_Error | OK | The installer binary was started from a network location, but the installation over network is not supported. |
TargetDirectoryInUse | No | The installation's target directory already contains an installation. |
WrongTargetDirectory | OK | The installation's target directory is a file or symlink. |
AlreadyRunning | OK | Another application instance is already running. |
Example code:
function Controller() { installer.autoRejectMessageBoxes; installer.setMessageBoxAutomaticAnswer("OverwriteTargetDirectory", QMessageBox.Yes); installer.setMessageBoxAutomaticAnswer("stopProcessesForUpdates", QMessageBox.Ignore); }
© 2021 The Qt Company Ltd. Documentation contributions included herein are the copyrights of their respective owners. The documentation provided herein is licensed under the terms of the GNU Free Documentation License version 1.3 as published by the Free Software Foundation. The Qt Company, Qt and their respective logos are trademarks of The Qt Company Ltd in Finland and/or other countries worldwide. All other trademarks are property of their respective owners.