def ensure_string_size(s, size, font): metrics = QFontMetrics(font) if metrics.horizontalAdvance(s) > size: while metrics.horizontalAdvance(s + "...") > size: s = s[:len(s) - 1] s += "..." return s
def __calculateHeaderSizes(self): """ Private method to calculate the section sizes of the horizontal header. """ fm = QFontMetrics(QFont()) for section in range(self.__passwordModel.columnCount()): header = self.passwordsTable.horizontalHeader().sectionSizeHint( section) if section == 0: try: header = fm.horizontalAdvance("averagebiglongsitename") except AttributeError: header = fm.width("averagebiglongsitename") elif section == 1: try: header = fm.horizontalAdvance("averagelongusername") except AttributeError: header = fm.width("averagelongusername") elif section == 2: try: header = fm.horizontalAdvance("averagelongpassword") except AttributeError: header = fm.width("averagelongpassword") try: buffer = fm.horizontalAdvance("mm") except AttributeError: buffer = fm.width("mm") header += buffer self.passwordsTable.horizontalHeader().resizeSection( section, header) self.passwordsTable.horizontalHeader().setStretchLastSection(True)
def ensure_string_size(s, size, font): if QGuiApplication.platformName() != "offscreen": metrics = QFontMetrics(font) if metrics.horizontalAdvance(s) > size: while metrics.horizontalAdvance(s + "..") > size: s = s[:len(s) - 1] s += ".." return s
def createUi(self): toolbar = QToolBar(self) save_icon = QIcon() save_icon.addPixmap(QPixmap(":/files/save_icon.svg"), QIcon.Normal, QIcon.Off) save_action = QAction(save_icon, 'Save', self) save_action.triggered.connect(self.save_design) toolbar.addAction(save_action) above_table_view = QTableView(self) above_table_model = ExchangerDesignTableModel(self._setup, 'abv', above_table_view) above_table_view.setModel(above_table_model) above_table_view.setMinimumHeight(100) above_table_view.setMaximumHeight(150) largest_header = max(HEDFM.headers(), key=len) font = QFont() font.setBold(True) fm = QFontMetrics(font) header = above_table_view.horizontalHeader() header.setMinimumSectionSize(fm.horizontalAdvance(largest_header)) header.setSectionResizeMode(QHeaderView.Stretch) below_table_view = QTableView(self) below_table_model = ExchangerDesignTableModel(self._setup, 'blw', below_table_view) below_table_view.setModel(below_table_model) below_table_view.setMinimumHeight(100) below_table_view.setMaximumHeight(150) largest_header = max(HEDFM.headers(), key=len) fm = QFontMetrics(font) header = below_table_view.horizontalHeader() header.setMinimumSectionSize(fm.horizontalAdvance(largest_header)) header.setSectionResizeMode(QHeaderView.Stretch) self.above_view = QGraphicsView(self) self.above_scene = PinchDesignScene('abv', self._setup, self.above_view) self.above_view.setScene(self.above_scene) self.below_view = QGraphicsView(self) self.below_scene = PinchDesignScene('blw', self._setup, self.below_view) self.below_view.setScene(self.below_scene) layout = QGridLayout() layout.addWidget(toolbar, 0, 0, 1, 1) layout.addWidget(above_table_view, 1, 0, 1, 1) layout.addWidget(self.above_view, 2, 0, 1, 1) layout.addWidget(below_table_view, 1, 1, 1, 1) layout.addWidget(self.below_view, 2, 1, 1, 1) self.setLayout(layout)
def __init__(self, cookieJar, parent=None): """ Constructor @param cookieJar reference to the cookie jar (CookieJar) @param parent reference to the parent widget (QWidget) """ super(CookiesExceptionsDialog, self).__init__(parent) self.setupUi(self) self.__cookieJar = cookieJar self.removeButton.clicked.connect(self.exceptionsTable.removeSelected) self.removeAllButton.clicked.connect(self.exceptionsTable.removeAll) self.exceptionsTable.verticalHeader().hide() self.__exceptionsModel = CookieExceptionsModel(cookieJar) self.__proxyModel = QSortFilterProxyModel(self) self.__proxyModel.setSourceModel(self.__exceptionsModel) self.searchEdit.textChanged.connect( self.__proxyModel.setFilterFixedString) self.exceptionsTable.setModel(self.__proxyModel) self.domainEdit.setCompleter( QCompleter(cookieJar.cookieDomains(), self.domainEdit)) f = QFont() f.setPointSize(10) fm = QFontMetrics(f) height = fm.height() + fm.height() // 3 self.exceptionsTable.verticalHeader().setDefaultSectionSize(height) self.exceptionsTable.verticalHeader().setMinimumSectionSize(-1) for section in range(self.__exceptionsModel.columnCount()): header = self.exceptionsTable.horizontalHeader().sectionSizeHint( section) if section == 0: try: header = fm.horizontalAdvance( "averagebiglonghost.averagedomain.info") except AttributeError: header = fm.width("averagebiglonghost.averagedomain.info") elif section == 1: try: header = fm.horizontalAdvance(self.tr("Allow For Session")) except AttributeError: header = fm.width(self.tr("Allow For Session")) try: buffer = fm.horizontalAdvance("mm") except AttributeError: buffer = fm.width("mm") header += buffer self.exceptionsTable.horizontalHeader().resizeSection( section, header)
def headerData(self, section, orientation, role): """ Public method to get header data from the model. @param section section number (integer) @param orientation orientation (Qt.Orientation) @param role role of the data to retrieve (integer) @return requested data """ if role == Qt.SizeHintRole: fm = QFontMetrics(QFont()) height = fm.height() + fm.height() // 3 try: width = fm.horizontalAdvance( self.headerData(section, orientation, Qt.DisplayRole)) except AttributeError: width = fm.width( self.headerData(section, orientation, Qt.DisplayRole)) return QSize(width, height) if orientation == Qt.Horizontal and role == Qt.DisplayRole: try: return self.__headers[section] except IndexError: return None return QAbstractTableModel.headerData(self, section, orientation, role)
def set_font(self, font: QFont = None): qfd = QFontDatabase() if font: info = QFontInfo(font) if info.styleHint() != QFont.Monospace: self.logger.warning("font: Please use monospaced font! " f"Unsupported font {info.family}.") font = qfd.systemFont(QFontDatabase.FixedFont) elif "Menlo" in qfd.families(): font = QFont("Menlo") info = QFontInfo(font) else: font = qfd.systemFont(QFontDatabase.FixedFont) info = QFontInfo(font) font.setPointSize(12) self.font = font metrics = QFontMetrics(font) self.char_width = metrics.horizontalAdvance("A") self.char_height = metrics.height() self.line_height = int(self.char_height * 1.2) self.logger.info(f"font: Font {info.family()} selected, character " f"size {self.char_width}x{self.char_height}.") self.row_len = int(self._width / self.char_width) self.col_len = int(self._height / self.line_height)
def _set_bounding_rect(self, text, top_left, font_name, font_size): font = QFont(font_name, font_size) metrics = QFontMetrics(font) width = metrics.horizontalAdvance(text) height = metrics.height() # ensures that origin is top left corner of the rectangle self._top_left = Coordinate(px=top_left) self._sides = Coordinate(px=[width, height])
def _paint_utility_blocks(self): scene = self w = scene.width() - (self._left_p + self._right_p) h = scene.height() - (self._top_p + self._bot_p) block_width = self._block_width font = QFont() font.setPointSize(12) font.setBold(True) fm = QFontMetrics(font) # hot utility pen = QPen(Qt.red, 5, Qt.SolidLine, Qt.SquareCap, Qt.RoundJoin) path = QPainterPath() path.addRoundedRect(0, 0, block_width, h, 10, 10) path = scene.addPath(path, pen=pen) path.setPos(self._map_x(0), self._map_y(h)) text = scene.addText("Hot Utility", font=font) text.setDefaultTextColor(Qt.red) t_wid = fm.horizontalAdvance(text.toPlainText()) text.setPos( self._map_x((block_width - fm.height()) / 2), self._map_y((h - t_wid) / 2) ) text.setRotation(-90.0) # cold utility pen = QPen(Qt.blue, 5, Qt.SolidLine, Qt.SquareCap, Qt.RoundJoin) path = QPainterPath() path.addRoundedRect(0, 0, block_width, h, 10, 10) path = scene.addPath(path, pen=pen) path.setPos(self._map_x(w - block_width), self._map_y(h)) text = scene.addText("Cold Utility", font=font) text.setDefaultTextColor(Qt.blue) t_wid = fm.horizontalAdvance(text.toPlainText()) text.setPos( self._map_x(w - (block_width + fm.height()) / 2), self._map_y((h - t_wid) / 2) ) text.setRotation(-90.0)
def resize_combobox(combobox): font = combobox.property("font") metrics = QFontMetrics(font) min_width = 0 for i in range(combobox.count()): size = metrics.horizontalAdvance(combobox.itemText(i)) if size > min_width: min_width = size combobox.setMinimumWidth(min_width + 30)
def __init__(self, parent=None, manager=None): """ Constructor @param parent reference to the parent widget (QWidget @param manager reference to the bookmarks manager object (BookmarksManager) """ super(BookmarksDialog, self).__init__(parent) self.setupUi(self) self.setWindowFlags(Qt.Window) self.__bookmarksManager = manager if self.__bookmarksManager is None: import WebBrowser.WebBrowserWindow self.__bookmarksManager = ( WebBrowser.WebBrowserWindow.WebBrowserWindow.bookmarksManager() ) self.__bookmarksModel = self.__bookmarksManager.bookmarksModel() self.__proxyModel = E5TreeSortFilterProxyModel(self) self.__proxyModel.setFilterKeyColumn(-1) self.__proxyModel.setSourceModel(self.__bookmarksModel) self.searchEdit.textChanged.connect( self.__proxyModel.setFilterFixedString) self.bookmarksTree.setModel(self.__proxyModel) self.bookmarksTree.setExpanded(self.__proxyModel.index(0, 0), True) fm = QFontMetrics(self.font()) try: header = fm.horizontalAdvance("m") * 40 except AttributeError: header = fm.width("m") * 40 self.bookmarksTree.header().resizeSection(0, header) self.bookmarksTree.header().setStretchLastSection(True) self.bookmarksTree.setContextMenuPolicy(Qt.CustomContextMenu) self.bookmarksTree.activated.connect(self.__activated) self.bookmarksTree.customContextMenuRequested.connect( self.__customContextMenuRequested) self.removeButton.clicked.connect( self.bookmarksTree.removeSelected) self.addFolderButton.clicked.connect(self.__newFolder) self.__expandNodes(self.__bookmarksManager.bookmarks())
def makeAction(self, icon, text, parent): """ Public method to create an action. @param icon icon of the action (QIcon) @param text text of the action (string) @param parent reference to the parent object (QObject) @return reference to the created action (QAction) """ fm = QFontMetrics(self.font()) if self.__maxWidth == -1: try: self.__maxWidth = fm.horizontalAdvance("m") * 30 except AttributeError: self.__maxWidth = fm.width('m') * 30 smallText = fm.elidedText(text, Qt.ElideMiddle, self.__maxWidth) return QAction(icon, smallText, parent)
def _paint_horizontal_lines(self) -> None: scene = self w = scene.width() - (self._left_p + self._right_p) h = scene.height() - (self._top_p + self._bot_p) # label font temp_lbl_fmt = '{0:4g} ({1})' font = QFont() font.setBold(True) hot_int = np.unique( self._hot_str.loc[:, [STFCFM.TIN.name, STFCFM.TOUT.name]].values) dt = self._setup.dt int_size = h / (hot_int.size - 1) for i, temp in enumerate(hot_int): x_temp = self._map_x(0.0) y_temp = self._map_y(self._temp_to_px(temp, hot_int)) # add the hot side temperature labels temp_lbl = temp_lbl_fmt.format(temp, self._setup.units.temperature) text = scene.addText(temp_lbl) text.setDefaultTextColor(Qt.red) text.setFont(font) fm = QFontMetrics(text.font()) # measure the text width required label_offset = fm.horizontalAdvance(text.toPlainText()) text.setPos(x_temp - label_offset, y_temp) # cold side labels temp_lbl = temp_lbl_fmt.format(temp - dt, self._setup.units.temperature) text = scene.addText(temp_lbl) text.setDefaultTextColor(Qt.blue) text.setFont(font) text.setPos(x_temp + w, y_temp) # horizontal interval lines dash_pen = QPen(Qt.DashLine) dash_pen.setDashPattern([20, 10]) line = scene.addLine(0, 0, w, 0, pen=dash_pen) line.setPos(x_temp, y_temp)
def create_path(self, start_point, end_point, directed): """Creeaza path-ul muchiei Path-ul muchiei este o curba Bezier. In cazul in care nici-un nod nu se intersecteaza cu path-ul direct dintre noduri, punctele de control ale curbei vor fi la centrul de greutate al dreptei date de cele 2 noduri, astfel creeandu-se o linie dreapta. In caz contrar, daca un nod se intersecteaza cu path-ul direct, pucntele de control ale curbei se vor situa pe dreapta perpendiculara pe path-ul direct, ce trece centrul de greutate al acestuia (dat de punctul de control initial) la o distanta egala dublul razei nodului. Aceste pucnte se pot situa in 2 pozitii, una la 'stanga' path-ului, iar cealalta la 'dreaptea' acestuia. Pozitia finala a punctului de control se determina 'trasand' 2 linii de la nodul care se intersecteaza la cele 2 posibile puncte de control. Verificand lungimea celor 2 linii se alege locatia punctului de control. panta dreptei : m = (y2 - y1) / (x2 - x1) ecuatia dreptei : y - y1 = m(x - x1) panta drepntei perpendiculare pe o dreapta : m' = -1 / m lungimea unei drepte : AB ^ 2 = (x2 - x1) ^ 2 + (y2 - y1) ^ 2 => primul pas pentru a afla pucntele de control in cazul unei intersectii este: de a calula panta dreptei perpendiculara pe path-ul direct => m' = -1 / (node2.y - node1.y) / (node2.x - node1.x) => m' = -1 * (node2.x - node1.x) / (node2.y - node1.y) => cel de-al doilea pas este calcularea ecuatiei dreptei de panta m' ce trece prin pucntul de control (not G) => y - G.y = m'(x - G.x) => y = m'(x - G.x) + G.y => cel de-al treilea pas este inlocuirea lui y in lungimea dreptei ( lungimea dreptei dorita este dublul razei nodului) pentru a afla cele 2 coordonate x posibile (la 'stanga' si la 'dreapta' path-ului direct) => (x2 - G.x) ^ 2 + (m'(x2 - G.x) + G.y - G.y) ^ 2 = (2raza) ^ 2 => x2 ^ 2 - 2 x2 G.x + G.x ^ 2 + (m' x2) ^ 2 - 2 (m' ^ 2) x2 G.x + (m' G.x) ^ 2 - (2raza) ^ 2 = 0 => (x2 ^ 2)(1 + m' ^ 2) + x2(2 G.x (1 + m' ^ 2)) + (G.x ^ 2)(1 + m' ^ 2) - (2raza) ^ 2 = 0 => cele 2 coordonate pe Ox ale punctului de control, prentu a afla cele 2 coordonate pe Oy se inlocuiesc valorie obtinute in ecuatia dreptei. Parametrii ---------- start_point : QPointF punctul de start al path-ului end_point : QPointF punctul de final al path-ului directed : bool orientarea grafului Returneaza ---------- path : QPainterPath path-ul final al muchiei """ # Centrul de greutate al dreptei formata de cele 2 noduri control_point = QPointF((start_point.x() + end_point.x()) / 2, (start_point.y() + end_point.y()) / 2) path = QPainterPath(start_point) node_radius = self.engine.node_radius point1 = point2 = None # Creearea path-ului direct _path = QPainterPath(start_point) _path.lineTo(end_point) self.direct_path.setPath(_path) # Verificarea pentru intersectii cu path-ul direct intersecting_items = self.engine.view.scene.collidingItems( self.direct_path) intersecting_items.remove(self.node1) intersecting_items.remove(self.node2) # Calcularea coordonatelor pe Ox a punctelor de control in cazul unei intersectii try: m = -1 * (self.node2.x() - self.node1.x()) / (self.node2.y() - self.node1.y()) agent = 1 + (m**2) factors = [ agent, -2 * control_point.x() * agent, (control_point.x()**2) * agent - (node_radius * 2)**2 ] roots = np.roots(factors) # In cazul in care nodurile au acceleasi coordonate pe Ox sau Oy panta # dreptei nu exista. Atunci se va trata cazul de ZeroDivisionError except ZeroDivisionError: point1 = control_point + QPointF(0, node_radius * 2) point2 = control_point - QPointF(0, node_radius * 2) for item in intersecting_items: if isinstance(item, Node): # Daca exista o intersectie si exista si panta dreptei atunci se calculeaza # si coordonatele pe Oy ale posibilelor puncte de control if (point1 and point2) is None: point1 = QPointF( roots[0], m * (roots[0] - control_point.x()) + control_point.y()) point2 = QPointF( roots[1], m * (roots[1] - control_point.x()) + control_point.y()) # Cele 2 linii de la nod la posibilele puncte de control line1 = QLineF(item.pos(), point1) line2 = QLineF(item.pos(), point2) # Daca lungimea primei linii este mai mica decat lungimea celei de-a doua linie # inseamna ca nodul este mai aproape de prima linie deci path-ul va trebui sa se # curbeze in partea opusa => se alege cel de-al doilea punct control_point = point2 if line1.length() <= line2.length( ) else point1 break # Creearea curbei Bezier path.cubicTo(control_point, control_point, end_point) # Daca graful este orientat se adauga la capatul muchiei o sageata pentru # a reprezenta orientarea acestuia if directed: pos = path.currentPosition() dx, dy, angle = self.engine.get_angle(control_point, end_point) path.lineTo( QPointF(pos.x() + self.arrow_length * math.cos(angle + 60), pos.y() + self.arrow_length * math.sin(angle + 60))) path.moveTo(end_point) path.lineTo( QPointF(pos.x() + self.arrow_length * math.cos(angle - 60), pos.y() + self.arrow_length * math.sin(angle - 60))) # In cazul in care muchia are un cost acesta va fi afisat la mijlocul muchiei font_metrics = QFontMetrics(TEXT_FONT) font_offset = QPointF(font_metrics.height(), font_metrics.horizontalAdvance(self.cost)) path.addText(control_point - font_offset / 2, TEXT_FONT, self.cost) return path
def data(self, index, role=Qt.DisplayRole): """ Public method get the role data of item. @param index the model index @type QModelIndex @param role the requested data role @type QtCore.Qt.ItemDataRole @return role data of item @rtype Any """ if not index.isValid() or index.row() < 0: return None node = index.internalPointer() column = index.column() if role in (Qt.DisplayRole, SORT_ROLE, Qt.EditRole): try: if column == 0: # Sort first column with values from third column if role == SORT_ROLE: return node.sort return node.name + node.indicator elif column == 1: return node.valueShort elif column == 2: return node.type elif column == 3: return node.sort else: return None except AttributeError: return ['None', '', '', ''][column] elif role == Qt.BackgroundRole: if node in node.parent.changedItems: return self.__bgColorChanged elif node in node.parent.newItems: return self.__bgColorNew elif role == Qt.ToolTipRole: if column == 0: tooltip = node.name + node.indicator elif column == 1: tooltip = node.tooltip elif column == 2: tooltip = node.type elif column == 3: tooltip = node.sort else: return None if Qt.mightBeRichText(tooltip): tooltip = Utilities.html_encode(tooltip) if column == 0: indentation = self.treeView.indentation() indentCount = 0 currentNode = node while currentNode.parent: indentCount += 1 currentNode = currentNode.parent indentation *= indentCount else: indentation = 0 # Check if text is longer than available space fontMetrics = QFontMetrics(self.treeView.font()) try: textSize = fontMetrics.horizontalAdvance(tooltip) except AttributeError: textSize = fontMetrics.width(tooltip) textSize += indentation + 5 # How to determine border size? header = self.treeView.header() if textSize >= header.sectionSize(column): return tooltip else: QToolTip.hideText() return None
def paint(self, painter, option, index): dlg = index.model().data(index, Qt.DisplayRole) painter.setRenderHint(QPainter.Antialiasing) color = QColor(Qt.white) if option.state & QStyle.State_MouseOver: color = QColor(variables.HIGHLIGHT_COLOR) painter.setPen(QPen(color)) painter.setBrush(QBrush(color)) painter.drawRect(option.rect) painter.setPen(Qt.black) painter.setBrush(Qt.NoBrush) painter.drawLine(option.rect.bottomLeft(), option.rect.bottomRight()) doc = QTextDocument(dlg.ip) doc.setDocumentMargin(0) doc.setDefaultFont(variables.font) textrect = QRect(option.rect) textrect = textrect.marginsRemoved(variables.IP_PADDING) textrect.setHeight(int(doc.size().height())) textrect.setWidth(int(doc.size().width())) offset = textrect.marginsAdded(variables.IP_PADDING).height() painter.setPen(Qt.black) painter.setFont(variables.font) painter.translate(textrect.x(), textrect.y()) textrectf = QRectF(textrect) textrectf.moveTo(0, 0) doc.drawContents(painter, textrectf) painter.translate(-textrect.x(), -textrect.y()) string = "" if dlg.user == variables.USER_ME: string += "You: " print(dlg.msg) string += dlg.msg fm = QFontMetrics(variables.font_small) textrect = QRect(option.rect) textrect.moveTop(textrect.y() + offset) textrect = textrect.marginsRemoved(variables.MSG_PADDING) textrect.setHeight(fm.lineSpacing()) spainter = QStylePainter(painter.device(), QWidget()) spainter.setRenderHint(QPainter.Antialiasing) if fm.horizontalAdvance(string) > textrect.width(): fade = QLinearGradient(variables.MSG_PADDING.left() + textrect.width()* 0.9, 0, variables.MSG_PADDING.left() + textrect.width(), 0) fade.setSpread(QGradient.PadSpread) fade.setColorAt(0, Qt.darkGray) fade.setColorAt(1, color) pal = QPalette() pal.setBrush(QPalette.Text, QBrush(fade)) spainter.setFont(variables.font_small) spainter.drawItemText(textrect, Qt.TextSingleLine, pal, True, string, QPalette.Text) else: spainter.setPen(Qt.darkGray) spainter.setFont(variables.font_small) spainter.drawText(textrect, Qt.TextSingleLine, string) p1 = textrect.bottomRight() + QPoint(36, -int(textrect.height() / 2)) if dlg.status == variables.STATUS_UNREAD: spainter.setPen(Qt.NoPen) spainter.setBrush(QColor(variables.STATUS_COLOR)) spainter.drawEllipse(p1, 7, 7) elif dlg.status == variables.STATUS_UNDELIVERED: pen = QPen(QColor(variables.STATUS_COLOR)) pen.setWidth(2) spainter.setPen(pen) spainter.setBrush(Qt.NoBrush) spainter.drawEllipse(p1, 7, 7) spainter.drawLine(p1, p1 + QPoint(0, -5)) spainter.drawLine(p1, p1 + QPoint(3, 0)) elif dlg.status == variables.STATUS_NEW: pen = QPen(QColor(variables.STATUS_NEW_COLOR)) pen.setWidth(5) spainter.setPen(pen) spainter.setBrush(Qt.NoBrush) spainter.drawEllipse(p1, 7, 7) #painter.translate(-textrect.x(), -textrect.y()) '''doc = QTextDocument(str)
def _paint_heat_flow_arrows(self) -> None: scene = self w = scene.width() - (self._left_p + self._right_p) h = scene.height() - (self._top_p + self._bot_p) n_blocks = len(self._blocks_tracker) int_names = list(self._blocks_tracker.keys()) int_blocks = list(self._blocks_tracker.values()) flow_font = QFont() flow_font.setPointSize(12) fm = QFontMetrics(flow_font) idx = 0 heat_flow = self._setup.heat_flow while idx < (n_blocks - 1): cur_block = int_blocks[idx] nxt_block = int_blocks[idx + 1] blk_pen = cur_block.pen() if heat_flow.at[idx, HFM.OUT.name] > 0: # paint flow between intervals b_mid = cur_block.pos().x() + cur_block.rect().size().width() / 2 b_bot = cur_block.pos().y() + cur_block.rect().size().height() b_top = nxt_block.pos().y() arrow = ArrowItem(b_mid, b_bot, b_mid, b_top, color=blk_pen.color(), width=blk_pen.width()) scene.addItem(arrow) out_flow = heat_flow.at[idx, HFM.OUT.name] text = scene.addText( self._heat_format.format( out_flow, self._heat_unit ), font=flow_font ) t_wid = fm.horizontalAdvance(text.toPlainText()) t_hei = fm.height() t_x = cur_block.pos().x() + cur_block.rect().size().width() t_y = b_bot + (b_top - b_bot - t_hei) / 2 text.setPos(t_x, t_y) else: # paint flow from hot utility b_x1 = self._map_x(self._block_width) b_x2 = cur_block.pos().x() b_y = cur_block.pos().y() + cur_block.rect().size().height() / 2 arrow = ArrowItem(b_x1, b_y, b_x2, b_y) scene.addItem(arrow) util_flow = heat_flow.at[idx, HFM.UTIL.name] text = scene.addText( self._heat_format.format( util_flow, self._heat_unit ), font=flow_font ) t_wid = fm.horizontalAdvance(text.toPlainText()) t_hei = fm.height() text.setPos((b_x2 - b_x1 - t_wid) / 2 + b_x1, b_y) idx += 1 # check if there is residual heat to be dumped into the cold utility last_flow = heat_flow.at[n_blocks - 1, HFM.OUT.name] if last_flow > 0: cur_block = int_blocks[-1] b_x1 = cur_block.pos().x() + cur_block.rect().size().width() b_x2 = self._map_x(w - self._block_width) b_y = cur_block.pos().y() + cur_block.rect().size().height() / 2 arrow = ArrowItem(b_x1, b_y, b_x2, b_y) scene.addItem(arrow) text = scene.addText( self._heat_format.format( last_flow, self._heat_unit ), font=flow_font) t_wid = fm.horizontalAdvance(text.toPlainText()) t_hei = fm.height() text.setPos((b_x2 - b_x1 - t_wid) / 2 + b_x1, b_y)
def paint(self, painter, option, index): """ Public method to paint the specified list item. @param painter painter object to paint to (QPainter) @param option style option used for painting (QStyleOptionViewItem) @param index model index of the item (QModelIndex) """ opt = QStyleOptionViewItem(option) self.initStyleOption(opt, index) widget = opt.widget style = widget.style() if widget is not None else QApplication.style() height = opt.rect.height() center = height // 2 + opt.rect.top() # Prepare title font titleFont = QFont(opt.font) titleFont.setBold(True) titleFont.setPointSize(titleFont.pointSize() + 1) titleMetrics = QFontMetrics(titleFont) if Globals.isWindowsPlatform(): colorRole = QPalette.Text else: colorRole = ( QPalette.HighlightedText if opt.state & QStyle.State_Selected else QPalette.Text ) leftPos = self.__padding rightPos = ( opt.rect.right() - self.__padding - GreaseMonkeyConfigurationListDelegate.RemoveIconSize ) # Draw background style.drawPrimitive(QStyle.PE_PanelItemViewItem, opt, painter, widget) # Draw checkbox checkBoxYPos = ( center - GreaseMonkeyConfigurationListDelegate.CheckBoxSize // 2 ) opt2 = QStyleOptionViewItem(opt) if opt2.checkState == Qt.Checked: opt2.state |= QStyle.State_On else: opt2.state |= QStyle.State_Off styleCheckBoxRect = style.subElementRect( QStyle.SE_ViewItemCheckIndicator, opt2, widget) opt2.rect = QRect( leftPos, checkBoxYPos, styleCheckBoxRect.width(), styleCheckBoxRect.height()) style.drawPrimitive(QStyle.PE_IndicatorViewItemCheck, opt2, painter, widget) leftPos = opt2.rect.right() + self.__padding # Draw icon iconYPos = center - GreaseMonkeyConfigurationListDelegate.IconSize // 2 iconRect = QRect(leftPos, iconYPos, GreaseMonkeyConfigurationListDelegate.IconSize, GreaseMonkeyConfigurationListDelegate.IconSize) pixmap = index.data(Qt.DecorationRole).pixmap( GreaseMonkeyConfigurationListDelegate.IconSize) painter.drawPixmap(iconRect, pixmap) leftPos = iconRect.right() + self.__padding # Draw script name name = index.data(Qt.DisplayRole) leftTitleEdge = leftPos + 2 rightTitleEdge = rightPos - self.__padding try: leftPosForVersion = ( titleMetrics.horizontalAdvance(name) + self.__padding ) except AttributeError: leftPosForVersion = titleMetrics.width(name) + self.__padding nameRect = QRect(leftTitleEdge, opt.rect.top() + self.__padding, rightTitleEdge - leftTitleEdge, titleMetrics.height()) painter.setFont(titleFont) style.drawItemText(painter, nameRect, Qt.AlignLeft, opt.palette, True, name, colorRole) # Draw version version = index.data(Qt.UserRole) versionRect = QRect( nameRect.x() + leftPosForVersion, nameRect.y(), rightTitleEdge - leftTitleEdge, titleMetrics.height()) versionFont = titleFont painter.setFont(versionFont) style.drawItemText(painter, versionRect, Qt.AlignLeft, opt.palette, True, version, colorRole) # Draw description infoYPos = nameRect.bottom() + opt.fontMetrics.leading() infoRect = QRect( nameRect.x(), infoYPos, nameRect.width(), opt.fontMetrics.height()) info = opt.fontMetrics.elidedText( index.data(Qt.UserRole + 1), Qt.ElideRight, infoRect.width()) painter.setFont(opt.font) style.drawItemText(painter, infoRect, Qt.AlignLeft | Qt.TextSingleLine, opt.palette, True, info, colorRole) # Draw remove button removeIconYPos = ( center - GreaseMonkeyConfigurationListDelegate.RemoveIconSize // 2 ) removeIconRect = QRect( rightPos, removeIconYPos, GreaseMonkeyConfigurationListDelegate.RemoveIconSize, GreaseMonkeyConfigurationListDelegate.RemoveIconSize) painter.drawPixmap(removeIconRect, self.__removePixmap)
def getTextWidth(text): font_metrics = QFontMetrics(QFont()) return font_metrics.horizontalAdvance(text)
def _paint_interval_blocks(self): scene = self w = scene.width() - (self._left_p + self._right_p) h = scene.height() - (self._top_p + self._bot_p) setup = self._setup summary = setup.summary n_blocks = len(summary) max_exheat = summary.loc[:, SFM.EXHEAT.name].abs().max() pen = QPen(Qt.black, 3, Qt.SolidLine, Qt.SquareCap, Qt.RoundJoin) # assume that block height and spacing between blocks is the same block_height = h / (2 * n_blocks - 1) block_width = self._block_width # measure minimum height for blocks block_font = QFont() block_font.setPointSize(12) fm = QFontMetrics(block_font) label_space = 5 # pixel spacing int_height = fm.height() heat_height = fm.height() label_height = int_height + heat_height + label_space minimum_block_height = label_height # set a minimum acceptable height (just in case) if block_height < minimum_block_height: block_height = minimum_block_height block_spacing = (h - n_blocks * block_height) / (n_blocks - 1) block_font.setPointSize(block_font.pointSize() - 2) else: block_spacing = block_height if np.isnan(self._setup.pinch): interval_pinch = None else: pinch_idx = summary.index[ summary[SFM.TOUT.name] == setup.pinch ].values.item() interval_pinch = summary.at[pinch_idx, SFM.INTERVAL.name] for i in range(n_blocks): block = scene.addRect(0, 0, block_width, block_height, pen=pen) block_h_s = (block_height + block_spacing) * i block.setPos( self._map_x((w - block_width) / 2), self._map_y(h - block_h_s) ) int_name = summary.at[i, SFM.INTERVAL.name] int_exheat = self._heat_format.format( summary.at[i, SFM.EXHEAT.name], self._heat_unit) int_label = scene.addText(int_name, block_font) int_ex_heat = scene.addText(int_exheat, block_font) int_width = fm.horizontalAdvance(int_label.toPlainText()) heat_width = fm.horizontalAdvance(int_ex_heat.toPlainText()) int_label.setPos( self._map_x((w - int_width) / 2), self._map_y( h - (block_h_s + (block_height - label_height) / 2) ) ) int_ex_heat.setPos( self._map_x((w - heat_width) / 2), self._map_y( h - (block_h_s + (block_height) / 2) ) ) # paint pinch line if there is one if interval_pinch is not None and int_name == interval_pinch: pinch_pen = QPen() pinch_pen.setWidth(3) pinch_pen.setDashPattern([10.0, 5.0]) line = scene.addLine( 10, 0, w - 2 * block_width - 10, 0, pinch_pen) line.setPos( self._map_x(block_width), self._map_y(h - block_h_s - 1.5 * block_spacing) ) text = scene.addText("Pinch") pinch_font = QFont() pinch_font.setBold(True) pinch_font.setPointSize(10) text.setFont(pinch_font) t_wid = fm.horizontalAdvance(text.toPlainText()) text.setPos( self._map_x((w - t_wid) / 2), self._map_y(h - block_h_s - 1.5 * block_spacing) ) self._blocks_tracker[int_name] = block