*************************** Communicating with the user *************************** .. contents:: :local: This section shows some methods and elements that should be used to communicate with the user, in order to keep consistency in the User Interface. Showing messages. The :class:`QgsMessageBar` class ================================================== Using message boxes can be a bad idea from a user experience point of view. For showing a small info line or a warning/error messages, the QGIS message bar is usually a better option. Using the reference to the QGIS interface object, you can show a message in the message bar with the following code :: from qgis.gui import QgsMessageBar iface.messageBar().pushMessage("Error", "I'm sorry Dave, I'm afraid I can't do that", level=QgsMessageBar.CRITICAL) .. figure:: /static/pyqgis_developer_cookbook/errorbar.png :align: center :width: 40em QGIS Message bar You can set a duration to show it for a limited time :: iface.messageBar().pushMessage("Error", ""Ooops, the plugin is not working as it should", level=QgsMessageBar.CRITICAL, duration=3) .. figure:: /static/pyqgis_developer_cookbook/errorbar-timed.png :align: center :width: 40em QGIS Message bar with timer The examples above show an error bar, but the ``level`` parameter can be used to creating warning messages or info messages, using the ``QgsMessageBar.WARNING`` and ``QgsMessageBar.INFO`` constants respectively. .. figure:: /static/pyqgis_developer_cookbook/infobar.png :align: center :width: 40em QGIS Message bar (info) Widgets can be added to the message bar, like for instance a button to show more info :: def showError(): pass widget = iface.messageBar().createMessage("Missing Layers", "Show Me") button = QPushButton(widget) button.setText("Show Me") button.pressed.connect(showError) widget.layout().addWidget(button) iface.messageBar().pushWidget(widget, QgsMessageBar.WARNING) .. figure:: /static/pyqgis_developer_cookbook/bar-button.png :align: center :width: 40em QGIS Message bar with a button You can even use a message bar in your own dialog so you don't have to show a message box, or if it doesn't make sense to show it in the main QGIS window :: class MyDialog(QDialog): def __init__(self): QDialog.__init__(self) self.bar = QgsMessageBar() self.bar.setSizePolicy( QSizePolicy.Minimum, QSizePolicy.Fixed ) self.setLayout(QGridLayout()) self.layout().setContentsMargins(0, 0, 0, 0) self.buttonbox = QDialogButtonBox(QDialogButtonBox.Ok) self.buttonbox.accepted.connect(self.run) self.layout().addWidget(self.buttonbox, 0, 0, 2, 1) self.layout().addWidget(self.bar, 0, 0, 1, 1) def run(self): self.bar.pushMessage("Hello", "World", level=QgsMessageBar.INFO) .. figure:: /static/pyqgis_developer_cookbook/dialog-with-bar.png :align: center :width: 40em QGIS Message bar in custom dialog Showing progress ================ Progress bars can also be put in the QGIS message bar, since, as we have seen, it accepts widgets. Here is an example that you can try in the console. :: import time from PyQt4.QtGui import QProgressBar from PyQt4.QtCore import * progressMessageBar = iface.messageBar().createMessage("Doing something boring...") progress = QProgressBar() progress.setMaximum(10) progress.setAlignment(Qt.AlignLeft|Qt.AlignVCenter) progressMessageBar.layout().addWidget(progress) iface.messageBar().pushWidget(progressMessageBar, iface.messageBar().INFO) for i in range(10): time.sleep(1) progress.setValue(i + 1) iface.messageBar().clearWidgets() Also, you can use the built-in status bar to report progress, as in the next example :: count = layers.featureCount() for i, feature in enumerate(features): #do something time-consuming here ... percent = i / float(count) * 100 iface.mainWindow().statusBar().showMessage("Processed {} %".format(int(percent))) iface.mainWindow().statusBar().clearMessage() Logging ======= You can use the QGIS logging system to log all the information that you want to save about the execution of your code. :: # You can optionally pass a 'tag' and a 'level' parameters QgsMessageLog.logMessage("Your plugin code has been executed correctly", 'MyPlugin', QgsMessageLog.INFO) QgsMessageLog.logMessage("Your plugin code might have some problems", level=QgsMessageLog.WARNING) QgsMessageLog.logMessage("Your plugin code has crashed!", level=QgsMessageLog.CRITICAL)