Автономное обновление Qt Installer Framework - как?

Я смог создать установку для моего программного обеспечения. Однако я не могу понять, как создать другой установщик, который мог бы обновить предыдущую установку.

Я обновил версии компонентов, версию программного обеспечения и даты выпуска, но всякий раз, когда я запускаю вторую установку поверх папки с предварительно установленным программным обеспечением - я получаю The folder you selected already exists and contains an installation. Chose different target for installation.

Любая подсказка о том, как обновить существующую установку с использованием Qt installer Framework, будет очень кстати!

4 ответа

Я тоже столкнулся с той же проблемой. Поэтому я скачал последний снимок и изучил образцы. Один из них особенно полезен: динамическая страница

Мне не удалось показать всплывающее предупреждение пользователю, когда он выбирает существующее местоположение, поэтому я нашел обходной путь: вместо этого под выбранным каталогом отображается красная метка.

Это не совсем решение для обновления компонента за компонентом, но вы сможете продолжить процесс установки.

Прежде всего, нам нужно заменить страницу по умолчанию "TargetDirectory".

В файле installerscript.qs, это то, что вам нужно добавить:

// Constructor
function Component()
{
    component.loaded.connect(this, Component.prototype.installerLoaded);
    installer.setDefaultPageVisible(QInstaller.TargetDirectory, false);
}

// Utility function like QString QDir::toNativeSeparators(const QString & pathName) [static]
var Dir = new function () {
    this.toNativeSparator = function (path) {
        if (installer.value("os") == "win")
            return path.replace(/\//g, '\\');
        return path;
    }
};

// Called as soon as the component was loaded
Component.prototype.installerLoaded = function()
{
    if (installer.addWizardPage(component, "TargetWidget", QInstaller.TargetDirectory)) {
        var widget = gui.pageWidgetByObjectName("DynamicTargetWidget");
        if (widget != null) {
            widget.targetDirectory.textChanged.connect(this, Component.prototype.targetChanged);
            widget.targetChooser.clicked.connect(this, Component.prototype.chooseTarget);

            widget.windowTitle = "Installation Folder";
            widget.targetDirectory.text = Dir.toNativeSparator(installer.value("TargetDir"));
        }
    }
}

// Callback when one is clicking on the button to select where to install your application
Component.prototype.chooseTarget = function () {
    var widget = gui.pageWidgetByObjectName("DynamicTargetWidget");
    if (widget != null) {
        var newTarget = QFileDialog.getExistingDirectory("Choose your target directory.", widget.targetDirectory.text);
        if (newTarget != "") {
            widget.targetDirectory.text = Dir.toNativeSparator(newTarget);
        }
    }
}

Component.prototype.targetChanged = function (text) {
    var widget = gui.pageWidgetByObjectName("DynamicTargetWidget");
    if (widget != null) {
        if (text != "") {
            widget.complete = true;
            installer.setValue("TargetDir", text);
            if (installer.fileExists(text + "/components.xml")) {
                var warning = "<font color='red'>" + qsTr("A previous installation exists in this folder. If you wish to continue, everything will be overwritten.") + "</font>";
                widget.labelOverwrite.text = warning;
            } else {
                widget.labelOverwrite.text = "";
            }
            return;
        }
        widget.complete = false;
    }
}

В файле targetwidget.ui

На самом деле это не настоящий файл.ui, просто для пояснения. В конце этого файла я добавил пустой QLabel labelOverwrite, Текст заполнен красным сообщением в targetChanged Перезвоните.

<widget class="QWidget" name="TargetWidget">
  <layout class="QVBoxLayout" name="verticalLayout">
    <item>
      <widget class="QLabel" name="label">
       <property name="text">
        <string>Please specify the folder where Miam-Player will be installed.</string>
       </property>
      </widget>
    </item>
    <item>
      <layout class="QHBoxLayout" name="horizontalLayout">
       <item>
        <widget class="QLineEdit" name="targetDirectory"/>
       </item>
       <item>
        <widget class="QToolButton" name="targetChooser"/>
       </item>
      </layout>
    </item>
    <item>
      <widget class="QLabel" name="labelOverwrite"/>
    </item>
  </layout>
</widget>

Наконец, не забудьте изменить существующий файл package.xml

<?xml version="1.0" encoding="UTF-8"?>
<Package>
    <DisplayName>Miam-Player</DisplayName>
    <Description>Miam-Player is the main program. It is required and cannot be unselected.</Description>
    <Name>org.miamplayer.core</Name>
    <Script>installscript.qs</Script>
    ...
    <UserInterfaces>
        <UserInterface>targetwidget.ui</UserInterface>
    </UserInterfaces>
</Package>

Ответ Матье правильный, кроме того, если вы хотите, чтобы диалог с вопросом использовался, используйте эту функцию в installerscript.qs:

Component.prototype.targetChanged = function (text)
{
    var widget = gui.currentPageWidget(); // get the current wizard page
    var install = false;

    if (widget != null)
    {
        if (text != "")
        {
            if (installer.fileExists(text + "/components.xml"))
            {
                var result = QMessageBox.question("quit.question", "Installer", "Do you want to overwrite previous installation?",
                    QMessageBox.Yes | QMessageBox.No);
                if (result == QMessageBox.Yes)
                {
                   install = true;
                }
            }
            else
                install = true;
        }
        else
            install = false;
    }

    widget.complete = install;

    if(install)
        installer.setValue("TargetDir", text);      
}
Controller.prototype.TargetDirectoryPageCallback = function()
{
    var widget = gui.currentPageWidget();
    widget.TargetDirectoryLineEdit.textChanged.connect(this, Controller.prototype.targetChanged);
    Controller.prototype.targetChanged(widget.TargetDirectoryLineEdit.text);
}

Controller.prototype.targetChanged = function (text) {
    installer.setValue("RemoveTargetDir", true);
    if (text != "" && installer.fileExists(text + "/components.xml")) {
        if(QMessageBox.question("OverwriteTargetDirectory", "Overwrite target directory", "Do you want to overwrite previous installation?", QMessageBox.Yes | QMessageBox.No) == QMessageBox.Yes) {
            installer.setValue("RemoveTargetDir", false);
    }
}

Это просто. Вы должны сделать следующее:

  1. Если у вас нет папки установщика, взгляните на Qt/Tools/QtInstallerFramework/3.0/examples/, Для этого примера я сделал копию online папка, которую я назову my_installer_example,

  2. Обновите репозиторий для загрузки из packages_update,

От my_installer_example бежать:

./../bin/repogen --update -p packages_update / repoForUpload

Флаг --updade позволяет взять существующий репозиторий (repoForUpload) в качестве входных данных и изменяет только те компоненты, которые указаны в качестве дополнительных параметров.

  1. Загрузить repoForUpload на сервере, указанном тегом в config/config.xml,

  2. Запустить maintenancetool находится в папке установки.

Другие вопросы по тегам