Youssef
Youssef

Reputation: 1495

After QPushButton clicked execute some code and when finished automatically go to next QWizardPage

I have a wizard with three pages. First page is BasicSettings(), second page is InstallPackages() and the last page (finish) is Summary(). BasicSettings() is for creating a virtual environment. If the 'Install and update Pip' checkbox is left unchecked, the wizard should go directly to the last page Summary(), else it should go on to InstallPackages() where the user can install some packages into the created virtual environment. And the last step is from there to go to Summary() where there is the 'finish' button.

In the code example below the createButton is connected to the method execute_venv_create(). When the method has executed the code, a message box pops up, indicating that the process has finished.

Now, when the user clicks Ok I want the wizard to automatically go to the next page defined by QWizard().nextId. I thought that I could achieve that by invoking QWizard().next(), but that doesen't work. I tried connecting createButton to it, but that doesn't have an effect.

How can I make the wizard automatically go on to the next page after execute_venv_create() finished executing code and the user has confirmed the info message box?


Code to reproduce:

# -*- coding: utf-8 -*-
from PyQt5.QtGui import QIcon
from PyQt5.QtCore import Qt
from PyQt5.QtWidgets import (QApplication, QGridLayout, QLabel, QCheckBox,
                             QHBoxLayout, QVBoxLayout, QToolButton, QWizard,
                             QWizardPage, QComboBox, QTableView, QLineEdit,
                             QGroupBox, QPushButton, QMessageBox)


class VenvWizard(QWizard):
    """
    Wizard for creating and setting up a virtual environment.
    """
    def __init__(self):
        super().__init__()

        self.setWindowTitle("Venv Wizard")
        self.resize(635, 480)
        self.move(528, 153)

        basicSettings = BasicSettings()
        self.addPage(basicSettings)

        installId = self.addPage(InstallPackages())
        summaryId = self.addPage(Summary())

        # go to last page if pip wasn't selected else go to the install page
        basicSettings.nextId = (
            lambda: installId if basicSettings.withPipCBox.isChecked()
            else summaryId
        )

        # ...

class BasicSettings(QWizardPage):
    """
    Basic settings of the virtual environment to create.
    """
    def __init__(self):
        super().__init__()

        folder_icon = QIcon.fromTheme("folder")

        self.setTitle("Basic Settings")
        self.setSubTitle("..........................."
                         "...........................")

        interpreterLabel = QLabel("&Interpreter:")
        self.interprComboBox = QComboBox()
        interpreterLabel.setBuddy(self.interprComboBox)

        venvNameLabel = QLabel("Venv &name:")
        self.venvNameLineEdit = QLineEdit()
        venvNameLabel.setBuddy(self.venvNameLineEdit)

        venvLocationLabel = QLabel("&Location:")
        self.venvLocationLineEdit = QLineEdit()
        venvLocationLabel.setBuddy(self.venvLocationLineEdit)

        self.selectDirToolButton = QToolButton(icon=folder_icon)
        self.selectDirToolButton.setFixedSize(26, 27)

        placeHolder = QLabel()

        # options groupbox
        groupBox = QGroupBox("Options")

        self.withPipCBox = QCheckBox(
            "Install and update &Pip"
        )
        self.sitePackagesCBox = QCheckBox(
            "&Make system (global) site-packages dir available to venv"
        )
        self.symlinksCBox = QCheckBox(
            "Attempt to &symlink rather than copy files into venv"
        )
        self.launchVenvCBox = QCheckBox(
            "Launch a &terminal with activated venv after installation"
        )
        self.createButton = QPushButton(
            "&Create", self,
            clicked=self.execute_venv_create,
        )
        self.createButton.setFixedWidth(90)

        # box layout containing the create button
        h_BoxLayout = QHBoxLayout()
        h_BoxLayout.setContentsMargins(495, 5, 0, 0)
        h_BoxLayout.addWidget(self.createButton)

        # grid layout
        gridLayout = QGridLayout()
        gridLayout.addWidget(interpreterLabel, 0, 0, 1, 1)
        gridLayout.addWidget(self.interprComboBox, 0, 1, 1, 2)
        gridLayout.addWidget(venvNameLabel, 1, 0, 1, 1)
        gridLayout.addWidget(self.venvNameLineEdit, 1, 1, 1, 2)
        gridLayout.addWidget(venvLocationLabel, 2, 0, 1, 1)
        gridLayout.addWidget(self.venvLocationLineEdit, 2, 1, 1, 1)
        gridLayout.addWidget(self.selectDirToolButton, 2, 2, 1, 1)
        gridLayout.addWidget(placeHolder, 3, 0, 1, 2)
        gridLayout.addWidget(groupBox, 4, 0, 1, 3)
        gridLayout.addLayout(h_BoxLayout, 5, 0, 1, 0)
        self.setLayout(gridLayout)

        # options groupbox
        groupBoxLayout = QVBoxLayout()
        groupBoxLayout.addWidget(self.withPipCBox)
        groupBoxLayout.addWidget(self.sitePackagesCBox)
        groupBoxLayout.addWidget(self.symlinksCBox)
        groupBoxLayout.addWidget(self.launchVenvCBox)
        groupBox.setLayout(groupBoxLayout)

    def execute_venv_create(self):
        """
        Execute the creation process.
        """
        # do something, then display info message
        QMessageBox.information(self, "Done", "message text")
        # when user clicks 'Ok', go to the next page defined in .nextId


class InstallPackages(QWizardPage):
    """
    Install packages via `pip` into the created virtual environment.
    """
    def __init__(self):
        super().__init__()

        self.setTitle("Install Packages")
        self.setSubTitle("..........................."
                         "...........................")

        verticalLayout = QVBoxLayout()
        gridLayout = QGridLayout(self)

        pkgNameLabel = QLabel("Package name:")
        self.pkgNameLineEdit = QLineEdit()
        self.searchButton = QPushButton("Search")
        resultsTable = QTableView(self)

        gridLayout.addWidget(pkgNameLabel, 0, 0, 1, 1)
        gridLayout.addWidget(self.pkgNameLineEdit, 0, 1, 1, 1)
        gridLayout.addWidget(self.searchButton, 0, 2, 1, 1)
        gridLayout.addWidget(resultsTable, 1, 0, 1, 3)

        verticalLayout.addLayout(gridLayout)

        # ...

class Summary(QWizardPage):
    def __init__(self):
        super().__init__()

        self.setTitle("Summary")
        self.setSubTitle("..........................."
                         "...........................")

        # ...

    def initializePage(self):
        pass


if __name__ == "__main__":
    import sys

    app = QApplication(sys.argv)
    wiz = VenvWizard()
    wiz.exec_()

    sys.exit(app.exec_())

Upvotes: 0

Views: 278

Answers (1)

Dimitry Ernot
Dimitry Ernot

Reputation: 6584

The change of pages (and the button next/finish, etc.) is handled by the QWizard and not the page itself.

Since you can't call methods from QWizard in your QWizardPage, the easiest way to change the page without clicking on the next button is to use a signal:

class VenvWizard(QWizard):
    """
    Wizard for creating and setting up a virtual environment.
    """
        def __init__(self):
        super().__init__()

        self.setWindowTitle("Venv Wizard")
        self.resize(635, 480)
        self.move(528, 153)

        self.basicSettings = BasicSettings()
        self.basicSettingsId = self.addPage(self.basicSettings)

        self.installId = self.addPage(InstallPackages())
        self.summaryId = self.addPage(Summary())


        self.basicSettings.done.connect(self.next)

        # go to last page if pip wasn't selected else go to the install page

    def nextId(self):
        # Process the flow only if the current page is basic settings
        if self.currentId() != self.basicSettingsId:
            return super().nextId()

        if self.basicSettings.withPipCBox.isChecked():
            return self.installId
        else:
            return self.summaryId
    done = pyqtSignal()
    def execute_venv_create(self):
        """
        Execute the creation process.
        """
        # do something, then display info message
        ok = QMessageBox.information(self, "Done", "message text")
        # when user clicks 'Ok', go to the next page defined in .nextId
        self.done.emit()

Upvotes: 2

Related Questions