Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Provide a dialog to change the engine version of an existing container #1832

Closed
madoar opened this issue Feb 13, 2019 · 16 comments
Closed

Provide a dialog to change the engine version of an existing container #1832

madoar opened this issue Feb 13, 2019 · 16 comments
Labels
new feature POL 4 features Features that are currently supported by POL-4
Milestone

Comments

@madoar
Copy link
Collaborator

madoar commented Feb 13, 2019

Currently it is not possible to change the engine version of an existing container from inside the container tab. Therefore I propose to provide a dialog which allows changing the engine version of an existing container.

Reaching the dialog

The dialog can be reached via a new button on the overview tab in the container information panel.

Content of the dialog

I propose to design the new dialog similar to the already existing engines tab. This means that the new dialog should consist of the following areas:

  • a sidebar on the left side which contains a search box, a list of all available engine types (engine categories) and a list widget selector
  • a TabPane for each engine subcategory of the selected engine type in the sidebar.
    Each tab in the TabPane contains a combined list widget with the corresponding engine versions
  • a details panel which contains a confirmation panel to apply a selected engine version for the previously selected container

Screenshot of the mentioned engines tab:
grafik

Changing the engine version of a container

The engine version change itself should be performed in a new changeVersion version, that should be added to the Engine interface. The changeVersion method could be defined as:

boolean changeVersion(String containerName, Map<String, Object> version);

or if we want to define it analogous to createContainer:

boolean changeVersion(String subCategory, String version, String containerName);

Implementing changeVersion for the wine engine

For the wine engine the following method needs to be implemented in https://github.com/PhoenicisOrg/scripts/blob/master/Engines/Wine/Engine/Implementation/script.js:

changeVersion: function (containerName, subCategory, version) {
    // run wineserver -k
    this.install(subCategory, version);
    // update phoenicis.cfg
    // run wineserver -k
}

Implementing changeVersion for engine types that don't support version changes

For engine types that don't support version changes a dummy implementation needs to be added to their engine implementation. Such a dummy implementation could look like the following:

function changeVersion(container, version) {
   // do nothing
}

or if we want to do provide an implementation which allows for a once only execution:

function changeVersion(container, version) {
   if (!hasEngineInstalled(container)) {
      // install the engine
   }
}

Selecting all allowed engine versions for a container

Containers are often only compatible with a subset of the engine versions. If you try to apply an incompatible engine version on a container, it is possible that the container breaks. To prevent this additionally a selectCompatibleEngineVersions method should be added for the engines. This method then returns a list of all compatible engine versions for a given container.

For more information see the discussion in #1829

@ImperatorS79
Copy link
Contributor

ImperatorS79 commented Jun 2, 2019

For wine it would simply be:

changeVersion: function (containerName, subCategory, version) {
    this.kill();
    this.install(subCategory, version);
    var parts = subCategory.split("-");
    var distribution = parts[0];
    var architecture = parts[2];

    var containerNameCleaned = containerName.replace(this._containerRegex, '');
    var containerDirectory = this._winePrefixesDirectory + "/" + containerNameCleaned + "/";

    var containerConfiguration = this._configFactory.open(containerDirectory + "/phoenicis.cfg");

    containerConfiguration.writeValue("wineVersion", version);
    containerConfiguration.writeValue("wineDistribution", distribution);
    containerConfiguration.writeValue("wineArchitecture", architecture);
    this.kill();
}

But I do not know how to do the GUI part ^^.

@plata
Copy link
Collaborator

plata commented Jun 3, 2019

Just thinking: we could also make

changeVersion: function (containerName)

and open a wizard from Javascript (like e.g. the custom installer script).

Maybe this would even be the cleaner solution because we could get rid of the subcategory and version which might not be applicable for other engines at all anyways.

@ImperatorS79
Copy link
Contributor

ImperatorS79 commented Jun 3, 2019

Ok, how would you ask the user for the required wine version (There is the distribution plus the version that you can change) ?

EDIT: something like this ?

changeVersion: function (containerName) {
    var wizard = this.getWizard();
	
    this.kill();
    var architecture = containerConfiguration.readValue("wineArchitecture", "x86");
    var operatingSystem = this._operatingSystemFetcher.fetchCurrentOperationSystem().getWinePackage();
    
    var wineJson = JSON.parse(this.getAvailableVersions());
    var distributions = new Array();
    var versions = new Array();
    wineJson.forEach(function (subPart) {
        var parts = subPart.split("-");
        if(parts[2] == architecture) {
            distributions.push(parts[0]);
            versions.push(new Array()); 
            subPart.packages.forEach(function (winePackage) {
        	versions[distributions.size()].push(winePackage.version);
            });
        }
    });
    
    var selectedDistribution = wizard.menu(tr("Please select the distribution of wine."), distributions);
    var selectedVersion = wizard.menu(tr("Please select the version of wine."), versions[distributions.indexOf(selectedDistribution)]);
    subCategory = selectedDistribution + "-" + operatingSystem + "-" + architecture;
    
    this.install(subCategory, version);

    var containerNameCleaned = containerName.replace(this._containerRegex, '');
    var containerDirectory = this._winePrefixesDirectory + "/" + containerNameCleaned + "/";

    var containerConfiguration = this._configFactory.open(containerDirectory + "/phoenicis.cfg");

    containerConfiguration.writeValue("wineVersion", selectedVersion);
    containerConfiguration.writeValue("wineDistribution", selectedDistribution);
    containerConfiguration.writeValue("wineArchitecture", architecture);
    this.kill();
}

@plata
Copy link
Collaborator

plata commented Jun 3, 2019

Not completely sure about the way the wizard is retrieved (might be required to create a new one) but yeah something in that direction.

@ImperatorS79
Copy link
Contributor

How could I add a button for that in the container information tab ? (next to delete container for example)

@plata
Copy link
Collaborator

plata commented Jun 4, 2019

@ImperatorS79
Copy link
Contributor

Okay, but how do I generate a "callback" that will call the javascript changeVersion method when the button is clicked ?

@madoar
Copy link
Collaborator Author

madoar commented Jun 4, 2019

I'm still planning to remove the old org.phoenicis.javafx.views.mainwindow and org.phoenicis.javafx.views.common packages. I just don't have a lot of time to continue working on this currently.

About how to add a new button:
This is quite simple actually. Like @plata mentioned you need to add a new Button object to

This can be done similar to the other buttons, for example the delete button:

final Button deleteButton = new Button(tr("Delete container"));
deleteButton.setOnMouseClicked(event -> Optional.ofNullable(getControl().getOnDeleteContainer())
.ifPresent(onDeleteContainer -> onDeleteContainer.accept(getControl().getContainer())));

When implementing a new button you should be aware that the container overview has already been modularized by me. This means it has been split into three components:

To add behavior to your new Button object you need to add a callback method to the onMouseClicked listener (for an example see the other buttons inside the component).
Whenever the button has been clicked with the mouse the callback method is executed.

@ImperatorS79
Copy link
Contributor

But how do I ask the callback to execute a javascript method ?

@plata
Copy link
Collaborator

plata commented Jun 4, 2019

Check where this is used:

public void getEngine(String engineId, Consumer<Engine> doneCallback, Consumer<Exception> errorCallback) {

The javascript engine object can be used like a Java object.

@madoar
Copy link
Collaborator Author

madoar commented Jun 4, 2019

@ImperatorS79 To get an EnginesManager instance in the ContainerOverviewPanel you need to pass it through from ContainerInformationPanel#containerEngineController. For this purpose you need to do the following:

  • add a getter method for EnginesManager to ContainerEngineController
  • add a private final ObjectProperty<ContainerEngineController> containerEngineController; field to ContainerOverviewPanel, including an initialization command in the constructor and a property and getter method (see the other properties for an example)
  • Pass the containerEngineController to the ContainerOverviewPanel in
    private Tab createContainerOverviewTab() {
    final ContainerOverviewPanel containerOverviewPanel = new ContainerOverviewPanel();
    containerOverviewPanel.containerProperty().bind(
    ObjectBindings.map(getControl().containerProperty(), container -> (WinePrefixContainerDTO) container));
    containerOverviewPanel.onDeleteContainerProperty().bind(getControl().onDeleteContainerProperty());
    containerOverviewPanel.onOpenFileBrowserProperty().bind(getControl().onOpenFileBrowserProperty());
    final Tab containerOverviewTab = new Tab(tr("Information"), containerOverviewPanel);
    containerOverviewTab.setClosable(false);
    return containerOverviewTab;
    }

Afterwards you should be able to access the EngineManager instance via your getControl().getContainerEngineController().getEngineManager() in ContainerOverviewPanelSkin.

If you have additional questions feel free to ask!

@ImperatorS79
Copy link
Contributor

That's above my java skills ^^. I see a little bit what you mean (the general flow), but the implementation details are too difficult for me and I do not have time currently for such things.

@madoar
Copy link
Collaborator Author

madoar commented Jun 4, 2019

@ImperatorS79 what do you require to continue? If you just require a button calling a method inside an interface, implemented by a script, I can implement that for you.

@ImperatorS79
Copy link
Contributor

Just a button that call the changeVersion function in the container panel ^^.

@ImperatorS79
Copy link
Contributor

The superseded issue was alpha-3.

@ImperatorS79
Copy link
Contributor

Solved by #1970.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
new feature POL 4 features Features that are currently supported by POL-4
Projects
None yet
Development

No branches or pull requests

3 participants