Beispiel #1
0
class SearchFindWidget(QWidget, object):

    textChanged = Signal(str)
    editingFinished = Signal(str)
    returnPressed = Signal()

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

        self.setObjectName('SearchFindWidget')

        self.text = ''
        self._placeholder_text = ''

        main_layout = layouts.HorizontalLayout(spacing=2, margins=(2, 2, 2, 2))
        self.setLayout(main_layout)

        self._search_line = search_line or QLineEdit(self)
        self._search_menu = QMenu()
        self._search_menu.addAction('Test')

        icon_size = self.style().pixelMetric(QStyle.PM_SmallIconSize)

        delete_icon = resources.icon('delete')
        search_icon = QIcon(resources.icon('search'))

        self._clear_btn = buttons.IconButton(delete_icon,
                                             icon_padding=2,
                                             parent=self)
        self._clear_btn.setIconSize(QSize(icon_size, icon_size))
        self._clear_btn.setFixedSize(QSize(icon_size, icon_size))
        self._clear_btn.hide()

        self._search_btn = buttons.IconButton(search_icon,
                                              icon_padding=2,
                                              parent=self)
        self._search_btn.setIconSize(QSize(icon_size, icon_size))
        self._search_btn.setFixedSize(QSize(icon_size, icon_size))
        # self._search_btn.setStyleSheet('border: none;')
        # self._search_btn.setPopupMode(QToolButton.InstantPopup)
        self._search_btn.setEnabled(True)

        self._search_line.setStyleSheet("""
            QLineEdit { padding-left: %spx; padding-right: %spx; border-radius:10px; border:2px; border-color:red; }
            """ % (self._search_button_padded_width(),
                   self._clear_button_padded_width()))
        self._search_line.setMinimumSize(
            max(
                self._search_line.minimumSizeHint().width(),
                self._clear_button_padded_width() +
                self._search_button_padded_width()),
            max(
                self._search_line.minimumSizeHint().height(),
                max(self._clear_button_padded_width(),
                    self._search_button_padded_width())))

        main_layout.addWidget(self._search_line)

        self._search_line.setFocus()

        self._search_line.textChanged.connect(self.textChanged)
        self._search_line.textChanged.connect(self.set_text)
        # self._search_line.editingFinished.connect(self.editingFinished)
        # self._search_line.returnPressed.connect(self.returnPressed)
        self._clear_btn.clicked.connect(self.clear)
        self._search_btn.clicked.connect(self._popup_menu)

    @property
    def search_line(self):
        return self._search_line

    def changeEvent(self, event):
        if event.type() == QEvent.EnabledChange:
            enabled = self.isEnabled()
            self._search_btn.setEnabled(enabled and self._search_menu)
            self._search_line.setEnabled(enabled)
            self._clear_btn.setEnabled(enabled)
        super(SearchFindWidget, self).changeEvent(event)

    def resizeEvent(self, event):
        if not (self._clear_btn and self._search_line):
            return
        super(SearchFindWidget, self).resizeEvent(event)
        x = self.width() - self._clear_button_padded_width() * 0.85
        y = (self.height() - self._clear_btn.height()) * 0.5
        self._clear_btn.move(x - 3, y)
        self._search_btn.move(self._search_line_frame_width() * 2,
                              (self.height() - self._search_btn.height()) *
                              0.5)

    def keyPressEvent(self, event):
        if event.key() == Qt.Key_Escape:
            self.clear()
        super(SearchFindWidget, self).keyPressEvent(event)

    def get_text(self):
        if not self._search_line:
            return ''
        return self._search_line.text()

    def set_text(self, text):
        if not (self._clear_btn and self._search_line):
            return

        self._clear_btn.setVisible(not (len(text) == 0))
        if text != self.get_text():
            self._search_line.setText(text)

    def get_placeholder_text(self):
        if not self._search_line:
            return ''

        return self._search_line.text()

    def set_placeholder_text(self, text):
        if not self._search_line:
            return
        self._search_line.setPlaceholderText(text)

    def get_menu(self):
        search_icon = resources.icon('search')
        self._search_btn.setIcon(search_icon)
        self._search_btn.setEnabled(self.isEnabled() and self._menu)

    def set_focus(self, reason=Qt.OtherFocusReason):
        if self._search_line:
            self._search_line.setFocus(reason)
        else:
            self.setFocus(Qt.OtherFocusReason)

    def clear(self):
        if not self._search_line:
            return
        self._search_line.clear()
        self.set_focus()

    def select_all(self):
        if not self._search_line:
            return
        self._search_line.selectAll()

    def _search_line_frame_width(self):
        return self._search_line.style().pixelMetric(
            QStyle.PM_DefaultFrameWidth)

    def _clear_button_padded_width(self):
        return self._clear_btn.width() + self._search_line_frame_width() * 2

    def _clear_button_padded_height(self):
        return self._clear_btn.height() + self._search_line_frame_width() * 2

    def _search_button_padded_width(self):
        return self._search_btn.width() + self._search_line_frame_width() * 2

    def _search_button_padded_height(self):
        return self._search_btn.height() + self._search_line_frame_width() * 2

    def _popup_menu(self):
        if self._search_menu:
            screen_rect = QApplication.desktop().availableGeometry(
                self._search_btn)
            size_hint = self._search_menu.sizeHint()
            rect = self._search_btn.rect()
            top_diff = rect.top() - size_hint.height()
            x = rect.right() - size_hint.width(
            ) if self._search_btn.isRightToLeft() else rect.left()
            y = rect.bottom(
            ) if self._search_btn.mapToGlobal(QPoint(0, rect.bottom())).y(
            ) + size_hint.height() <= screen_rect.height() else top_diff
            point = self._search_btn.mapToGlobal(QPoint(x, y))
            point.setX(
                max(screen_rect.left(),
                    min(point.x(),
                        screen_rect.right() - size_hint.width())))
            point.setY(point.y() + 1)
            print('pop up on {}'.format(point))
            self._search_menu.popup(point)
Beispiel #2
0
class propertiesDialog(QDialog, Ui_propertiesDialog):
    """
    Properties dialog class
    """
    def __init__(self, properties, headers=None, mode='adri'):
        """
        mode a: allow add
        mode d: allow delete
        mode r: allow reorder
        mode i: force name to be valid identifier
        """
        super().__init__()
        self.setupUi(self)
        self.properties = OrderedDict(properties)
        self.mode = mode
        # set to cursor position
        # will place window in current screen, even when cursor at some 'odd location'
        rect = self.geometry()
        rect.moveTo(QCursor.pos())
        self.setGeometry(
            rect
        )  # will place window in current screen, even when at some 'odd location'

        self.propertiesTableView.setStyle(customStyle())
        model = customModel(parent=self.propertiesTableView)
        self.propertiesTableView.setModel(model)

        self.row = -1
        if 'd' in self.mode:
            self.propertiesTableView.customContextMenuRequested.connect(
                self.showContextMenu)
        if 'a' in self.mode:
            self.addProperty.clicked.connect(self.addRow)
        else:
            self.addProperty.hide()
        if 'r' in mode:
            self.propertiesTableView.setDragDropMode(
                QAbstractItemView.InternalMove)

        # push buttons signals
        self.buttonBox.accepted.connect(self.accept)
        self.buttonBox.rejected.connect(self.reject)

        model.populate(self.properties, headers)

    def showContextMenu(self, pos):
        self.row = self.propertiesTableView.indexAt(pos).row()
        self.menu = QMenu(self)
        deleteRowAction = QAction('Delete', self)
        deleteRowAction.triggered.connect(self.deleteRow)
        self.menu.addAction(deleteRowAction)
        # add other required actions
        self.menu.popup(QCursor.pos())

    def deleteRow(self):
        model = self.propertiesTableView.model()
        model.removeRows(self.row, 1)

    def addRow(self):
        model = self.propertiesTableView.model()
        data = [QStandardItem('') for i in range(model.columnCount())]
        for d in data:
            d.setDropEnabled(False)
        model.appendRow(data)

    def accept(self):
        print('OK')
        model = self.propertiesTableView.model()

        new_properties = OrderedDict()

        for row in range(model.rowCount()):
            values = []
            name = model.data(model.index(row, 0))
            for col in range(1, model.columnCount()):
                ix = model.index(row, col)
                widget = self.propertiesTableView.indexWidget(ix)
                if widget:
                    value = widget.value
                else:
                    value = model.data(model.index(row, col))  # string type
                    if name in self.properties:  # restore original type
                        value = type(self.properties[name][col - 1])(value)
                values.append(value)

            name = str(name).strip()
            if 'i' in self.mode:
                if name.isidentifier():  # valid name
                    new_properties[name] = values
            elif name:
                new_properties[name] = values

        self.properties = new_properties
        super().accept()