Search code examples
pythonpyqt5qwizardqwizardpage

How can i disable the next button PyQt5 QWizard if a condition is not respected?


I have to do a GUI for a script running on terminal to modify the login Background on Ubuntu, i decided to use PyQt5 QWizard to do it and in the firs page i have to disable the next button if the distro used is not compatible. I can't find the way to disable it, i searched everywhere but i am not able to find the way to do it..

# -*- coding: utf-8 -*-

# Form implementation generated from reading ui file 'wizard.ui'
#
# Created by: PyQt5 UI code generator 5.14.2
#
# WARNING! All changes made in this file will be lost!

import os
from PyQt5 import QtCore, QtGui, QtWidgets
from PyQt5.QtWidgets import QFileDialog


class Ui_Wizard(object):
    def setupUi(self, Wizard):
        Wizard.setObjectName("Wizard")
        Wizard.resize(470, 454)
        Wizard.setOptions(QtWidgets.QWizard.NoBackButtonOnLastPage|QtWidgets.QWizard.NoCancelButtonOnLastPage)
        self.page_1 = QtWidgets.QWizardPage()
        self.page_1.setEnabled(True)
        self.page_1.setObjectName("page_1")
        self.gridLayout_2 = QtWidgets.QGridLayout(self.page_1)
        self.gridLayout_2.setObjectName("gridLayout_2")
        self.label_2 = QtWidgets.QLabel(self.page_1)
        self.label_2.setAlignment(QtCore.Qt.AlignCenter)
        self.label_2.setObjectName("label_2")
        self.gridLayout_2.addWidget(self.label_2, 3, 0, 1, 1)
        spacerItem = QtWidgets.QSpacerItem(20, 40, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding)
        self.gridLayout_2.addItem(spacerItem, 5, 0, 1, 1)
        spacerItem1 = QtWidgets.QSpacerItem(20, 40, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding)
        self.gridLayout_2.addItem(spacerItem1, 1, 0, 1, 1)
        self.label_1 = QtWidgets.QLabel(self.page_1)
        self.label_1.setAlignment(QtCore.Qt.AlignCenter)
        self.label_1.setObjectName("label_1")
        self.gridLayout_2.addWidget(self.label_1, 2, 0, 1, 1)
        self.label_3 = QtWidgets.QLabel(self.page_1)
        self.label_3.setAlignment(QtCore.Qt.AlignCenter)
        self.label_3.setObjectName("label_3")
        self.gridLayout_2.addWidget(self.label_3, 4, 0, 1, 1)
        Wizard.addPage(self.page_1)
        self.page_2 = QtWidgets.QWizardPage()
        self.page_2.setObjectName("page_2")
        self.gridLayout = QtWidgets.QGridLayout(self.page_2)
        self.gridLayout.setObjectName("gridLayout")
        self.label_path = QtWidgets.QLabel(self.page_2)
        self.label_path.setObjectName("label_path")
        self.gridLayout.addWidget(self.label_path, 1, 0, 1, 1)
        spacerItem2 = QtWidgets.QSpacerItem(20, 90, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding)
        self.gridLayout.addItem(spacerItem2, 0, 0, 1, 2)
        spacerItem3 = QtWidgets.QSpacerItem(20, 90, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding)
        self.gridLayout.addItem(spacerItem3, 4, 0, 1, 2)
        self.edit_path = QtWidgets.QLineEdit(self.page_2)
        self.edit_path.setObjectName("edit_path")
        self.gridLayout.addWidget(self.edit_path, 3, 0, 1, 1)
        self.browse_path = QtWidgets.QPushButton(self.page_2)
        self.browse_path.setObjectName("browse_path")
        self.gridLayout.addWidget(self.browse_path, 3, 1, 1, 1)
        Wizard.addPage(self.page_2)
        self.page_3 = QtWidgets.QWizardPage()
        self.page_3.setAutoFillBackground(False)
        self.page_3.setObjectName("page_3")
        self.verticalLayout = QtWidgets.QVBoxLayout(self.page_3)
        self.verticalLayout.setObjectName("verticalLayout")
        spacerItem4 = QtWidgets.QSpacerItem(20, 40, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding)
        self.verticalLayout.addItem(spacerItem4)
        self.label_4 = QtWidgets.QLabel(self.page_3)
        self.label_4.setAlignment(QtCore.Qt.AlignCenter)
        self.label_4.setObjectName("label_4")
        self.verticalLayout.addWidget(self.label_4)
        self.label_5 = QtWidgets.QLabel(self.page_3)
        self.label_5.setAlignment(QtCore.Qt.AlignCenter)
        self.label_5.setObjectName("label_5")
        self.verticalLayout.addWidget(self.label_5)
        self.label_6 = QtWidgets.QLabel(self.page_3)
        self.label_6.setAlignment(QtCore.Qt.AlignCenter)
        self.label_6.setTextInteractionFlags(QtCore.Qt.LinksAccessibleByMouse)
        self.label_6.setObjectName("label_6")
        self.verticalLayout.addWidget(self.label_6)
        spacerItem5 = QtWidgets.QSpacerItem(20, 40, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding)
        self.verticalLayout.addItem(spacerItem5)
        Wizard.addPage(self.page_3)

        self.retranslateUi(Wizard)
        QtCore.QMetaObject.connectSlotsByName(Wizard)

    def retranslateUi(self, Wizard):
        _translate = QtCore.QCoreApplication.translate
        Wizard.setWindowTitle(_translate("Wizard", "Wizard"))
        self.page_1.setTitle(_translate("Wizard", "Change gdm Background wizard"))
        self.page_1.setSubTitle(_translate("Wizard", "Welcomet to the Change gdm Background wizard, and thank you for the download"))
        self.label_2.setText(_translate("Wizard", "Compatibility: Ubuntu 20.04"))
        self.label_1.setText(_translate("Wizard", "Use at your own risk"))
        value = self.check_distro()
        self.label_3.setText(_translate("Wizard", value))
        self.page_2.setSubTitle(_translate("Wizard", "Select the image to use as background"))
        self.label_path.setText(_translate("Wizard", "File Path"))
        self.browse_path.setText(_translate("Wizard", "..."))
        self.browse_path.clicked.connect(self.select_file)
        self.label_4.setText(_translate("Wizard", "Background set, restarting your device"))
        self.label_5.setText(_translate("Wizard", "Thank you for download"))
        self.label_6.setText(_translate("Wizard", "Credits to: ..."))

    # To check ubuntu version
    # script usable only if usinng ubuntu 20.04
    def check_distro(self):
        check = os.uname()
        if "Ubuntu" and "20.04" not in check[3]:
            value = "Not compatible with your Distro \n Please stop"
        else:
            value = "Compatible with your Distro \n Please go ahead"
            # next_btn = QtWidget.QtGui.QWizard.NextButton
            # next_btn.setEnabled(False)
        return value

    # To open FileDialog and select file
    # TODO: Add filtering file, to select only specific extension files.
    # example .jpg or photo format
    def select_file(self):
        title = "Explorer"
        qfd = QFileDialog()
        path = "$HOME"
        filter = "All Images(*.jpg | *.jpeg | *.png);;JPG Only(*.jpg);;JPEG Only(*.jpeg);;PNG Only(*.png)"
        filename = QFileDialog.getOpenFileName(qfd, title, path, filter)
        # filter_file(title)
        # filename = QFileDialog.getOpenFileName()
        self.edit_path.setText(filename[0])

if __name__ == "__main__":
    import sys
    app = QtWidgets.QApplication(sys.argv)
    Wizard = QtWidgets.QWizard()
    ui = Ui_Wizard()
    ui.setupUi(Wizard)
    Wizard.show()
    sys.exit(app.exec_())

exactly at the first page, inside the method "check_distro" i have to disable the Next button inside the the first case of the if


Solution

  • You must override the isComplete method that returns whether or not you can advance to the next page.

    On the other hand, the method you use to verify if your OS is Ubuntu 20.04 is not correct, so it was rewritten using the distro library (you can install it with python -m pip install distro or if you are on ubuntu or compatible system then you can install it with sudo apt-get python3-distro.

    import distro
    from PyQt5 import QtCore, QtGui, QtWidgets
    
    
    class FirstPage(QtWidgets.QWizardPage):
        def __init__(self, parent=None):
            super().__init__(parent)
            self.setTitle("Change gdm Background wizard")
            self.setSubTitle(
                "Welcomet to the Change gdm Background wizard, and thank you for the download"
            )
    
            lay = QtWidgets.QVBoxLayout(self)
    
            self.message_label = QtWidgets.QLabel(alignment=QtCore.Qt.AlignCenter)
    
            lay.addStretch()
            lay.addWidget(self.message_label)
            lay.addStretch()
    
            message = "Use at your own risk\nCompatibility: Ubuntu 20.04\n%s" % (
                "Compatible with your Distro \n Please go ahead"
                if self.check_distro()
                else "Not compatible with your Distro \n Please stop"
            )
            self.message_label.setText(message)
    
        def check_distro(self):
            return distro.name() == "Ubuntu" and distro.version() == "20.04"
    
        def isComplete(self):
            return self.check_distro() and super().isComplete()
    
    
    class SecondPage(QtWidgets.QWizardPage):
        def __init__(self, parent=None):
            super().__init__(parent)
            self.setSubTitle("Select the image to use as background")
    
            self.path_le = QtWidgets.QLineEdit()
            self.path_btn = QtWidgets.QPushButton("...")
            self.path_lbl = QtWidgets.QLabel()
    
            lay = QtWidgets.QGridLayout(self)
            lay.addWidget(QtWidgets.QLabel("File Path"))
            lay.addWidget(self.path_le, 1, 0)
            lay.addWidget(self.path_btn, 1, 1)
            lay.addWidget(self.path_lbl, 2, 0, 1, 2)
    
            self.path_btn.clicked.connect(self.handle_clicked)
    
        @QtCore.pyqtSlot()
        def handle_clicked(self):
            title = "Explorer"
            path = "$HOME"
            filter = "All Images(*.jpg | *.jpeg | *.png);;JPG Only(*.jpg);;JPEG Only(*.jpeg);;PNG Only(*.png)"
            filename, _ = QtWidgets.QFileDialog.getOpenFileName(None, title, path, filter)
            if filename:
                self.path_le.setText(filename)
                self.path_lbl.setPixmap(QtGui.QPixmap(filename))
                self.completeChanged.emit()
    
        def isComplete(self):
            return bool(self.path_le.text()) and super().isComplete()
    
    
    class ThirdPage(QtWidgets.QWizardPage):
        def __init__(self, parent=None):
            super().__init__(parent)
    
            lay = QtWidgets.QVBoxLayout(self)
    
            self.message_label = QtWidgets.QLabel(alignment=QtCore.Qt.AlignCenter)
    
            lay.addStretch()
            lay.addWidget(self.message_label)
            lay.addStretch()
            self.message_label.setText(
                "Background set, restarting your device\nThank you for download\nCredits to: ..."
            )
    
    
    if __name__ == "__main__":
        import sys
    
        app = QtWidgets.QApplication(sys.argv)
        w = QtWidgets.QWizard()
        w.setOptions(
            QtWidgets.QWizard.NoBackButtonOnLastPage
            | QtWidgets.QWizard.NoCancelButtonOnLastPage
        )
        w.addPage(FirstPage())
        w.addPage(SecondPage())
        w.addPage(ThirdPage())
        w.show()
        sys.exit(app.exec_())