How to use engine.show_modal

How am I supposed to use engine.show_modal?

When I click a button connected to either the dialogs accept or reject signals my dialog disappears but the window and shotgun banner are still there.

from Qt import QtWidgets, QtGui, QtCore

class Dialog(QtWidgets.QDialog):

    def __init__(self):
        super(Dialog, self).__init__()
        self.build_ui()
        self.resize(250, 150)

    def build_ui(self):
        layout = QtWidgets.QVBoxLayout()
        self.setLayout(layout)

        text = QtWidgets.QLabel('message')
        text.setAlignment(QtCore.Qt.AlignHCenter | QtCore.Qt.AlignVCenter)
        layout.addWidget(text)

        h_layout = QtWidgets.QHBoxLayout()
        yes_button = QtWidgets.QPushButton('yes')
        no_button = QtWidgets.QPushButton('no')

        no_button.setDefault(True)

        yes_button.clicked.connect(self.accept)
        no_button.clicked.connect(self.reject)

        h_layout.addWidget(yes_button)
        h_layout.addWidget(no_button)
        layout.addLayout(h_layout)


print engine.show_modal('Test', engine, Dialog)
2 Likes

I couldn’t get this to work. I’ll just give up on the shotgun banner and manage the dialog myself.

1 Like

Hi @jhultgre

I just mocked up a basic app here and replicated what you are seeing. I think the issue is that the QDialog widget doesn’t call close:

I got it to work by overriding the reject and accept methods and calling close in them.
Here is my basic app code:

from sgtk.platform import Application
from sgtk.platform.qt import QtGui, QtCore

class Dialog(QtGui.QDialog):

    def __init__(self):
        super(Dialog, self).__init__()
        self.build_ui()
        self.resize(250, 150)

    def build_ui(self):
        layout = QtGui.QVBoxLayout()
        self.setLayout(layout)

        text = QtGui.QLabel('message')
        text.setAlignment(QtCore.Qt.AlignHCenter | QtCore.Qt.AlignVCenter)
        layout.addWidget(text)

        h_layout = QtGui.QHBoxLayout()
        yes_button = QtGui.QPushButton('yes')
        no_button = QtGui.QPushButton('no')

        no_button.setDefault(True)

        yes_button.clicked.connect(self.accept)
        no_button.clicked.connect(self.reject)

        h_layout.addWidget(yes_button)
        h_layout.addWidget(no_button)
        layout.addLayout(h_layout)

    def reject(self):
        super(Dialog, self).reject()
        self.close()

    def accept(self):
        super(Dialog, self).accept()
        self.close()

class StgkStarterApp(Application):
    
    def init_app(self):
        self.engine.register_command("Show Starter Template App...", self.show_app)

    def show_app(self):
        print self.engine.show_modal('Test', self, Dialog)
1 Like

Given that we’re discussing Dialog boxes and not app UI…

Pros of using engine.show_modal:

  • Integrated with look of SgTk
  • Integrated with the host DCC’s windows
  • Closed when bundle / app is destroyed

It is a fair bit of code though, as @philip.scadding 's example above shows. Compare to this:

def warning_dialog(bundle, title, text):
    box = QtGui.QMessageBox(
        QtGui.QMessageBox.Warning, 
        title, 
        text, 
        parent=bundle.engine._get_dialog_parent()
        )
    box.show()
    box.raise_()
    box.exec_() 

The brevity of PySide’s QMessageBox static methods are preferable, but there isn’t a way to hint those to appear on top(?)

1 Like