コード例 #1
0
class BaseFileFolderDialog(BaseDialog,
                           abstract_dialog.AbstractFileFolderDialog):
    """
    Base dialog classes for folders and files
    """

    def_title = 'Select File'
    def_size = (200, 125)
    def_use_app_browser = False

    def __init__(self, name='BaseFileFolder', parent=None, **kwargs):
        super(BaseFileFolderDialog, self).__init__(name=name, parent=parent)

        self.directory = None
        self.filters = None
        self._use_app_browser = kwargs.pop('use_app_browser',
                                           self.def_use_app_browser)

        self.set_filters('All Files (*.*)')

        # By default, we set the directory to the user folder
        self.set_directory(os.path.expanduser('~'))
        self.center()

    def open_app_browser(self):
        return

    def ui(self):
        super(BaseFileFolderDialog, self).ui()

        from tpDcc.libs.qt.widgets import directory

        self.places = dict()

        self.grid = layouts.GridLayout()
        sub_grid = layouts.GridLayout()
        self.grid.addWidget(QLabel('Path:'), 0, 0, Qt.AlignRight)

        self.path_edit = QLineEdit(self)
        self.path_edit.setReadOnly(True)
        self.filter_box = QComboBox(self)
        self.file_edit = QLineEdit(self)

        self.view = directory.FileListWidget(self)
        self.view.setWrapping(True)
        self.view.setFocusPolicy(Qt.StrongFocus)

        self.open_button = QPushButton('Select', self)
        self.cancel_button = QPushButton('Cancel', self)

        size = QSize(32, 24)
        self.up_button = QPushButton('Up')
        self.up_button.setToolTip('Go up')
        self.up_button.setMinimumSize(size)
        self.up_button.setMaximumSize(size)

        size = QSize(56, 24)
        self.refresh_button = QPushButton('Reload')
        self.refresh_button.setToolTip('Reload file list')
        self.refresh_button.setMinimumSize(size)
        self.refresh_button.setMaximumSize(size)

        self.show_hidden = QCheckBox('Hidden')
        self.show_hidden.setChecked(False)
        self.show_hidden.setToolTip('Toggle show hidden files')

        sub_grid.addWidget(self.up_button, 0, 1)
        sub_grid.addWidget(self.path_edit, 0, 2)
        sub_grid.addWidget(self.refresh_button, 0, 3)
        sub_grid.addWidget(self.show_hidden, 0, 4)
        self.grid.addLayout(sub_grid, 0, 1)
        self.grid.addWidget(self.get_drives_widget(), 1, 0)
        self.grid.addWidget(self.view, 1, 1)
        self.grid.addWidget(QLabel('File name:'), 7, 0, Qt.AlignRight)
        self.grid.addWidget(self.file_edit, 7, 1)
        self.filter_label = QLabel('Filter:')
        self.grid.addWidget(self.filter_label, 8, 0, Qt.AlignRight)
        self.grid.addWidget(self.filter_box, 8, 1)
        hbox = layouts.GridLayout()
        hbox.addWidget(self.open_button, 0, 0, Qt.AlignRight)
        hbox.addWidget(self.cancel_button, 0, 1, Qt.AlignRight)
        self.grid.addLayout(hbox, 9, 1, Qt.AlignRight)
        self.main_layout.addLayout(self.grid)
        self.setGeometry(200, 100, 600, 400)

        self.open_button.clicked.connect(self.accept)
        self.cancel_button.clicked.connect(self.reject)
        self.up_button.clicked.connect(self.go_up)
        self.refresh_button.clicked.connect(self.update_view)
        self.show_hidden.stateChanged.connect(self.update_view)
        self.view.directory_activated.connect(
            self.activate_directory_from_view)
        self.view.file_activated.connect(self.activate_file_from_view)
        self.view.file_selected.connect(self.select_file_item)
        self.view.folder_selected.connect(self.select_folder_item)
        self.view.up_requested.connect(self.go_up)
        self.view.update_requested.connect(self.update_view)

    def exec_(self, *args, **kwargs):
        if self._use_app_browser:
            return self.open_app_browser()
        else:
            self.update_view()
            self.filter_box.currentIndexChanged.connect(self.update_view)
            accepted = super(BaseFileFolderDialog, self).exec_()
            self.filter_box.currentIndexChanged.disconnect(self.update_view)
            return self.get_result() if accepted == 1 else None

    def set_filters(self, filters, selected=0):
        self.filter_box.clear()
        filter_types = filters.split(';;')
        for ft in filter_types:
            extensions = string.extract(ft, '(', ')')
            filter_name = string.rstrips(ft, '({})'.format(extensions))
            extensions = extensions.split(' ')
            self.filter_box.addItem(
                '{} ({})'.format(filter_name, ','.join(extensions)),
                extensions)
        if 0 <= selected < self.filter_box.count():
            self.filter_box.setCurrentIndex(selected)
        self.filters = filters

    def get_drives_widget(self):
        """
        Returns a QGroupBox widget that contains all disk drivers of the PC in a vertical layout
        :return: QGroupBox
        """

        w = QGroupBox('')
        w.setParent(self)
        box = layouts.VerticalLayout()
        box.setAlignment(Qt.AlignTop)
        places = [(getpass.getuser(),
                   os.path.realpath(os.path.expanduser('~')))]
        places += [
            (q, q) for q in
            [os.path.realpath(x.absolutePath()) for x in QDir().drives()]
        ]
        for label, loc in places:
            icon = QFileIconProvider().icon(QFileInfo(loc))
            drive_btn = QRadioButton(label)
            drive_btn.setIcon(icon)
            drive_btn.setToolTip(loc)
            drive_btn.setProperty('path', loc)
            drive_btn.clicked.connect(self.go_to_drive)
            self.places[loc] = drive_btn
            box.addWidget(drive_btn)
        w.setLayout(box)
        return w

    def go_to_drive(self):
        """
        Updates widget to show the content of the selected disk drive
        """

        sender = self.sender()
        self.set_directory(sender.property('path'), False)

    def get_result(self):
        tf = self.file_edit.text()
        sf = self.get_file_path(tf)
        return sf, os.path.dirname(sf), tf.split(os.pathsep)

    def get_filter_patterns(self):
        """
        Get list of filter patterns that are being used by the widget
        :return: list<str>
        """

        idx = self.filter_box.currentIndex()
        if idx >= 0:
            return self.filter_box.itemData(idx)
        else:
            return []

    def get_file_path(self, file_name):
        """
        Returns file path of the given file name taking account the selected directory
        :param file_name: str, name of the file without path
        :return: str
        """

        sname = file_name.split(os.pathsep)[0]
        return os.path.realpath(
            os.path.join(os.path.abspath(self.directory), sname))


#     def accept(self):
#         self._overlay.close()
#         super(BaseFileFolderDialog, self).accept()
#
#
#     def reject(self):
#         self._overlay.close()
#         super(BaseFileFolderDialog, self).reject()

    def update_view(self):
        """
        Updates file/folder view
        :return:
        """

        self.view.clear()
        qdir = QDir(self.directory)
        qdir.setNameFilters(self.get_filter_patterns())
        filters = QDir.Dirs | QDir.AllDirs | QDir.Files | QDir.NoDot | QDir.NoDotDot
        if self.show_hidden.isChecked():
            filters = filters | QDir.Hidden
        entries = qdir.entryInfoList(filters=filters,
                                     sort=QDir.DirsFirst | QDir.Name)
        file_path = self.get_file_path('..')
        if os.path.exists(file_path) and file_path != self.directory:
            icon = QFileIconProvider().icon(QFileInfo(self.directory))
            QListWidgetItem(icon, '..', self.view, 0)
        for info in entries:
            icon = QFileIconProvider().icon(info)
            suf = info.completeSuffix()
            name, tp = (info.fileName(), 0) if info.isDir() else (
                '%s%s' % (info.baseName(), '.%s' % suf if suf else ''), 1)
            QListWidgetItem(icon, name, self.view, tp)
        self.view.setFocus()

    def set_directory(self, path, check_drive=True):
        """
        Sets the directory that you want to explore
        :param path: str, valid path
        :param check_drive: bool,
        :return:
        """

        self.directory = os.path.realpath(path)
        self.path_edit.setText(self.directory)
        self.file_edit.setText('')

        # If necessary, update selected disk driver
        if check_drive:
            for loc in self.places:
                rb = self.places[loc]
                rb.setAutoExclusive(False)
                rb.setChecked(loc.lower() == self.directory.lower())
                rb.setAutoExclusive(True)

        self.update_view()
        self.up_button.setEnabled(not self.cant_go_up())

    def go_up(self):
        """
        Updates the current directory to go to its parent directory
        """

        self.set_directory(os.path.dirname(self.directory))

    def cant_go_up(self):
        """
        Checks whether we can naviage to current selected parent directory or not
        :return: bool
        """

        return os.path.dirname(self.directory) == self.directory

    def activate_directory_from_view(self, name):
        """
        Updates selected directory
        :param name: str, name of the directory
        """

        self.set_directory(os.path.join(self.directory, name))

    def activate_file_from_view(self, name):
        """
        Updates selected file text and returns its info by accepting it
        :param name: str, name of the file
        """

        self.select_file_item(name=name)
        self.accept()

    def select_file_item(self, name):
        """
        Updates selected file text and returns its info by accepting it
        :param name: str, name of the file
        """

        self.file_edit.setText(name)

    def select_folder_item(self, name):
        """
        Updates selected folder text and returns its info by accepting it
        :param name: str, name of the folder
        """

        self.file_edit.setText(name)
コード例 #2
0
class Dialog(QDialog):
    def __init__(self, parent: QWidget = None) -> None:
        super().__init__(parent)

        self.tcpServer = QTcpServer()
        self.tcpClient = QTcpSocket()
        self.tcpServerConnection: QTcpSocket = None

        self.bytesToWrite = 0
        self.bytesWritten = 0
        self.bytesReceived = 0

        self.clientProgressBar = QProgressBar()
        self.clientStatusLabel = QLabel(self.tr("Client ready"))
        self.serverProgressBar = QProgressBar()
        self.serverStatusLabel = QLabel(self.tr("Server ready"))

        self.startButton = QPushButton(self.tr("&Start"))
        self.quitButton = QPushButton(self.tr("&Quit"))

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

        self.startButton.clicked.connect(self.start)
        self.quitButton.clicked.connect(self.close)
        self.tcpServer.newConnection.connect(self.acceptConnection)
        self.tcpClient.connected.connect(self.startTransfer)
        self.tcpClient.bytesWritten.connect(self.updateClientProgress)
        self.tcpClient.error.connect(self.displayError)

        mainLayout = QVBoxLayout(self)
        mainLayout.addWidget(self.clientProgressBar)
        mainLayout.addWidget(self.clientStatusLabel)
        mainLayout.addWidget(self.serverProgressBar)
        mainLayout.addWidget(self.serverStatusLabel)
        mainLayout.addStretch(1)
        mainLayout.addSpacing(10)
        mainLayout.addWidget(self.buttonBox)

    @Slot()
    def start(self):
        self.startButton.setEnabled(False)

        QGuiApplication.setOverrideCursor(Qt.WaitCursor)

        self.bytesWritten = 0
        self.bytesReceived = 0

        while not self.tcpServer.isListening() and not self.tcpServer.listen():
            ret = QMessageBox.critical(
                self,
                self.tr("Loopback"),
                self.tr(
                    "Unable to start the test: %s" % (self.tcpServer.errorString())
                ),
                QMessageBox.Retry | QMessageBox.Cancel,
            )
            if ret == QMessageBox.Cancel:
                return

        self.serverStatusLabel.setText(self.tr("Listening"))
        self.clientStatusLabel.setText(self.tr("Connecting"))
        self.tcpClient.connectToHost(
            QHostAddress.LocalHost, self.tcpServer.serverPort()
        )

    @Slot()
    def acceptConnection(self):
        self.tcpServerConnection = self.tcpServer.nextPendingConnection()
        if not self.tcpServerConnection:
            self.serverStatusLabel.setText(
                self.tr("Error: got invalid pending connection!")
            )
            return

        self.tcpServerConnection.readyRead.connect(self.updateServerProgress)
        self.tcpServerConnection.error.connect(self.displayError)
        self.tcpServerConnection.disconnected.connect(
            self.tcpServerConnection.deleteLater
        )

        self.serverStatusLabel.setText(self.tr("Accepted connection"))
        self.tcpServer.close()

    @Slot()
    def startTransfer(self):
        # called when the TCP client connected to the loopback server
        self.bytesToWrite = TOTAL_BYTES - int(
            self.tcpClient.write(QByteArray(PAYLOAD_SIZE, "@"))
        )
        self.clientStatusLabel.setText(self.tr("Connected"))

    @Slot()
    def updateServerProgress(self):
        self.bytesReceived += int(self.tcpServerConnection.bytesAvailable())
        self.tcpServerConnection.readAll()

        self.serverProgressBar.setMaximum(TOTAL_BYTES)
        self.serverProgressBar.setValue(self.bytesReceived)
        self.serverStatusLabel.setText(
            self.tr("Received %dMB" % (self.bytesReceived / (1024 * 1024),))
        )

        if self.bytesReceived == TOTAL_BYTES:
            self.tcpServerConnection.close()
            self.startButton.setEnabled(True)

            QGuiApplication.restoreOverrideCursor()

    @Slot("qint64")
    def updateClientProgress(self, numBytes):
        self.bytesWritten += int(numBytes)

        if self.bytesToWrite > 0 and self.tcpClient.bytesToWrite() <= 4 * PAYLOAD_SIZE:
            self.bytesToWrite -= self.tcpClient.write(
                QByteArray(min(self.bytesToWrite, PAYLOAD_SIZE), "@")
            )

        self.clientProgressBar.setMaximum(TOTAL_BYTES)
        self.clientProgressBar.setValue(self.bytesWritten)
        self.clientStatusLabel.setText(
            self.tr("Sent %dMB" % (self.bytesWritten / (1024 * 1024),))
        )

    @Slot(QAbstractSocket.SocketError)
    def displayError(self, socketError):
        if socketError == QTcpSocket.RemoteHostClosedError:
            return

        QMessageBox.information(
            self,
            self.tr("Network error"),
            self.tr(
                "The following error occurred: {}.".format(self.tcpClient.errorString())
            ),
        )
        self.tcpClient.close()
        self.tcpServer.close()
        self.clientProgressBar.reset()
        self.serverProgressBar.reset()
        self.clientStatusLabel.setText(self.tr("Client ready"))
        self.serverStatusLabel.setText(self.tr("Server ready"))
        self.startButton.setEnabled(True)
        QGuiApplication.restoreOverrideCursor()
コード例 #3
0
class WindowDragger(QFrame, object):
    """
    Class to create custom window dragger for Solstice Tools
    """

    DEFAULT_LOGO_ICON_SIZE = 22

    doubleClicked = Signal()

    def __init__(self, window=None, on_close=None):
        super(WindowDragger, self).__init__(window)

        self._window = window
        self._dragging_enabled = True
        self._lock_window_operations = False
        self._mouse_press_pos = None
        self._mouse_move_pos = None
        self._dragging_threshold = 5
        self._minimize_enabled = True
        self._maximize_enabled = True
        self._on_close = on_close

        self.setObjectName('titleFrame')

        self.ui()

    # =================================================================================================================
    # PROPERTIES
    # =================================================================================================================

    @property
    def contents_layout(self):
        return self._contents_layout

    @property
    def corner_contents_layout(self):
        return self._corner_contents_layout

    # =================================================================================================================
    # OVERRIDES
    # =================================================================================================================

    def mousePressEvent(self, event):
        if event.button() == Qt.LeftButton and self._dragging_enabled:
            self._mouse_press_pos = event.globalPos()
            self._mouse_move_pos = event.globalPos() - self._window.pos()
        super(WindowDragger, self).mousePressEvent(event)

    def mouseMoveEvent(self, event):
        if event.buttons() & Qt.LeftButton:
            global_pos = event.globalPos()
            if self._mouse_press_pos and self._dragging_enabled:
                moved = global_pos - self._mouse_press_pos
                if moved.manhattanLength() > self._dragging_threshold:
                    diff = global_pos - self._mouse_move_pos
                    self._window.move(diff)
                    self._mouse_move_pos = global_pos - self._window.pos()
        super(WindowDragger, self).mouseMoveEvent(event)

    def mouseDoubleClickEvent(self, event):
        if self._lock_window_operations:
            return
        if self._button_maximized.isVisible():
            self._on_maximize_window()
        else:
            self._on_restore_window()
        super(WindowDragger, self).mouseDoubleClickEvent(event)
        self.doubleClicked.emit()

    def mouseReleaseEvent(self, event):
        if self._mouse_press_pos is not None:
            if event.button() == Qt.LeftButton and self._dragging_enabled:
                moved = event.globalPos() - self._mouse_press_pos
                if moved.manhattanLength() > self._dragging_threshold:
                    event.ignore()
                self._mouse_press_pos = None
        super(WindowDragger, self).mouseReleaseEvent(event)

    # =================================================================================================================
    # BASE
    # =================================================================================================================

    def ui(self):
        self.setFixedHeight(qtutils.dpi_scale(40))

        main_layout = layouts.HorizontalLayout(spacing=5,
                                               margins=(15, 0, 15, 0))
        self.setLayout(main_layout)

        self._logo_button = self._setup_logo_button()
        self._title_text = label.ClippedLabel(text=self._window.windowTitle())
        self._title_text.setObjectName('WindowDraggerLabel')
        self._contents_layout = layouts.HorizontalLayout()
        self._corner_contents_layout = layouts.HorizontalLayout()

        main_layout.addWidget(self._logo_button)
        main_layout.addWidget(self._title_text)
        main_layout.addItem(
            QSpacerItem(25, 0, QSizePolicy.Fixed, QSizePolicy.Fixed))
        main_layout.addLayout(self._contents_layout)
        main_layout.addLayout(self._corner_contents_layout)

        buttons_widget = QWidget()
        self.buttons_layout = layouts.HorizontalLayout(spacing=0,
                                                       margins=(0, 0, 0, 0))
        self.buttons_layout.setAlignment(Qt.AlignRight)
        buttons_widget.setLayout(self.buttons_layout)
        main_layout.addWidget(buttons_widget)

        self._button_minimized = QPushButton()
        self._button_minimized.setIconSize(QSize(25, 25))
        # self._button_minimized.setSizePolicy(QSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed))
        self._button_minimized.setIcon(
            resources.icon('minimize', theme='window'))
        self._button_minimized.setStyleSheet(
            'QWidget {background-color: rgba(255, 255, 255, 0); border:0px;}')
        self._button_maximized = QPushButton()
        self._button_maximized.setIcon(
            resources.icon('maximize', theme='window'))
        # self._button_maximized.setSizePolicy(QSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed))
        self._button_maximized.setStyleSheet(
            'QWidget {background-color: rgba(255, 255, 255, 0); border:0px;}')
        self._button_maximized.setIconSize(QSize(25, 25))
        self._button_restored = QPushButton()
        # self._button_restored.setSizePolicy(QSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed))
        self._button_restored.setVisible(False)
        self._button_restored.setIcon(resources.icon('restore',
                                                     theme='window'))
        self._button_restored.setStyleSheet(
            'QWidget {background-color: rgba(255, 255, 255, 0); border:0px;}')
        self._button_restored.setIconSize(QSize(25, 25))
        self._button_closed = QPushButton()
        # button_closed.setSizePolicy(QSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed))
        self._button_closed.setIcon(resources.icon('close', theme='window'))
        self._button_closed.setStyleSheet(
            'QWidget {background-color: rgba(255, 255, 255, 0); border:0px;}')
        self._button_closed.setIconSize(QSize(25, 25))

        self.buttons_layout.addWidget(self._button_minimized)
        self.buttons_layout.addWidget(self._button_maximized)
        self.buttons_layout.addWidget(self._button_restored)
        self.buttons_layout.addWidget(self._button_closed)

        self._button_maximized.clicked.connect(self._on_maximize_window)
        self._button_minimized.clicked.connect(self._on_minimize_window)
        self._button_restored.clicked.connect(self._on_restore_window)
        self._button_closed.clicked.connect(self._on_close_window)

    def set_icon(self, icon=None, highlight=False):
        """
        Sets the icon of the window dragger
        :param icon: QIcon
        :param highlight: bool
        """

        icon = icon or self._window.windowIcon()
        if not icon or icon.isNull():
            icon = resources.icon('tpDcc')

        size = self.DEFAULT_LOGO_ICON_SIZE

        if highlight:
            self._logo_button.set_icon(
                [icon],
                colors=[None],
                tint_composition=QPainter.CompositionMode_Plus,
                size=size,
                icon_scaling=[1],
                color_offset=0,
                grayscale=True)
        else:
            self._logo_button.set_icon([icon],
                                       colors=None,
                                       size=size,
                                       icon_scaling=[1],
                                       color_offset=0)

        self._logo_button.set_icon_idle(icon)

        # self._lbl_icon.setPixmap(icon.pixmap(icon.actualSize(QSize(24, 24))))

    def set_height(self, value):
        """
        Sets the size of the dragger and updates icon
        :param value: float
        """

        self.setFixedHeight(qtutils.dpi_scale(value))

    def set_title(self, title):
        """
        Sets the title of the window dragger
        :param title: str
        """

        self._title_text.setText(title)

    def set_dragging_enabled(self, flag):
        """
        Sets whether or not drag functionality is enabled
        :param flag: bool
        """

        self._dragging_enabled = flag

    def set_minimize_enabled(self, flag):
        """
        Sets whether dragger shows minimize button or not
        :param flag: bool
        """

        self._minimize_enabled = flag
        self._button_minimized.setVisible(flag)

    def set_maximized_enabled(self, flag):
        """
        Sets whether dragger shows maximize button or not
        :param flag: bool
        """

        self._maximize_enabled = flag
        self._button_maximized.setVisible(flag)

    def show_logo(self):
        """
        Shows window logo
        """

        self._logo_button.setVisible(True)

    def hide_logo(self):
        """
        Hides window logo
        """

        self._logo_button.setVisible(False)

    def set_window_buttons_state(self, state, show_close_button=False):
        """
        Sets the state of the dragger buttons
        :param state: bool
        :param show_close_button: bool
        """

        self._lock_window_operations = not state
        self._button_closed.setEnabled(state or show_close_button)
        self._button_closed.setVisible(state or show_close_button)

        if self._maximize_enabled:
            self._button_maximized.setEnabled(state)
            self._button_maximized.setVisible(state)
        else:
            self._button_maximized.setEnabled(False)
            self._button_maximized.setVisible(False)

        if self._minimize_enabled:
            self._button_minimized.setEnabled(state)
            self._button_minimized.setVisible(state)
        else:
            self._button_minimized.setEnabled(False)
            self._button_minimized.setVisible(False)

        if not state:
            self._button_restored.setEnabled(state)
            self._button_restored.setVisible(state)
        else:
            if self.isMaximized():
                self._button_restored.setEnabled(state)
                self._button_restored.setVisible(state)

    def set_frameless_enabled(self, frameless=False):
        """
        Enables/Disables frameless mode or OS system default
        :param frameless: bool
        """

        from tpDcc.managers import tools

        tool_inst = tools.ToolsManager().get_tool_by_plugin_instance(
            self._window)
        if not tool_inst:
            return

        offset = QPoint()

        if self._window.docked():
            rect = self._window.rect()
            pos = self._window.mapToGlobal(QPoint(-10, -10))
            rect.setWidth(rect.width() + 21)
            self._window.close()
        else:
            rect = self.window().rect()
            pos = self.window().pos()
            offset = QPoint(3, 15)
            self.window().close()

        tool_inst._launch(launch_frameless=frameless)

        new_tool = tool_inst.latest_tool()

        QTimer.singleShot(
            0,
            lambda: new_tool.window().setGeometry(pos.x() + offset.x(),
                                                  pos.y() + offset.y(),
                                                  rect.width(), rect.height()))
        new_tool.framelessChanged.emit(frameless)
        QApplication.processEvents()

        return new_tool

    def _setup_logo_button(self):
        """
        Internal function that setup window dragger button logo
        :return: IconMenuButton
        """

        from tpDcc.libs.qt.widgets import buttons
        logo_button = buttons.IconMenuButton(parent=self)
        logo_button.setIconSize(QSize(24, 24))
        logo_button.setFixedSize(QSize(30, 30))
        self._toggle_frameless = logo_button.addAction(
            'Toggle Frameless Mode',
            connect=self._on_toggle_frameless_mode,
            checkable=True)
        self._toggle_frameless.setChecked(self._window.is_frameless())
        logo_button.set_menu_align(Qt.AlignLeft)

        return logo_button

    def _on_toggle_frameless_mode(self, action):
        """
        Internal callback function that is called when switch frameless mode button is pressed by user
        :param flag: bool
        """

        self.set_frameless_enabled(action.isChecked())

    def _on_maximize_window(self):
        """
        Internal callback function that is called when the user clicks on maximize button
        """

        self._button_restored.setVisible(True)
        self._button_maximized.setVisible(False)
        self._window.setWindowState(Qt.WindowMaximized)

    def _on_minimize_window(self):
        """
        Internal callback function that is called when the user clicks on minimize button
        """

        self._window.setWindowState(Qt.WindowMinimized)

    def _on_restore_window(self):
        """
        Internal callback function that is called when the user clicks on restore button
        """

        self._button_restored.setVisible(False)
        self._button_maximized.setVisible(True)
        self._window.setWindowState(Qt.WindowNoState)

    def _on_close_window(self):
        """
        Internal callback function that is called when the user clicks on close button
        """

        from tpDcc.managers import tools

        closed = False
        if hasattr(self._window, 'WindowId'):
            closed = tools.ToolsManager().close_tool(self._window.WindowId,
                                                     force=False)

        if not closed:
            if hasattr(self._window, 'docked'):
                if self._window.docked():
                    self._window.fade_close()
                else:
                    self.window().fade_close()
            else:
                self._window.fade_close()
コード例 #4
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()))
コード例 #5
0
class InformationWindow(QDialog):
    imageChanged = Signal(int, str)

    def __init__(self, id_, items, parent=None):
        super().__init__(parent)

        itemLabel = QLabel(self.tr("Item: "))
        descriptionLabel = QLabel(self.tr("Description: "))
        imageFileLabel = QLabel(self.tr("Image file: "))

        self.createButtons()

        self.itemText = QLabel()
        self.descriptionEditor = QTextEdit()

        self.imageFileEditor = QComboBox()
        self.imageFileEditor.setModel(items.relationModel(1))
        self.imageFileEditor.setModelColumn(
            items.relationModel(1).fieldIndex("file"))

        self.mapper = QDataWidgetMapper(self)
        self.mapper.setModel(items)
        self.mapper.setSubmitPolicy(QDataWidgetMapper.ManualSubmit)
        self.mapper.setItemDelegate(QSqlRelationalDelegate(self.mapper))
        self.mapper.addMapping(self.imageFileEditor, 1)
        self.mapper.addMapping(self.itemText, 2, b"text")
        self.mapper.addMapping(self.descriptionEditor, 3)
        self.mapper.setCurrentIndex(id_)

        self.descriptionEditor.textChanged.connect(self.enableButtons)
        self.imageFileEditor.currentIndexChanged.connect(self.enableButtons)

        formLayout = QFormLayout()
        formLayout.addRow(itemLabel, self.itemText)
        formLayout.addRow(imageFileLabel, self.imageFileEditor)
        formLayout.addRow(descriptionLabel, self.descriptionEditor)

        layout = QVBoxLayout()
        layout.addLayout(formLayout)
        layout.addWidget(self.buttonBox)
        self.setLayout(layout)

        self.itemId = id_
        self.displayedImage = self.imageFileEditor.currentText()

        self.setWindowFlags(Qt.Window)
        self.enableButtons(False)
        self.setWindowTitle(self.itemText.text())

    def id(self):
        return self.itemId

    @Slot()
    def revert(self):
        self.mapper.revert()
        self.enableButtons(False)

    @Slot()
    def submit(self):
        newImage = self.imageFileEditor.currentText()

        if self.displayedImage != newImage:
            self.displayedImage = newImage
            self.imageChanged.emit(self.itemId, newImage)

        self.mapper.submit()
        self.mapper.setCurrentIndex(self.itemId)

        self.enableButtons(False)

    def createButtons(self):

        self.closeButton = QPushButton(self.tr("&Close"))
        self.revertButton = QPushButton(self.tr("&Revert"))
        self.submitButton = QPushButton(self.tr("&Submit"))

        self.closeButton.setDefault(True)

        self.closeButton.clicked.connect(self.close)
        self.revertButton.clicked.connect(self.revert)
        self.submitButton.clicked.connect(self.submit)

        self.buttonBox = QDialogButtonBox(self)
        self.buttonBox.addButton(self.submitButton,
                                 QDialogButtonBox.AcceptRole)
        self.buttonBox.addButton(self.revertButton, QDialogButtonBox.ResetRole)
        self.buttonBox.addButton(self.closeButton, QDialogButtonBox.RejectRole)

    @Slot()
    @Slot(bool)
    def enableButtons(self, enable=True):
        self.revertButton.setEnabled(enable)
        self.submitButton.setEnabled(enable)
コード例 #6
0
ファイル: precision_rotate.py プロジェクト: QChASM/SEQCROW
class PrecisionRotate(ToolInstance):

    help = "https://github.com/QChASM/SEQCROW/wiki/Rotate-Tool"
    SESSION_ENDURING = False
    SESSION_SAVE = False

    def __init__(self, session, name):
        super().__init__(session, name)

        self.tool_window = MainToolWindow(self)

        self.settings = _PrecisionRotateSettings(session, name)

        self.bonds = {}
        self.bond_centers = {}
        self.groups = {}
        self.perpendiculars = {}
        self.perp_centers = {}
        self.manual_center = {}

        self._build_ui()

        self._show_rot_vec = self.session.triggers.add_handler(
            SELECTION_CHANGED, self.show_rot_vec)
        global_triggers = get_triggers()
        self._changes = global_triggers.add_handler("changes done",
                                                    self.show_rot_vec)

        self.show_rot_vec()

    def _build_ui(self):
        layout = QGridLayout()

        layout.addWidget(QLabel("center of rotation:"), 0, 0, 1, 1,
                         Qt.AlignLeft | Qt.AlignVCenter)

        self.cor_button = QComboBox()
        self.cor_button.addItems(
            ["automatic", "select atoms", "view's center of rotation"])
        layout.addWidget(self.cor_button, 0, 1, 1, 1, Qt.AlignTop)

        self.set_cor_selection = QPushButton("set selection")
        self.cor_button.currentTextChanged.connect(
            lambda t, widget=self.set_cor_selection: widget.setEnabled(
                t == "select atoms"))
        self.set_cor_selection.clicked.connect(self.manual_cor)
        layout.addWidget(self.set_cor_selection, 0, 2, 1, 1, Qt.AlignTop)
        self.set_cor_selection.setEnabled(False)

        layout.addWidget(QLabel("rotation vector:"), 1, 0, 1, 1,
                         Qt.AlignLeft | Qt.AlignVCenter)

        self.vector_option = QComboBox()
        self.vector_option.addItems([
            "axis", "view axis", "bond", "perpendicular to plane",
            "centroid of atoms", "custom"
        ])
        layout.addWidget(self.vector_option, 1, 1, 1, 1, Qt.AlignVCenter)

        vector = QWidget()
        vector.setToolTip("vector will be normalized before rotating")
        vector_layout = QHBoxLayout(vector)
        vector_layout.setContentsMargins(0, 0, 0, 0)
        self.vector_x = QDoubleSpinBox()
        self.vector_y = QDoubleSpinBox()
        self.vector_z = QDoubleSpinBox()
        self.vector_z.setValue(1.0)
        for c, t in zip([self.vector_x, self.vector_y, self.vector_z],
                        [" x", " y", " z"]):
            c.setSingleStep(0.01)
            c.setRange(-100, 100)
            # c.setSuffix(t)
            c.valueChanged.connect(self.show_rot_vec)
            vector_layout.addWidget(c)

        layout.addWidget(vector, 1, 2, 1, 1, Qt.AlignTop)
        vector.setVisible(self.vector_option.currentText() == "custom")
        self.vector_option.currentTextChanged.connect(
            lambda text, widget=vector: widget.setVisible(text == "custom"))

        self.view_axis = QComboBox()
        self.view_axis.addItems(["z", "y", "x"])
        layout.addWidget(self.view_axis, 1, 2, 1, 1, Qt.AlignTop)
        self.view_axis.setVisible(
            self.vector_option.currentText() == "view axis")
        self.vector_option.currentTextChanged.connect(
            lambda text, widget=self.view_axis: widget.setVisible(text ==
                                                                  "view axis"))

        self.axis = QComboBox()
        self.axis.addItems(["z", "y", "x"])
        layout.addWidget(self.axis, 1, 2, 1, 1, Qt.AlignTop)
        self.axis.setVisible(self.vector_option.currentText() == "axis")
        self.vector_option.currentTextChanged.connect(
            lambda text, widget=self.axis: widget.setVisible(text == "axis"))

        self.bond_button = QPushButton("set selected bond")
        self.bond_button.clicked.connect(self.set_bonds)
        layout.addWidget(self.bond_button, 1, 2, 1, 1, Qt.AlignTop)
        self.bond_button.setVisible(self.vector_option.currentText() == "bond")
        self.vector_option.currentTextChanged.connect(
            lambda text, widget=self.bond_button: widget.setVisible(text ==
                                                                    "bond"))

        self.perp_button = QPushButton("set selected atoms")
        self.perp_button.clicked.connect(self.set_perpendicular)
        layout.addWidget(self.perp_button, 1, 2, 1, 1, Qt.AlignTop)
        self.perp_button.setVisible(
            self.vector_option.currentText() == "perpendicular to plane")
        self.vector_option.currentTextChanged.connect(
            lambda text, widget=self.perp_button: widget.setVisible(
                text == "perpendicular to plane"))

        self.group_button = QPushButton("set selected atoms")
        self.group_button.clicked.connect(self.set_group)
        layout.addWidget(self.group_button, 1, 2, 1, 1, Qt.AlignTop)
        self.group_button.setVisible(
            self.vector_option.currentText() == "centroid of atoms")
        self.vector_option.currentTextChanged.connect(
            lambda text, widget=self.group_button: widget.setVisible(
                text == "centroid of atoms"))

        layout.addWidget(QLabel("angle:"), 2, 0, 1, 1,
                         Qt.AlignLeft | Qt.AlignVCenter)

        self.angle = QDoubleSpinBox()
        self.angle.setRange(-360, 360)
        self.angle.setSingleStep(5)
        self.angle.setSuffix("°")
        layout.addWidget(self.angle, 2, 1, 1, 1,
                         Qt.AlignLeft | Qt.AlignVCenter)

        layout.addWidget(QLabel("preview rotation axis:"), 3, 0, 1, 1,
                         Qt.AlignLeft | Qt.AlignVCenter)
        self.display_rot_vec = QCheckBox()
        self.display_rot_vec.setCheckState(Qt.Checked)
        self.display_rot_vec.stateChanged.connect(self.show_rot_vec)
        layout.addWidget(self.display_rot_vec, 3, 1, 1, 1,
                         Qt.AlignLeft | Qt.AlignVCenter)

        rotate_button = QPushButton("rotate selected atoms")
        rotate_button.clicked.connect(self.do_rotate)
        layout.addWidget(rotate_button, 4, 0, 1, 3, Qt.AlignTop)
        self.rotate_button = rotate_button

        self.status_bar = QStatusBar()
        self.status_bar.setSizeGripEnabled(False)
        layout.addWidget(self.status_bar, 5, 0, 1, 3, Qt.AlignTop)

        self.vector_option.currentTextChanged.connect(self.show_auto_status)
        self.cor_button.currentIndexChanged.connect(
            lambda *args: self.show_auto_status("select atoms"))

        self.cor_button.currentIndexChanged.connect(self.show_rot_vec)
        self.set_cor_selection.clicked.connect(self.show_rot_vec)
        self.vector_option.currentIndexChanged.connect(self.show_rot_vec)
        self.axis.currentIndexChanged.connect(self.show_rot_vec)
        self.view_axis.currentIndexChanged.connect(self.show_rot_vec)
        self.bond_button.clicked.connect(self.show_rot_vec)
        self.perp_button.clicked.connect(self.show_rot_vec)
        self.group_button.clicked.connect(self.show_rot_vec)

        layout.setRowStretch(0, 0)
        layout.setRowStretch(1, 0)
        layout.setRowStretch(2, 0)
        layout.setRowStretch(3, 0)
        layout.setRowStretch(4, 0)
        layout.setRowStretch(5, 1)

        layout.setColumnStretch(0, 0)
        layout.setColumnStretch(1, 1)
        layout.setColumnStretch(2, 1)

        self.tool_window.ui_area.setLayout(layout)

        self.tool_window.manage(None)

    def manual_cor(self, *args):
        selection = selected_atoms(self.session)

        models = {}
        for atom in selection:
            if atom.structure not in models:
                models[atom.structure] = [atom]
            else:
                models[atom.structure].append(atom)

        self.manual_center = {}
        for model in models:
            atoms = models[model]
            coords = np.array([atom.coord for atom in atoms])
            self.manual_center[model] = np.mean(coords, axis=0)

    def show_auto_status(self, text):
        if self.cor_button.currentText() == "automatic":
            if text == "bond":
                self.status_bar.showMessage(
                    "center set to one of the bonded atoms")
            elif text == "perpendicular to plane":
                self.status_bar.showMessage("center set to centroid of atoms")
            else:
                self.status_bar.showMessage(
                    "center set to centroid of rotating atoms")

        elif self.cor_button.currentText() == "select atoms":
            self.status_bar.showMessage(
                "center set to centroid of specified atoms")

        else:
            self.status_bar.showMessage(
                "center set to view's center of rotation")

    def set_bonds(self, *args):
        bonds = selected_bonds(self.session)
        if len(bonds) == 0:
            self.session.logger.error("no bonds selected")
            return

        models = [bond.structure for bond in bonds]
        if any(models.count(m) > 1 for m in models):
            self.session.logger.error(
                "multiple bonds selected on the same structure")
            return

        self.bonds = {
            model: (bond.atoms[0].coord - bond.atoms[1].coord)
            for model, bond in zip(models, bonds)
        }
        self.bond_centers = {
            model: bond.atoms[1].coord
            for model, bond in zip(models, bonds)
        }

    def set_perpendicular(self, *args):
        atoms = selected_atoms(self.session)
        if len(atoms) == 0:
            self.session.logger.error("no atoms selected")
            return

        self.perpendiculars = {}
        self.perp_centers = {}

        models = set(atom.structure for atom in atoms)
        for model in models:
            atom_coords = []
            for atom in atoms:
                if atom.structure is model:
                    atom_coords.append(atom.coord)

            if len(atom_coords) < 3:
                self.session.logger.error("fewer than 3 atoms selected on %s" %
                                          model.atomspec)
                continue

            xyz = np.array(atom_coords)
            xyz -= np.mean(atom_coords, axis=0)
            R = np.dot(xyz.T, xyz)
            u, s, vh = np.linalg.svd(R, compute_uv=True)
            vector = u[:, -1]

            self.perpendiculars[model] = vector
            self.perp_centers[model] = np.mean(atom_coords, axis=0)

    def set_group(self, *args):
        atoms = selected_atoms(self.session)
        if len(atoms) == 0:
            self.session.logger.error("no atoms selected")
            return

        self.groups = {}

        models = set(atom.structure for atom in atoms)
        for model in models:
            atom_coords = []
            for atom in atoms:
                if atom.structure is model:
                    atom_coords.append(atom.coord)

            self.groups[model] = np.mean(atom_coords, axis=0)

    def do_rotate(self, *args):
        selection = selected_atoms(self.session)

        models = {}
        for atom in selection:
            if atom.structure not in models:
                models[atom.structure] = [atom]
            else:
                models[atom.structure].append(atom)

        if len(models.keys()) == 0:
            return

        if self.vector_option.currentText() == "axis":
            if self.axis.currentText() == "z":
                vector = np.array([0., 0., 1.])
            elif self.axis.currentText() == "y":
                vector = np.array([0., 1., 0.])
            elif self.axis.currentText() == "x":
                vector = np.array([1., 0., 0.])

        elif self.vector_option.currentText() == "view axis":
            if self.view_axis.currentText() == "z":
                vector = self.session.view.camera.get_position().axes()[2]
            elif self.view_axis.currentText() == "y":
                vector = self.session.view.camera.get_position().axes()[1]
            elif self.view_axis.currentText() == "x":
                vector = self.session.view.camera.get_position().axes()[0]

        elif self.vector_option.currentText() == "bond":
            vector = self.bonds

        elif self.vector_option.currentText() == "perpendicular to plane":
            vector = self.perpendiculars

        elif self.vector_option.currentText() == "centroid of atoms":
            vector = self.groups

        elif self.vector_option.currentText() == "custom":
            x = self.vector_x.value()
            y = self.vector_y.value()
            z = self.vector_z.value()
            vector = np.array([x, y, z])

        angle = np.deg2rad(self.angle.value())

        center = {}
        for model in models:
            atoms = models[model]
            coords = np.array([atom.coord for atom in atoms])
            center[model] = np.mean(coords, axis=0)

        if self.cor_button.currentText() == "automatic":
            if self.vector_option.currentText() == "perpendicular to plane":
                center = self.perp_centers

            elif self.vector_option.currentText() == "bond":
                center = self.bond_centers

        elif self.cor_button.currentText() == "select atoms":
            center = self.manual_center

        else:
            center = self.session.main_view.center_of_rotation

        for model in models:
            if isinstance(vector, dict):
                if model not in vector.keys():
                    continue
                else:
                    v = vector[model]

            else:
                v = vector

            if isinstance(center, dict):
                if model not in center.keys():
                    continue
                else:
                    c = center[model]

            else:
                c = center

            if self.vector_option.currentText(
            ) == "centroid of atoms" and self.cor_button.currentText(
            ) != "automatic":
                v = v - c

            v = v / np.linalg.norm(v)
            q = np.hstack(([np.cos(angle / 2)], v * np.sin(angle / 2)))

            q /= np.linalg.norm(q)
            qs = q[0]
            qv = q[1:]

            xyz = np.array([a.coord for a in models[model]])
            xyz -= c
            xprod = np.cross(qv, xyz)
            qs_xprod = 2 * qs * xprod
            qv_xprod = 2 * np.cross(qv, xprod)

            xyz += qs_xprod + qv_xprod + c
            for t, coord in zip(models[model], xyz):
                t.coord = coord

    def show_rot_vec(self, *args):
        for model in self.session.models.list(type=Generic3DModel):
            if model.name == "rotation vector":
                model.delete()

        if self.display_rot_vec.checkState() == Qt.Unchecked:
            return

        selection = selected_atoms(self.session)

        if len(selection) == 0:
            return

        models = {}
        for atom in selection:
            if atom.structure not in models:
                models[atom.structure] = [atom]
            else:
                models[atom.structure].append(atom)

        if len(models.keys()) == 0:
            return

        if self.vector_option.currentText() == "axis":
            if self.axis.currentText() == "z":
                vector = np.array([0., 0., 1.])
            elif self.axis.currentText() == "y":
                vector = np.array([0., 1., 0.])
            elif self.axis.currentText() == "x":
                vector = np.array([1., 0., 0.])

        elif self.vector_option.currentText() == "view axis":
            if self.view_axis.currentText() == "z":
                vector = self.session.view.camera.get_position().axes()[2]
            elif self.view_axis.currentText() == "y":
                vector = self.session.view.camera.get_position().axes()[1]
            elif self.view_axis.currentText() == "x":
                vector = self.session.view.camera.get_position().axes()[0]

        elif self.vector_option.currentText() == "bond":
            vector = self.bonds

        elif self.vector_option.currentText() == "perpendicular to plane":
            vector = self.perpendiculars

        elif self.vector_option.currentText() == "centroid of atoms":
            vector = self.groups

        elif self.vector_option.currentText() == "custom":
            x = self.vector_x.value()
            y = self.vector_y.value()
            z = self.vector_z.value()
            vector = np.array([x, y, z])

        center = {}
        for model in models:
            atoms = models[model]
            coords = np.array([atom.coord for atom in atoms])
            center[model] = np.mean(coords, axis=0)

        if self.cor_button.currentText() == "automatic":
            if self.vector_option.currentText() == "perpendicular to plane":
                center = self.perp_centers

            elif self.vector_option.currentText() == "bond":
                center = self.bond_centers

        elif self.cor_button.currentText() == "select atoms":
            center = self.manual_center

        else:
            center = self.session.main_view.center_of_rotation

        for model in models:
            if isinstance(vector, dict):
                if model not in vector.keys():
                    continue
                else:
                    v = vector[model]

            else:
                v = vector

            if isinstance(center, dict):
                if model not in center.keys():
                    continue
                else:
                    c = center[model]

            else:
                c = center

            if self.vector_option.currentText(
            ) == "centroid of atoms" and self.cor_button.currentText(
            ) != "automatic":
                v = v - c

            if np.linalg.norm(v) == 0:
                continue

            residues = []
            for atom in models[model]:
                if atom.residue not in residues:
                    residues.append(atom.residue)

            v_c = c + v

            s = ".color red\n"
            s += ".arrow %10.6f %10.6f %10.6f   %10.6f %10.6f %10.6f   0.2 0.4 0.7\n" % (
                *c, *v_c)

            stream = BytesIO(bytes(s, 'utf-8'))
            bild_obj, status = read_bild(self.session, stream,
                                         "rotation vector")

            self.session.models.add(bild_obj, parent=model)

    def delete(self):
        self.session.triggers.remove_handler(self._show_rot_vec)
        global_triggers = get_triggers()
        global_triggers.remove_handler(self._changes)

        for model in self.session.models.list(type=Generic3DModel):
            if model.name == "rotation vector":
                model.delete()

        return super().delete()

    def close(self):
        self.session.triggers.remove_handler(self._show_rot_vec)
        global_triggers = get_triggers()
        global_triggers.remove_handler(self._changes)

        for model in self.session.models.list(type=Generic3DModel):
            if model.name == "rotation vector":
                model.delete()

        return super().close()
コード例 #7
0
class PenSetWidget(QWidget):

    penSizeTrigger = Signal(int)
    penColorTrigger = Signal(str)
    fontChangeTrigger = Signal(QFont)

    def __init__(self, parent=None):
        super(PenSetWidget, self).__init__(parent)

        self.paddingX = 5
        self.paddingY = 2
        self.iconWidth = self.iconHeight = 24
        self.setSizePolicy(QSizePolicy.Preferred, QSizePolicy.Fixed)
        self.setWindowFlags(Qt.ToolTip)

        self.initWindows()

        self.prevSizeButton = self.penSize1
        self.penSize1.setChecked(True)
        self.presentColor.setStyleSheet(
            'QPushButton { background-color: %s; }' % PENCOLOR)

    def generateButtons(self, parent=None):
        """ Generate buttons due to colorDic """
        self.colorButtons = []
        for color in self.colorList:
            button = QPushButton(parent)
            button.setObjectName(color[0])
            button.setStyleSheet('QPushButton { background-color: %s; }' %
                                 color[1])
            button.setFixedSize(self.iconWidth / 2, self.iconHeight / 2)
            button.setCheckable(True)
            self.colorButtons.append(button)

    def initWindows(self):
        self.mainLayout = QHBoxLayout()
        self.setLayout(self.mainLayout)
        self.mainLayout.setSpacing(0)
        self.mainLayout.setContentsMargins(5, 2, 5, 2)

        self.initPenSizeButtons()
        self.initFontWidget()
        self.initPenColorButtons()

        self.separator = QFrame(self)
        self.separator.setFrameShape(QFrame.VLine)
        self.separator.setFrameShadow(QFrame.Sunken)

        self.mainLayout.addWidget(self.penSize)
        self.mainLayout.addWidget(self.changeFontButton)
        self.mainLayout.addWidget(self.separator)

        self.mainLayout.addWidget(self.colorSet)

    def initPenSizeButtons(self):
        self.penSize = QWidget(self)
        self.penSizeLayout = QHBoxLayout()
        self.penSize.setLayout(self.penSizeLayout)
        # adjust pen size
        self.penSize1 = QPushButton(self.penSize)
        self.penSize1.setIcon(QIcon(":/resource/icon/pensize1.png"))
        self.penSize1.setObjectName('1')
        self.penSize1.setFixedSize(self.iconWidth, self.iconHeight)
        self.penSize1.setCheckable(True)

        self.penSize2 = QPushButton(self.penSize)
        self.penSize2.setIcon(QIcon(":/resource/icon/pensize2.png"))
        self.penSize2.setObjectName('2')
        self.penSize2.setFixedSize(self.iconWidth, self.iconHeight)
        self.penSize2.setCheckable(True)

        self.penSize3 = QPushButton(self.penSize)
        self.penSize3.setIcon(QIcon(":/resource/icon/pensize3.png"))
        self.penSize3.setObjectName('3')
        self.penSize3.setFixedSize(self.iconWidth, self.iconHeight)
        self.penSize3.setCheckable(True)

        self.sizeButtonGroup = QButtonGroup(self.penSize)
        self.sizeButtonGroup.addButton(self.penSize1)
        self.sizeButtonGroup.addButton(self.penSize2)
        self.sizeButtonGroup.addButton(self.penSize3)
        self.sizeButtonGroup.buttonClicked.connect(self.sizeButtonToggled)

        self.penSizeLayout.addWidget(self.penSize1)
        self.penSizeLayout.addWidget(self.penSize2)
        self.penSizeLayout.addWidget(self.penSize3)

        self.penSizeLayout.setSpacing(5)
        self.penSizeLayout.setContentsMargins(0, 0, 0, 0)

    def initPenColorButtons(self):
        self.colorSet = QWidget(self)
        self.colorLayout = QHBoxLayout()
        self.colorLayout.setSpacing(5)
        self.colorLayout.setContentsMargins(5, 0, 5, 0)
        self.colorSet.setLayout(self.colorLayout)

        self.presentColor = QPushButton(self.colorSet)
        self.presentColor.setFixedSize(self.iconWidth, self.iconHeight)
        self.presentColor.setEnabled(False)

        # adjust pen color

        self.colorPick = QWidget(self.colorSet)
        self.colorGrid = QGridLayout()
        self.colorGrid.setSpacing(0)
        self.colorGrid.setContentsMargins(5, 0, 5, 0)
        self.colorPick.setLayout(self.colorGrid)

        self.colorList = [('white', '#ffffff'), ('red', '#ff0000'),
                          ('green', '#00ff00'), ('blue', '#0000ff'),
                          ('cyan', '#00ffff'), ('magenta', '#ff00ff'),
                          ('yellow', '#ffff00'), ('gray', '#a0a0a4'),
                          ('black', '#000000'), ('darkRed', '#800000'),
                          ('darkGreen', '#008000'), ('darkBlue', '#000080'),
                          ('darkCyan', '#008080'), ('darkMagenta', '#800080'),
                          ('darkYellow', '#808000'), ('darkGray', '#808080')]

        self.generateButtons()

        self.colorButtonGroup = QButtonGroup(self)
        for button in self.colorButtons:
            self.colorButtonGroup.addButton(button)
        self.colorButtonGroup.buttonClicked.connect(self.colorButtonToggled)

        # set the layout
        tmp = 0
        for x in range(0, 2):
            for y in range(0, int(len(self.colorList) / 2)):
                self.colorGrid.addWidget(self.colorButtons[tmp], x, y)
                tmp += 1

        self.colorGrid.setSpacing(0)
        self.colorGrid.setContentsMargins(0, 0, 0, 0)

        self.colorLayout.addWidget(self.presentColor)
        self.colorLayout.addWidget(self.colorPick)

    def initFontWidget(self):
        self.fontDialog = QFontDialog()
        self.changeFontButton = QPushButton(self)
        self.fontDialog.setCurrentFont(QFont('Sans serif'))
        self.changeFontButton.setText('{0} {1}'.format(
            self.fontDialog.currentFont().family(),
            self.fontDialog.currentFont().pointSize()))
        self.changeFontButton.clicked.connect(self.fontButtonClicked)

    def showFontWidget(self):
        self.changeFontButton.show()
        self.penSize1.hide()
        self.penSize2.hide()
        self.penSize3.hide()

    def showPenWidget(self):
        self.changeFontButton.hide()
        self.penSize1.show()
        self.penSize2.show()
        self.penSize3.show()

    # slots
    def colorButtonToggled(self, button):
        self.presentColor.setStyleSheet(
            'QPushButton { background-color: %s; }' % button.objectName())
        self.penColorTrigger.emit(button.objectName())

    def sizeButtonToggled(self, button):
        self.penSizeTrigger.emit(int(button.objectName()) * 2)

    def fontButtonClicked(self):
        ok = True
        font = QFontDialog.getFont(self)
        if font[1]:
            self.changeFontButton.setText('{0} {1}'.format(
                font[0].family(), font[0].pointSize()))
            self.fontChangeTrigger.emit(font[0])