Ejemplo n.º 1
0
    def setZoom(self, zoom):
        '''Set a new zoom level.
        Args:
            zoom (int): The new zoom level.
        '''
        self._zoom = zoom
        zoomSelector = clip(zoom, self._minZoomScale, self._maxZoomScale)
        meters = self._scaleView[zoomSelector]
        if meters >= 1000:
            self._text = '%d km' % (meters / 1000.0)
        else:
            self._text = '%d m' % meters
        self._meters = meters
        self._meterPerPixelsEquator = self.EarthCircumference / np.power(2.0, zoom + 8)

        # Evaluate the bounding box of the current text
        anchor = self._anchor
        textRect = QFontMetrics(QFont()).boundingRect(self._text)
        if anchor == Qt.BottomRightCorner or anchor == Qt.TopRightCorner:
            textRect.moveLeft(-textRect.width() - 10)
            textRect.moveTop(-textRect.height() + 10)
        else:
            textRect.moveTop(-textRect.height() + 14)
        self._textRect = QRectF(textRect)
        self.update()
Ejemplo n.º 2
0
    def setZoom(self, zoom):
        '''Set a new zoom level.
        Args:
            zoom (int): The new zoom level.
        '''
        self._zoom = zoom
        zoomSelector = clip(zoom, self._minZoomScale, self._maxZoomScale)
        meters = self._scaleView[zoomSelector]
        if meters >= 1000:
            self._text = '%d km' % (meters / 1000.0)
        else:
            self._text = '%d m' % meters
        self._meters = meters
        self._meterPerPixelsEquator = self.EarthCircumference / np.power(
            2.0, zoom + 8)

        # Evaluate the bounding box of the current text
        anchor = self._anchor
        textRect = QFontMetrics(QFont()).boundingRect(self._text)
        if anchor == Qt.BottomRightCorner or anchor == Qt.TopRightCorner:
            textRect.moveLeft(-textRect.width() - 10)
            textRect.moveTop(-textRect.height() + 10)
        else:
            textRect.moveTop(-textRect.height() + 14)
        self._textRect = QRectF(textRect)
        self.update()
Ejemplo n.º 3
0
 def sizeHint(self):
     """Override Qt method.
     Returns the widget size hint (based on the editor font size).
     """
     fm = QFontMetrics(self.editor.font())
     size_hint = QSize(fm.height(), fm.height())
     if size_hint.width() > 16:
         size_hint.setWidth(16)
     return size_hint
Ejemplo n.º 4
0
    def sizeHint(self):
        """Override Qt method.

        Returns the widget size hint (based on the editor font size).
        """
        fm = QFontMetrics(self.editor.font())
        size_hint = QSize(fm.height(), fm.height())
        if size_hint.width() > 16:
            size_hint.setWidth(16)
        return size_hint
Ejemplo n.º 5
0
def _resize_widgets(build_popup, visible):

    output = build_popup.textBrowser_output
    cmd = build_popup.lineEdit_cmd

    font = QFont('Monospace' if visible else '')
    font.setStyleHint(QFont.TypeWriter)

    metrics = QFontMetrics(font)
    output.setFont(font)
    mw = build_popup.min_width = metrics.width(' ' * 80)
    output.setMinimumSize(QSize(mw,
                                20*metrics.height()))
    cmd.setMinimumSize(QSize(metrics.width(' ' * 40),
                             metrics.height()))
Ejemplo n.º 6
0
 def set(self, U=None, vmin=None, vmax=None):
     # normalize U
     fm = QFontMetrics(self.font())
     self.vmin = vmin if vmin is not None else (
         np.min(U) if U is not None else 0.)
     self.vmax = vmax if vmax is not None else (
         np.max(U) if U is not None else 1.)
     difference = abs(self.vmin - self.vmax)
     if difference == 0:
         precision = 3
     else:
         precision = m.log(
             max(abs(self.vmin), abs(self.vmax)) / difference, 10) + 1
         precision = int(min(max(precision, 3), 8))
     self.vmin_str = format(
         ('{:.' + str(precision) + '}').format(self.vmin))
     self.vmax_str = format(
         ('{:.' + str(precision) + '}').format(self.vmax))
     self.vmin_width = fm.width(self.vmin_str)
     self.vmax_width = fm.width(self.vmax_str)
     self.text_height = fm.height() * 1.5
     self.text_ascent = fm.ascent() * 1.5
     self.text_descent = fm.descent() * 1.5
     self.setMinimumSize(
         max(self.vmin_width, self.vmax_width) + 20, 300)
     self.update()
Ejemplo n.º 7
0
 def _get_mouse_position(self):
     # Creates a text with empty space to get the height of the rendered text - this is used
     # to provide the same offset for the tooltip, scaled relative to the current resolution and zoom.
     font_metrics = QFontMetrics(QFont(" "))
     # The height itself is divided by 2 just to reduce the offset so that the tooltip is
     # reasonably positioned, relative to the cursor
     return QCursor.pos() + QPoint(font_metrics.height() / 2, 0)
Ejemplo n.º 8
0
    def create_layout(self):
        '''
        Creates the complete layout including all controls
        '''
        self.title_label = ElidingLabel(text=self.dock_widget.windowTitle())
        self.title_label.set_elide_mode(Qt.ElideRight)
        self.title_label.setObjectName("dockWidgetTabLabel")
        self.title_label.setAlignment(Qt.AlignCenter)
        self.close_button = QPushButton()
        self.close_button.setObjectName("tabCloseButton")

        set_button_icon(self.public.style(), self.close_button,
                        QStyle.SP_TitleBarCloseButton)

        self.close_button.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed)
        self.close_button.setVisible(False)
        self.close_button.setToolTip("Close Tab")
        self.close_button.clicked.connect(self.public.close_requested)

        fm = QFontMetrics(self.title_label.font())
        spacing = round(fm.height() / 4.0)

        # Fill the layout
        layout = QBoxLayout(QBoxLayout.LeftToRight)
        layout.setContentsMargins(2 * spacing, 0, 0, 0)
        layout.setSpacing(0)
        self.public.setLayout(layout)
        layout.addWidget(self.title_label, 1)
        layout.addSpacing(spacing)
        layout.addWidget(self.close_button)
        layout.addSpacing(round(spacing * 4.0 / 3.0))
        layout.setAlignment(Qt.AlignCenter)
        self.title_label.setVisible(True)
Ejemplo n.º 9
0
def show_mouse_toast(message):
    # Creates a text with empty space to get the height of the rendered text - this is used
    # to provide the same offset for the tooltip, scaled relative to the current resolution and zoom.
    font_metrics = QFontMetrics(QFont(" "))
    # The height itself is divided by 2 just to reduce the offset so that the tooltip is
    # reasonably position relative to the cursor
    QToolTip.showText(QCursor.pos() + QPoint(font_metrics.height() / 2, 0), message)
Ejemplo n.º 10
0
def show_mouse_toast(message):
    # Creates a text with empty space to get the height of the rendered text - this is used
    # to provide the same offset for the tooltip, scaled relative to the current resolution and zoom.
    font_metrics = QFontMetrics(QFont(" "))
    # The height itself is divided by 2 just to reduce the offset so that the tooltip is
    # reasonably position relative to the cursor
    QToolTip.showText(QCursor.pos() + QPoint(font_metrics.height() / 2, 0),
                      message)
Ejemplo n.º 11
0
    def __init__(self, parent, widthSpace=10):
        super().__init__()

        self.parent = parent

        self.widthSpace = widthSpace
        self.dateFmt = "%d %b %Y"

        self.headerLabels = [
            'Date', 'Time', 'Distance (km)', 'Avg. speed\n(km/h)', 'Calories',
            'Gear'
        ]
        self.setHeaderLabels(self.headerLabels)
        self.header().setStretchLastSection(False)
        # make header tall enough for two rows of text (avg speed has line break)
        font = self.header().font()
        metrics = QFontMetrics(font)
        height = metrics.height()
        self.header().setMinimumHeight(height * 2)
        # align header text centrally
        for idx in range(len(self.headerLabels)):
            self.headerItem().setTextAlignment(idx, Qt.AlignCenter)

        self.setSelectionMode(QAbstractItemView.ExtendedSelection)

        self.makeTree()

        self.sortColumn = None
        self.sortDescending = [True for _ in range(len(self.headerLabels))]
        self.header().setSectionsClickable(True)
        self.header().sectionClicked.connect(self.sortTree)

        self.currentItemChanged.connect(self._itemChanged)

        self.itemSelectionChanged.connect(self._summariseSelected)

        self.sortTree(0)

        msg = "Browse all sessions, grouped by month. Click on the headers \n"
        msg += "to sort by that metric in ascending or descending order.\n"
        msg += "Click on a session to highlight it in the plot."
        self.setToolTip(msg)

        self.editAction = QAction("Edit")
        self.editAction.setShortcut(QKeySequence("Ctrl+E"))
        self.editAction.triggered.connect(self._editItems)
        self.addAction(self.editAction)

        self.mergeAction = QAction("Merge")
        self.mergeAction.setShortcut(QKeySequence("Ctrl+M"))
        self.mergeAction.triggered.connect(self.combineRows)
        self.addAction(self.mergeAction)

        self.setContextMenuPolicy(Qt.CustomContextMenu)
        self.customContextMenuRequested.connect(self._showContextMenu)
Ejemplo n.º 12
0
    def resize_to_content(self, lines):
        if len(lines) == 0:
            lines.append('')

        # resize properly
        fm = QFontMetrics(self.font())
        text_width = fm.width(lines[0]+'__')
        text_width = text_width+20  # some buffer
        text_height = fm.height()*(len(lines))+12  # also some vertical buffer
        self.setFixedWidth(text_width if text_width > self.base_width else self.base_width)
        self.setFixedHeight(text_height if text_height > self.base_height else self.base_height)
        self.parent_node_instance.update_shape()
Ejemplo n.º 13
0
    def __init__(self,
                 colormap: BaseColormap,
                 accepted: bool,
                 name: str,
                 removable: bool = False,
                 used: bool = False):
        super().__init__()
        self.image = convert_colormap_to_image(colormap)
        self.name = name
        self.removable = removable
        self.checked = QCheckBox()
        self.checked.setChecked(accepted)
        self.checked.setDisabled(used)
        self.setMinimumWidth(80)
        metrics = QFontMetrics(QFont())
        layout = QHBoxLayout()
        layout.addWidget(self.checked)
        layout.addStretch(1)
        self.remove_btn = QToolButton()
        self.remove_btn.setIcon(_icon_selector.close_icon)
        if removable:
            self.remove_btn.setToolTip("Remove colormap")
        else:
            self.remove_btn.setToolTip("This colormap is protected")
        self.remove_btn.setEnabled(not accepted and self.removable)

        self.edit_btn = QToolButton()
        self.edit_btn.setIcon(_icon_selector.edit_icon)
        layout.addWidget(self.remove_btn)
        layout.addWidget(self.edit_btn)
        self.setLayout(layout)
        self.checked.stateChanged.connect(self._selection_changed)
        self.edit_btn.clicked.connect(partial(self.edit_request.emit, name))
        if isinstance(colormap, ColorMap):
            self.edit_btn.clicked.connect(
                partial(self.edit_request[ColorMap].emit, colormap))
            self.edit_btn.setToolTip("Create colormap base on this")
        else:
            self.edit_btn.setDisabled(True)
            self.edit_btn.setToolTip("This colormap is not editable")
        self.remove_btn.clicked.connect(partial(self.remove_request.emit,
                                                name))
        self.setMinimumHeight(
            max(metrics.height(), self.edit_btn.minimumHeight(),
                self.checked.minimumHeight()) + 20)
Ejemplo n.º 14
0
    def __init__(self, parent, ancestor):
        QListWidget.__init__(self, ancestor)
        self.setWindowFlags(Qt.SubWindow | Qt.FramelessWindowHint)
        self.textedit = parent
        self.hide()
        self.itemActivated.connect(self.item_selected)
        self.currentRowChanged.connect(self.row_changed)
        self.is_internal_console = False
        self.completion_list = None
        self.completion_position = None
        self.automatic = False

        # Setup item rendering
        self.setItemDelegate(HTMLDelegate(self, margin=3))
        self.setMinimumWidth(DEFAULT_COMPLETION_ITEM_WIDTH)

        # Initial item height and width
        fm = QFontMetrics(self.textedit.font())
        self.item_height = fm.height()
        self.item_width = self.width()
Ejemplo n.º 15
0
    def create_layout(self):
        '''
        Creates the complete layout including all controls
        '''
        self.title_label = ElidingLabel()
        self.title_label.set_elide_mode(Qt.ElideRight)
        self.title_label.setText("DockWidget->windowTitle()")
        self.title_label.setObjectName("floatingTitleLabel")
        self.title_label.setAlignment(Qt.AlignLeft)

        self.close_button = QPushButton()
        self.close_button.setObjectName("floatingTitleCloseButton")
        self.close_button.setFlat(True)

        # self.close_button.setAutoRaise(True)
        set_button_icon(self.public.style(), self.close_button,
                        QStyle.SP_TitleBarCloseButton)

        self.close_button.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed)
        self.close_button.setVisible(True)
        self.close_button.setFocusPolicy(Qt.NoFocus)
        self.close_button.clicked.connect(self.public.close_requested)

        fm = QFontMetrics(self.title_label.font())
        spacing = round(fm.height() / 4.0)

        # Fill the layout
        layout = QBoxLayout(QBoxLayout.LeftToRight)
        layout.setContentsMargins(6, 0, 0, 0)
        layout.setSpacing(0)
        self.public.setLayout(layout)
        layout.addWidget(self.title_label, 1)
        layout.addSpacing(spacing)
        layout.addWidget(self.close_button)
        layout.setAlignment(Qt.AlignCenter)
        self.title_label.setVisible(True)
Ejemplo n.º 16
0
    def __init__(self, mainWindow, parent=None, rows=5):
        self.headerLabels = [
            'Date', 'Time', 'Distance (km)', 'Avg. speed\n(km/h)', 'Calories',
            'Gear'
        ]
        columns = len(self.headerLabels)
        super().__init__(rows, columns)
        self.mainWindow = mainWindow
        self.parent = parent

        # dict of columns that can be selected and the functions used to compare values
        self.selectableColumns = {
            'Time': hourMinSecToFloat,
            'Distance (km)': float,
            'Avg. speed (km/h)': float,
            'Calories': float
        }

        self.setHorizontalHeaderLabels(self.headerLabels)

        self.setSelectionBehavior(QAbstractItemView.SelectRows)

        self.selectKey = "Avg. speed (km/h)"

        # make header tall enough for two rows of text (avg speed has line break)
        font = self.header.font()
        metrics = QFontMetrics(font)
        height = metrics.height()
        self.header.setMinimumHeight(height * 2)

        self.currentCellChanged.connect(self._cellChanged)
        self.header.sectionClicked.connect(self.selectColumn)
        self.selectColumn(self.headerLabels.index('Avg. speed\n(km/h)'))

        self.newIdx = None
        self._setToolTip(rows)
Ejemplo n.º 17
0
class LineNumberArea(QWidget):
    def __init__(self, textEditor):
        QWidget.__init__(self, textEditor)
        self.textEditor = textEditor
        self.prefix_color = Qt.lightGray
        self.prefix_font_color = Qt.black
        self.update_font()

        self._firstlinecode = [' >>> ']
        self.blinks = [':', ' ']

        self.painter = QPainter()

        self.promptTimer = QTimer(self)
        self.promptTimer.timeout.connect(self.nextPrompt)

        self.profile_start = time.monotonic()
        self.profile_threshold = 10
        self.profile_enabled = False

    def start_profiling(self):
        self.profile_start = time.monotonic()
        self.profile_enabled = True

    def stop_profiling(self):
        self.profile_enabled = False

    def update_font(self):
        self.setFont(self.textEditor.font())
        self.fontmetric = QFontMetrics(self.textEditor.font())
        self.prefixwidth = self.fontmetric.width('12345')
        self.prefixheight = self.fontmetric.height()
        self.setFixedWidth(self.prefixwidth)
        self.textEditor.setViewportMargins(self.prefixwidth, 0, 0, 0)

    def set_firstlinecode(self, prefices):
        self._firstlinecode = prefices

        if len(self._firstlinecode) > 1:
            self.promptTimer.start(500)
        else:
            self.promptTimer.stop()

    def get_firstlinecode(self):
        if self.profile_enabled:
            elapsed = time.monotonic() - self.profile_start
            if elapsed > self.profile_threshold:
                if elapsed >= 3600:
                    profile = time.strftime("%H:%M", time.gmtime(elapsed))
                else:
                    profile = time.strftime("%M:%S", time.gmtime(elapsed))
                return profile[:-3] + self.blinks[0] + profile[-2:]
        return self._firstlinecode[0]

    firstlinecode = property(get_firstlinecode, set_firstlinecode)

    def nextPrompt(self):
        self._firstlinecode = self._firstlinecode[1:] + self._firstlinecode[:1]
        self.blinks = self.blinks[1:] + self.blinks[:1]
        self.repaint()

    def paintEvent(self, event):
        cursor = self.textEditor.cursorForPosition(
            self.textEditor.viewport().pos())

        painter = self.painter
        try:
            painter.begin(self)
            painter.fillRect(event.rect(), self.prefix_color)

            for i in range(100):
                blockNumber = cursor.block().blockNumber()

                if blockNumber == 0:
                    code = self.firstlinecode
                else:
                    code = str(blockNumber + 1)

                painter.setPen(self.prefix_font_color)
                y = self.textEditor.cursorRect(
                    cursor).y() + self.textEditor.viewport().pos().y() - 2
                painter.drawText(0, y, self.prefixwidth, self.prefixheight,
                                 Qt.AlignRight, code)

                if y > event.rect().bottom():
                    break
                if not cursor.block().next().isValid():
                    break

                cursor.movePosition(cursor.NextBlock)
        finally:
            painter.end()

    def sizeHint(self):
        return QSize(self.prefixwidth, 0)
Ejemplo n.º 18
0
Archivo: byte.py Proyecto: slaclab/pydm
 def minimumSizeHint(self):
     fm = QFontMetrics(self.font())
     return QSize(fm.height(), fm.height())
Ejemplo n.º 19
0
class NodeGeometry:
    def __init__(self, node: NodeBase):
        super().__init__()
        self._node = node
        self._model = node.model
        self._dragging_pos = QPointF(-1000, -1000)
        self._entry_width = 0
        self._entry_height = 20
        self._font_metrics = QFontMetrics(QFont())
        self._height = 150
        self._hovered = False
        self._input_port_width = 70
        self._output_port_width = 70
        self._spacing = 20
        self._style = node.style
        self._width = 100

        f = QFont()
        f.setBold(True)
        self._bold_font_metrics = QFontMetrics(f)

    @property
    def height(self) -> int:
        """
        Height

        Returns
        -------
        value : int
        """
        return self._height

    @height.setter
    def height(self, h: int):
        self._height = int(h)

    @property
    def width(self) -> int:
        """
        Width

        Returns
        -------
        value : int
        """
        return self._width

    @width.setter
    def width(self, width: int):
        """
        Set width

        Parameters
        ----------
        width : int
        """
        self._width = int(width)

    @property
    def entry_height(self) -> int:
        """
        Entry height

        Returns
        -------
        value : int
        """
        return self._entry_height

    @entry_height.setter
    def entry_height(self, h: int):
        """
        Set entry height

        Parameters
        ----------
        h : int
        """
        self._entry_height = int(h)

    @property
    def entry_width(self) -> int:
        """
        Entry width

        Returns
        -------
        value : int
        """
        return self._entry_width

    @entry_width.setter
    def entry_width(self, width: int):
        """
        Set entry width

        Parameters
        ----------
        width : int
        """
        self._entry_width = int(width)

    @property
    def spacing(self) -> int:
        """
        Spacing

        Returns
        -------
        value : int
        """
        return self._spacing

    @spacing.setter
    def spacing(self, s: int):
        """
        Set spacing

        Parameters
        ----------
        s : int
        """
        self._spacing = int(s)

    @property
    def hovered(self) -> bool:
        """
        Hovered

        Returns
        -------
        value : bool
        """
        return self._hovered

    @hovered.setter
    def hovered(self, h: int):
        """
        Set hovered

        Parameters
        ----------
        h : int
        """
        self._hovered = bool(h)

    @property
    def num_sources(self) -> int:
        """
        N sources

        Returns
        -------
        value : int
        """
        return self._model.num_ports[PortType.output]

    @property
    def num_sinks(self) -> int:
        """
        N sinks

        Returns
        -------
        value : int
        """
        return self._model.num_ports[PortType.input]

    @property
    def dragging_pos(self) -> QPointF:
        """
        Dragging pos

        Returns
        -------
        value : QPointF
        """
        return self._dragging_pos

    @dragging_pos.setter
    def dragging_position(self, pos: QPointF):
        self._dragging_pos = QPointF(pos)

    def entry_bounding_rect(self, *, addon=0.0) -> QRectF:
        """
        Entry bounding rect

        Returns
        -------
        value : QRectF
        """
        return QRectF(0 - addon, 0 - addon, self._entry_width + 2 * addon,
                      self._entry_height + 2 * addon)

    @property
    def bounding_rect(self) -> QRectF:
        """
        Bounding rect

        Returns
        -------
        value : QRectF
        """
        addon = 4 * self._style.connection_point_diameter
        return QRectF(0 - addon, 0 - addon, self._width + 2 * addon,
                      self._height + 2 * addon)

    def recalculate_size(self, font: QFont = None):
        """
        If font is unspecified,
            Updates size unconditionally
        Otherwise,
            Updates size if the QFontMetrics is changed
        """
        if font is not None:
            font_metrics = QFontMetrics(font)
            bold_font = QFont(font)
            bold_font.setBold(True)
            bold_font_metrics = QFontMetrics(bold_font)
            if self._bold_font_metrics == bold_font_metrics:
                return

            self._font_metrics = font_metrics
            self._bold_font_metrics = bold_font_metrics

        self._entry_height = self._font_metrics.height()

        max_num_of_entries = max((self.num_sinks, self.num_sources))
        step = self._entry_height + self._spacing
        height = step * max_num_of_entries

        widget = self._model.embedded_widget()
        if widget:
            height = max((height, widget.height()))

        height += self.caption_height
        self._input_port_width = self.port_width(PortType.input)
        self._output_port_width = self.port_width(PortType.output)
        width = self._input_port_width + self._output_port_width + 2 * self._spacing

        if widget:
            width += widget.width()

        width = max((width, self.caption_width))

        if self._model.validation_state() != NodeValidationState.valid:
            width = max((width, self.validation_width))
            height += self.validation_height + self._spacing

        self._width = width
        self._height = height

    def port_scene_position(self,
                            port_type: PortType,
                            index: int,
                            t: QTransform = None) -> QPointF:
        """
        Port scene position

        Parameters
        ----------
        port_type : PortType
        index : int
        t : QTransform

        Returns
        -------
        value : QPointF
        """
        if t is None:
            t = QTransform()

        step = self._entry_height + self._spacing
        total_height = float(self.caption_height) + step * index
        # TODO_UPSTREAM: why?
        total_height += step / 2.0

        if port_type == PortType.output:
            x = self._width + self._style.connection_point_diameter
            result = QPointF(x, total_height)
        elif port_type == PortType.input:
            x = -float(self._style.connection_point_diameter)
            result = QPointF(x, total_height)
        else:
            raise ValueError(port_type)

        return t.map(result)

    def check_hit_scene_point(self, port_type: PortType, scene_point: QPointF,
                              scene_transform: QTransform) -> Port:
        """
        Check hit scene point

        Parameters
        ----------
        port_type : PortType
        scene_point : QPointF
        scene_transform : QTransform

        Returns
        -------
        value : Port
        """
        if port_type == PortType.none:
            return None

        tolerance = 2.0 * self._style.connection_point_diameter
        for idx, port in self._node.state[port_type].items():
            pos = port.get_mapped_scene_position(scene_transform) - scene_point
            distance = math.sqrt(QPointF.dotProduct(pos, pos))
            if distance < tolerance:
                return port

    @property
    def resize_rect(self) -> QRect:
        """
        Resize rect

        Returns
        -------
        value : QRect
        """
        rect_size = 7
        return QRect(self._width - rect_size, self._height - rect_size,
                     rect_size, rect_size)

    @property
    def widget_position(self) -> QPointF:
        """
        Returns the position of a widget on the Node surface

        Returns
        -------
        value : QPointF
        """
        widget = self._model.embedded_widget()
        if not widget:
            return QPointF()

        if widget.sizePolicy().verticalPolicy() & QSizePolicy.ExpandFlag:
            # If the widget wants to use as much vertical space as possible,
            # place it immediately after the caption.
            return QPointF(self._spacing + self.port_width(PortType.input),
                           self.caption_height)

        if self._model.validation_state() != NodeValidationState.valid:
            return QPointF(
                self._spacing + self.port_width(PortType.input),
                (self.caption_height + self._height - self.validation_height -
                 self._spacing - widget.height()) / 2.0,
            )

        return QPointF(self._spacing + self.port_width(PortType.input),
                       (self.caption_height + self._height - widget.height()) /
                       2.0)

    def equivalent_widget_height(self) -> int:
        '''
        The maximum height a widget can be without causing the node to grow.

        Returns
        -------
        value : int
        '''
        base_height = self.height - self.caption_height

        if self._model.validation_state() != NodeValidationState.valid:
            return (base_height + self.validation_height)

        return base_height

    @property
    def validation_height(self) -> int:
        """
        Validation height

        Returns
        -------
        value : int
        """
        msg = self._model.validation_message()
        return self._bold_font_metrics.boundingRect(msg).height()

    @property
    def validation_width(self) -> int:
        """
        Validation width

        Returns
        -------
        value : int
        """
        msg = self._model.validation_message()
        return self._bold_font_metrics.boundingRect(msg).width()

    @staticmethod
    def calculate_node_position_between_node_ports(
            target_port_index: int, target_port: PortType,
            target_node: NodeBase, source_port_index: int,
            source_port: PortType, source_node: NodeBase,
            new_node: NodeBase) -> QPointF:
        """
        calculate node position between node ports

        Calculating the nodes position in the scene. It'll be positioned half
        way between the two ports that it "connects".  The first line
        calculates the halfway point between the ports (node position + port
        position on the node for both nodes averaged).  The second line offsets
        self coordinate with the size of the new node, so that the new nodes
        center falls on the originally calculated coordinate, instead of it's
        upper left corner.

        Parameters
        ----------
        target_port_index : int
        target_port : PortType
        target_node : Node
        source_port_index : int
        source_port : PortType
        source_node : Node
        new_node : Node

        Returns
        -------
        value : QPointF
        """
        converter_node_pos = (source_node.graphics_object.pos() +
                              source_node.geometry.port_scene_position(
                                  source_port, source_port_index) +
                              target_node.graphics_object.pos() +
                              target_node.geometry.port_scene_position(
                                  target_port, target_port_index)) / 2.0
        converter_node_pos.setX(converter_node_pos.x() -
                                new_node.geometry.width / 2.0)
        converter_node_pos.setY(converter_node_pos.y() -
                                new_node.geometry.height / 2.0)
        return converter_node_pos

    @property
    def caption_height(self) -> int:
        """
        Caption height

        Returns
        -------
        value : int
        """
        if not self._model.caption_visible:
            return 0
        name = self._model.caption
        return self._bold_font_metrics.boundingRect(name).height()

    @property
    def caption_width(self) -> int:
        """
        Caption width

        Returns
        -------
        value : int
        """
        if not self._model.caption_visible:
            return 0
        name = self._model.caption
        return self._bold_font_metrics.boundingRect(name).width()

    def port_width(self, port_type: PortType) -> int:
        """
        Port width

        Parameters
        ----------
        port_type : PortType

        Returns
        -------
        value : int
        """
        names = [port.display_text for port in self._node[port_type].values()]
        if not names:
            return 0

        return max(
            self._font_metrics.horizontalAdvance(name) for name in names)

    @property
    def size(self):
        """
        Get the node size

        Parameters
        ----------
        node : Node

        Returns
        -------
        value : QSizeF
        """
        return QSizeF(self.width, self.height)
Ejemplo n.º 20
0
 def minimumSizeHint(self):
     fm = QFontMetrics(self.font())
     return QSize(fm.height(), fm.height())