Exemplo n.º 1
0
class DockTitleBar(QWidget, object):
    def __init__(self, dock_widget, renamable=False):
        super(DockTitleBar, self).__init__(dock_widget)

        self._renamable = renamable

        main_layout = QHBoxLayout()
        main_layout.setContentsMargins(0, 0, 0, 1)
        self.setLayout(main_layout)

        self._buttons_box = QGroupBox('')
        self._buttons_box.setObjectName('Docked')
        self._buttons_layout = QHBoxLayout()
        self._buttons_layout.setSpacing(1)
        self._buttons_layout.setMargin(2)
        self._buttons_box.setLayout(self._buttons_layout)
        main_layout.addWidget(self._buttons_box)

        self._title_label = QLabel(self)
        self._title_label.setStyleSheet('background: transparent')
        self._title_edit = QLineEdit(self)
        self._title_edit.setVisible(False)

        self._button_size = QSize(14, 14)

        self._dock_btn = QToolButton(self)
        self._dock_btn.setIcon(resources.icon('restore_window', theme='color'))
        self._dock_btn.setMaximumSize(self._button_size)
        self._dock_btn.setAutoRaise(True)
        self._close_btn = QToolButton(self)
        self._close_btn.setIcon(resources.icon('close_window', theme='color'))
        self._close_btn.setMaximumSize(self._button_size)
        self._close_btn.setAutoRaise(True)

        self._buttons_layout.addSpacing(2)
        self._buttons_layout.addWidget(self._title_label)
        self._buttons_layout.addWidget(self._title_edit)
        self._buttons_layout.addStretch()
        self._buttons_layout.addSpacing(5)
        self._buttons_layout.addWidget(self._dock_btn)
        self._buttons_layout.addWidget(self._close_btn)

        self._buttons_box.mouseDoubleClickEvent = self.mouseDoubleClickEvent
        self._buttons_box.mousePressEvent = self.mousePressEvent
        self._buttons_box.mouseMoveEvent = self.mouseMoveEvent
        self._buttons_box.mouseReleaseEvent = self.mouseReleaseEvent

        dock_widget.featuresChanged.connect(self._on_dock_features_changed)
        self._title_edit.editingFinished.connect(self._on_finish_edit)
        self._dock_btn.clicked.connect(self._on_dock_btn_clicked)
        self._close_btn.clicked.connect(self._on_close_btn_clicked)

        self._on_dock_features_changed(dock_widget.features())
        self.set_title(dock_widget.windowTitle())
        dock_widget.installEventFilter(self)
        dock_widget.topLevelChanged.connect(self._on_change_floating_style)

    @property
    def renamable(self):
        return self._renamable

    @renamable.setter
    def renamable(self, flag):
        self._renamable = flag

    def eventFilter(self, obj, event):
        if event.type() == QEvent.WindowTitleChange:
            self.set_title(obj.windowTitle())
        return super(DockTitleBar, self).eventFilter(obj, event)

    def mouseMoveEvent(self, event):
        event.ignore()

    def mousePressEvent(self, event):
        event.ignore()

    def mouseReleaseEvent(self, event):
        event.ignore()

    def mouseDoubleClickEvent(self, event):
        if event.pos().x() <= self._title_label.width() and self._renamable:
            self._start_edit()
        else:
            super(DockTitleBar, self).mouseDoubleClickEvent(event)

    def update(self, *args, **kwargs):
        self._on_change_floating_style(self.parent().isFloating())
        super(DockTitleBar, self).update(*args, **kwargs)

    def set_title(self, title):
        self._title_label.setText(title)
        self._title_edit.setText(title)

    def add_button(self, button):
        button.setAutoRaise(True)
        button.setMaximumSize(self._button_size)
        self._buttons_layout.insertWidget(5, button)

    def _start_edit(self):
        self._title_label.hide()
        self._title_edit.show()
        self._title_edit.setFocus()

    def _finish_edit(self):
        self._title_edit.hide()
        self._title_label.show()
        self.parent().setWindowTitle(self._title_edit.text())

    def _on_dock_features_changed(self, features):
        if not features & QDockWidget.DockWidgetVerticalTitleBar:
            self._close_btn.setVisible(features
                                       & QDockWidget.DockWidgetClosable)
            self._dock_btn.setVisible(features
                                      & QDockWidget.DockWidgetFloatable)
        else:
            raise ValueError('Vertical title bar is not supported!')

    def _on_finish_edit(self):
        self._finish_edit()

    def _on_dock_btn_clicked(self):
        self.parent().setFloating(not self.parent().isFloating())

    def _on_close_btn_clicked(self):
        self.parent().toggleViewAction().setChecked(False)
        self.parent().close()

    def _on_change_floating_style(self, state):
        pass
Exemplo n.º 2
0
class Client(QDialog):
    def __init__(self, parent: QWidget = None):
        super().__init__(parent)

        self._in = QDataStream()
        self.blockSize = 0

        self.currentFortune = ""

        self.hostLineEdit = QLineEdit("fortune")
        self.getFortuneButton = QPushButton(self.tr("Get Fortune"))
        self.statusLabel = QLabel(
            self.tr(
                "This examples requires that you run the Local Fortune Server example as well."
            )
        )
        self.socket = QLocalSocket()

        self.setWindowFlags(self.windowFlags() & ~Qt.WindowContextHelpButtonHint)
        hostLabel = QLabel(self.tr("&Server name:"))
        hostLabel.setBuddy(self.hostLineEdit)

        self.statusLabel.setWordWrap(True)

        self.getFortuneButton.setDefault(True)
        quitButton = QPushButton(self.tr("Quit"))

        buttonBox = QDialogButtonBox()
        buttonBox.addButton(self.getFortuneButton, QDialogButtonBox.ActionRole)
        buttonBox.addButton(quitButton, QDialogButtonBox.RejectRole)

        self._in.setDevice(self.socket)
        self._in.setVersion(QDataStream.Qt_5_10)

        self.hostLineEdit.textChanged.connect(self.enableGetFortuneButton)

        self.getFortuneButton.clicked.connect(self.requestNewFortune)
        quitButton.clicked.connect(self.close)
        self.socket.readyRead.connect(self.readFortune)
        self.socket.errorOccurred.connect(self.displayError)

        mainLayout = QGridLayout(self)
        mainLayout.addWidget(hostLabel, 0, 0)
        mainLayout.addWidget(self.hostLineEdit, 0, 1)
        mainLayout.addWidget(self.statusLabel, 2, 0, 1, 2)
        mainLayout.addWidget(buttonBox, 3, 0, 1, 2)

        self.setWindowTitle(QGuiApplication.applicationDisplayName())
        self.hostLineEdit.setFocus()

    @Slot()
    def requestNewFortune(self):
        self.getFortuneButton.setEnabled(False)
        self.blockSize = 0
        self.socket.abort()
        self.socket.connectToServer(self.hostLineEdit.text())

    @Slot()
    def readFortune(self):
        if self.blockSize == 0:
            # Relies on the fact that QDataStream serializes a quint32 into
            # sizeof(quint32) bytes
            if self.socket.bytesAvailable() < 4:  #  (int)sizeof(quint32))
                return
            self.blockSize = self._in.readUInt32()

        if self.socket.bytesAvailable() < self.blockSize or self._in.atEnd():
            return

        nextFortune = ""
        nextFortune = self._in.readQString()

        if nextFortune == self.currentFortune:
            QTimer.singleShot(0, self.requestNewFortune)
            return

        currentFortune = nextFortune
        self.statusLabel.setText(currentFortune)
        self.getFortuneButton.setEnabled(True)

    @Slot(QLocalSocket.LocalSocketError)
    def displayError(self, socketError):
        if socketError == QLocalSocket.ServerNotFoundError:

            QMessageBox.information(
                self,
                self.tr("Local Fortune Client"),
                self.tr(
                    "The host was not found. Please make sure "
                    "that the server is running and that the "
                    "server name is correct."
                ),
            )
        elif socketError == QLocalSocket.ConnectionRefusedError:
            QMessageBox.information(
                self,
                self.tr("Local Fortune Client"),
                self.tr(
                    "The connection was refused by the peer. "
                    "Make sure the fortune server is running, "
                    "and check that the server name is correct."
                ),
            )
        elif socketError == QLocalSocket.PeerClosedError:
            return
        else:
            QMessageBox.information(
                self,
                self.tr("Local Fortune Client"),
                self.tr(
                    "The following error occurred: %s." % (self.socket.errorString())
                ),
            )

        self.getFortuneButton.setEnabled(True)

    @Slot()
    def enableGetFortuneButton(self):
        self.getFortuneButton.setEnabled(bool(self.hostLineEdit.ext()))