Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Qt Installer Framework Offline Update - how?

I've been able to create an installation for my software. However, I can't figure out how to create another installer which could update previous installation.

I have updated component versions, software version and release dates, but whenever I run second installation over the folder with pre-installed software - I'm getting The folder you selected already exists and contains an installation. Chose different target for installation.

Any hint on how to update an existing installation using Qt installer Framework would be very welcome!

like image 905
Vlad Avatar asked Jan 27 '14 18:01

Vlad


1 Answers

I faced the same problem too. So I have downloaded the latest snapshot and studied samples. One in particular is very helpful : dynamicpage

I didn't succeed to show a popup warning to the user when he's choosing an existing location, so I have found a work around: instead, a red label is shown under the selected directory.

This is not really a solution for updating component by component, but you will be able to continue installation process.

First of all, we need to replace the default page "TargetDirectory".

In file installerscript.qs, this is what you need to add:

// 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;
    }
}

In file targetwidget.ui

This is actually not the real .ui file, just for explanation purpose. In the end of this file, I have added an empty QLabel called labelOverwrite. The text is filled with red message in targetChanged callback.

<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>

Finally, don't forget to modify your existing file 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>
like image 104
MBach Avatar answered Oct 13 '22 08:10

MBach