1#!/usr/bin/env python
2
3#============================================================================#
4# PyQt5 port of the designer/containerextension example from Qt v5.x         #
5#----------------------------------------------------------------------------#
6from PyQt5.QtCore import pyqtProperty, pyqtSignal, pyqtSlot, QSize
7from PyQt5.QtWidgets import (QApplication, QComboBox, QLabel, QStackedWidget,
8        QVBoxLayout, QWidget)
9
10
11#============================================================================#
12# Implementation of a MultiPageWidget using a QComboBox and a QStackedWidget #
13#----------------------------------------------------------------------------#
14class PyMultiPageWidget(QWidget):
15
16    currentIndexChanged = pyqtSignal(int)
17
18    pageTitleChanged = pyqtSignal(str)
19
20    def __init__(self, parent=None):
21        super(PyMultiPageWidget, self).__init__(parent)
22
23        self.comboBox = QComboBox()
24        # MAGIC
25        # It is important that the combo box has an object name beginning
26        # with '__qt__passive_', otherwise, it is inactive in the form editor
27        # of the designer and you can't change the current page via the
28        # combo box.
29        # MAGIC
30        self.comboBox.setObjectName('__qt__passive_comboBox')
31        self.stackWidget = QStackedWidget()
32        self.comboBox.activated.connect(self.setCurrentIndex)
33        self.layout = QVBoxLayout()
34        self.layout.addWidget(self.comboBox)
35        self.layout.addWidget(self.stackWidget)
36        self.setLayout(self.layout)
37
38    def sizeHint(self):
39        return QSize(200, 150)
40
41    def count(self):
42        return self.stackWidget.count()
43
44    def widget(self, index):
45        return self.stackWidget.widget(index)
46
47    @pyqtSlot(QWidget)
48    def addPage(self, page):
49        self.insertPage(self.count(), page)
50
51    @pyqtSlot(int, QWidget)
52    def insertPage(self, index, page):
53        page.setParent(self.stackWidget)
54        self.stackWidget.insertWidget(index, page)
55        title = page.windowTitle()
56        if title == "":
57            title = "Page %d" % (self.comboBox.count() + 1)
58            page.setWindowTitle(title)
59        self.comboBox.insertItem(index, title)
60
61    @pyqtSlot(int)
62    def removePage(self, index):
63        widget = self.stackWidget.widget(index)
64        self.stackWidget.removeWidget(widget)
65        self.comboBox.removeItem(index)
66
67    def getPageTitle(self):
68        cw = self.stackWidget.currentWidget()
69        return cw.windowTitle() if cw is not None else ''
70
71    @pyqtSlot(str)
72    def setPageTitle(self, newTitle):
73        cw = self.stackWidget.currentWidget()
74        if cw is not None:
75            self.comboBox.setItemText(self.getCurrentIndex(), newTitle)
76            cw.setWindowTitle(newTitle)
77            self.pageTitleChanged.emit(newTitle)
78
79    def getCurrentIndex(self):
80        return self.stackWidget.currentIndex()
81
82    @pyqtSlot(int)
83    def setCurrentIndex(self, index):
84        if index != self.getCurrentIndex():
85            self.stackWidget.setCurrentIndex(index)
86            self.comboBox.setCurrentIndex(index)
87            self.currentIndexChanged.emit(index)
88
89    pageTitle = pyqtProperty(str, fget=getPageTitle, fset=setPageTitle, stored=False)
90    currentIndex = pyqtProperty(int, fget=getCurrentIndex, fset=setCurrentIndex)
91
92
93#============================================================================#
94# Main for testing the class                                                 #
95#----------------------------------------------------------------------------#
96if __name__ == "__main__":
97    import sys
98    app = QApplication(sys.argv)
99    widget = PyMultiPageWidget()
100    widget.addPage(QLabel('This is page #1'))
101    widget.addPage(QLabel('This is page #2'))
102    widget.show()
103    sys.exit(app.exec_())
104
105#============================================================================#
106# EOF                                                                        #
107#----------------------------------------------------------------------------#
108