def excepthook(exc_type, exc_value, traceback_obj): # "redirect" stderr to an in memory buffer in order to capture output of sys.excepthook() for use in GUI message sys.stderr = _text_buffer _original_hook(exc_type, exc_value, traceback_obj) # This is for me using PyCharm. # It will cause the traceback to be printed in the "Run" window, # providing a clickable link to the offending line. print(_text_buffer.getvalue(), file=_original_stderr) # make traceback visible in GUI font = QFont("non-existent") font.setStyleHint(QFont.StyleHint.TypeWriter) error_box = QMessageBox() error_box.setFont(font) error_box.setIcon(QMessageBox.Critical) error_box.setWindowTitle( "Warning: Something Wicked This Way Comes...\t\t\t\t\t\t\t\t\t") error_box.setText("<h2>An unhandled exception occurred.</h2>") error_box.setInformativeText(_text_buffer.getvalue()) error_box.exec() # prevent accumulation of messages cluttering output _text_buffer.truncate(0) sys.stderr = _original_stderr
def __init__(self, engine, parent=None) -> None: super().__init__(parent) self._engine = engine self._path = "" self._icons = {} # type: Dict[str, Dict[str, QUrl]] self._deprecated_icons = {} # type: Dict[str, Dict[str, str]] self._images = {} # type: Dict[str, QUrl] # Workaround for incorrect default font on Windows if sys.platform == "win32": default_font = QFont() default_font.setPointSize(9) QCoreApplication.instance().setFont(default_font) self._em_height = int( QFontMetrics(QCoreApplication.instance().font()).ascent()) self._em_width = self._em_height # Cache the initial language in the preferences. For fonts, a special font can be defined with, for example, # "medium" and "medium_nl_NL". If the special one exists, getFont() will return that, otherwise the default # will be returned. We cache the initial language here is because Cura can only change its language if it gets # restarted, so we need to keep the fonts consistent in a single Cura run. self._preferences = UM.Application.Application.getInstance( ).getPreferences() self._lang_code = self._preferences.getValue("general/language") self._initializeDefaults() self._check_if_trusted = False self.reload()
def button(self): self.btn0 = QPushButton('Start', self) self.btn0.setGeometry(0, 30, 150, 70) self.btn0.setStyleSheet('background-color:green') self.btn0.setFont(QFont('san serif', 15)) self.btn1 = QPushButton('Stop', self) self.btn1.setGeometry(150, 30, 150, 70) self.btn1.setStyleSheet('background-color:grey') self.btn1.setFont(QFont('san serif', 15)) self.btn0.clicked.connect(self.clickButton0) self.btn1.clicked.connect(self.clickButton1)
def __init__(self, text, rect, parent=None): super().__init__(text, parent) self.setStyleSheet("color: white;") self.setGeometry(QRect(rect)) self.setAlignment(Qt.AlignmentFlag.AlignCenter) self.setWordWrap(True) self.font = QFont("Helvetica") self.font.setPixelSize(72) self.setFont(self.font) shadow = QGraphicsDropShadowEffect(self) shadow.setBlurRadius(40) shadow.setColor(QColor("black")) shadow.setOffset(3) self.setGraphicsEffect(shadow)
def __init__(self): super(Window, self).__init__() self.groupBox = QGroupBox( "What is your favorite programming Language ?") self.groupBox.setFont(QFont("Sanserif", 13)) self.checkBox1 = QCheckBox("Python") self.checkBox1.setIcon(QIcon("")) self.checkBox1.setWhatsThis("This is a checkbox of Python") self.checkBox2 = QCheckBox("C++") self.checkBox2.setIcon(QIcon("")) self.checkBox1.setWhatsThis("This is a checkbox of C++") self.checkBox3 = QCheckBox("Java") self.checkBox3.setIcon(QIcon("")) self.checkBox1.setWhatsThis("This is a checkbox of Java") self.label = QLabel("You Have Selected FootBall") self.title = " " self.left = 100 self.top = 200 self.width = 400 self.height = 300 self.InitWindow()
def setUpWindow(self): """Set up the dialog's widgets and layout.""" header_label = QLabel("""<p style='color:#65888C'> Welcome to Database Manager</p>""") header_label.setFont(QFont("Arial", 24)) header_label.setAlignment(Qt.AlignmentFlag.AlignCenter) self.info_label = QLabel("""<p style='color:#65888C'> Sign into your account.</p>""") self.info_label.setAlignment(Qt.AlignmentFlag.AlignHCenter) username_label = QLabel("Username:"******"Password:"******"Log In", QDialogButtonBox.ButtonRole.AcceptRole) button_box.accepted.connect(self.clickedLogInButton) log_in_grid = QGridLayout() log_in_grid.addWidget(header_label, 0, 0, 1, 3, Qt.AlignmentFlag.AlignCenter) log_in_grid.addWidget(self.info_label, 1, 0, 1, 3, Qt.AlignmentFlag.AlignCenter) log_in_grid.addWidget(username_label, 2, 0) log_in_grid.addWidget(self.username_line, 2, 1) log_in_grid.addWidget(password_label, 3, 0) log_in_grid.addWidget(self.password_line, 3, 1) log_in_grid.addWidget(button_box, 4, 1) self.setLayout(log_in_grid)
def addMainApp(self): self.lineNumberedTextEdit = LineNumberedTextEdit() self.textEdit = self.lineNumberedTextEdit.getTextEdit() font = QFont() font.setStyleHint(QFont().StyleHint.Monospace) font.setFamily('monospace') self.textEdit.setFont(font) self.setCentralWidget(self.lineNumberedTextEdit)
def __init__(self, game, parent=None): super().__init__(game, parent) self.question_label.setVisible(False) if self.parent().alex: self.answer_label.setVisible(False) self.dd_label = QuestionLabel("DAILY<br/>DOUBLE!", self.qurect, self) self.dd_label.setFont(QFont("Helvetica", 140)) self.dd_label.setVisible(True) self.update()
def getFont(self, font_name: str) -> QFont: lang_specific_font_name = "%s_%s" % (font_name, self._lang_code) if lang_specific_font_name in self._fonts: return self._fonts[lang_specific_font_name] if font_name in self._fonts: return self._fonts[font_name] Logger.log("w", "No font %s defined in Theme", font_name) return QFont()
def __init__(self): super().__init__() self.setWindowTitle('LazyDictionary') self.setWindowIcon(QIcon('book.png')) self.setFixedHeight(100) self.setFixedWidth(300) self.label = QLabel('word count: 0', self) self.label.setFont(QFont('san serif', 15)) self.label.move(90, 0) self.button() self.oneClick = True
def data(self, index, role): """Handles how the the items are displayed in the table using roles.""" if index.isValid(): # data is the text displayed for every index in the table data = self.data[index.row()][index.column()] if role == Qt.ItemDataRole.DisplayRole: return data # Demonstrates how to set bold text for a specific column if role == Qt.ItemDataRole.FontRole and index.column() == 0: bold_font = QFont() bold_font.setBold(True) return bold_font # Demonstrates how to set the background color in order to highlight # specific cells that contain desired values if role == Qt.ItemDataRole.BackgroundRole and "Brown Trout" in data: blue_bg = QBrush(QColor("#6EEEF8")) return blue_bg
def initUI(self): QToolTip.setFont(QFont('SansSerif', 10)) self.setToolTip('This is a <b>QWidget</b> widget') btn = QPushButton('Button', self) btn.setToolTip('This is a <b>QPushButton</b> widget') btn.resize(btn.sizeHint()) btn.move(50, 50) self.setGeometry(300, 300, 300, 200) self.setWindowTitle('Tooltips') self.show()
def __init__(self, host): QMainWindow.__init__(self) self.setAttribute(Qt.WidgetAttribute.WA_DeleteOnClose) screen = QGuiApplication.screens()[1] screen_width = screen.size().width() display_width = int(0.7 * screen_width) display_height = int(0.2 * display_width) font_size = int(0.06 * display_width) self.setWindowFlags(Qt.WindowType.WindowStaysOnTopHint | Qt.WindowType.FramelessWindowHint | Qt.WindowType.X11BypassWindowManagerHint) self.setGeometry( QStyle.alignedRect( Qt.LayoutDirection.LeftToRight, Qt.AlignmentFlag.AlignCenter, QSize(display_width, display_height), screen.geometry(), )) font = QFont() font.setPointSize(font_size) self.label = QLabel("http://" + host, self) self.label.setGeometry(self.rect() - QMargins(0, 0, 0, self.rect().height() // 2)) self.label.setAlignment(Qt.AlignmentFlag.AlignCenter) self.label.setFont(font) self.playerview = PlayerView(self.rect() - QMargins(0, self.rect().height() // 2, 0, 0), fontsize=OVERLAYFONTSIZE, parent=self) self.show()
def drawWidget(self, qp): MAX_CAPACITY = 700 OVER_CAPACITY = 750 font = QFont('Serif', 7, QFont.Weight.Light) qp.setFont(font) size = self.size() w = size.width() h = size.height() step = int(round(w / 10)) till = int(((w / OVER_CAPACITY) * self.value)) full = int(((w / OVER_CAPACITY) * MAX_CAPACITY)) if self.value >= MAX_CAPACITY: qp.setPen(QColor(255, 255, 255)) qp.setBrush(QColor(255, 255, 184)) qp.drawRect(0, 0, full, h) qp.setPen(QColor(255, 175, 175)) qp.setBrush(QColor(255, 175, 175)) qp.drawRect(full, 0, till - full, h) else: qp.setPen(QColor(255, 255, 255)) qp.setBrush(QColor(255, 255, 184)) qp.drawRect(0, 0, till, h) pen = QPen(QColor(20, 20, 20), 1, Qt.PenStyle.SolidLine) qp.setPen(pen) qp.setBrush(Qt.BrushStyle.NoBrush) qp.drawRect(0, 0, w - 1, h - 1) j = 0 for i in range(step, 10 * step, step): qp.drawLine(i, 0, i, 5) metrics = qp.fontMetrics() fw = metrics.horizontalAdvance(str(self.num[j])) x, y = int(i - fw / 2), int(h / 2) qp.drawText(x, y, str(self.num[j])) j = j + 1
def __init__(self, parent=None, window=None): """Construct Dialog Box. kwargs: parent (QWidget, optional) Parent widget object. Defaults to None. window (QWidget, optional) Program's MainWindow. Defaults to None. """ super().__init__(parent=parent) self.window = window font = QFont() font2 = QFont() font.setPointSize(11) font2.setPointSize(20) fixed = QSizePolicy.Policy.Fixed sizePolicy = QSizePolicy(fixed, fixed) self.resize(365, 229) self.setWindowTitle("About") self.setObjectName("aboutBox") self.setGeometry(QRect(180, 190, 171, 32)) self.setSizePolicy(sizePolicy) self.label = QLabel(self) self.label_2 = QLabel(self) self.label_3 = QLabel(self) self.label_4 = QLabel(self) self.label_5 = QLabel(self) self.label_6 = QLabel(self) self.label.setGeometry(QRect(20, 10, 161, 51)) self.label_2.setGeometry(QRect(150, 30, 49, 16)) self.label_3.setGeometry(QRect(20, 80, 211, 16)) self.label_4.setGeometry(QRect(20, 160, 201, 20)) self.label_5.setGeometry(QRect(20, 120, 341, 41)) self.label_6.setGeometry(QRect(20, 110, 121, 16)) self.label.setFont(font2) self.label_3.setFont(font) self.label_5.setFont(font) self.label_6.setFont(font) self.label.setText("BlackJack") self.label_2.setText("v 0.3") self.label_3.setText("Copyright 2021 AlexPdev Inc.") self.label_4.setText("https://fsf.org/") self.label_5.setText("License GNU LESSER GENERAL PUBLIC LICENSE") self.label_6.setText("Creator AlexPdev") self.button = QPushButton("Ok", parent=self) self.button.pressed.connect(self.okbutton)
def __init__(self): super(Window, self).__init__() self.groupBox = QGroupBox( "What is your favorite programming Language ?") self.groupBox.setFont(QFont("Sanserif", 13)) self.lineEdit = QLineEdit() self.label = QLabel("You input string is :") self.title = " " self.left = 100 self.top = 200 self.width = 400 self.height = 300 self.InitWindow()
def __init__(self): super().__init__() self.setFixedWidth(400) self.setFixedHeight(300) self.setWindowTitle('Clean Freezerworks Export File') font = QFont() font.setFamily('Consolas') font.setPointSize(16) self.label = QLabel(self) self.label.setFont(font) self.label.setText( 'This is a test to see if the font style works or not!')
def main(): app = QApplication(sys.argv) font = QFont("Courier", 15) app.setFont(font) ex = AbacusWalletBridge() sys.exit(app.exec())
import abc from PyQt6.QtCore import Qt from PyQt6.QtGui import QFont # fonts from PyQt6.QtWidgets import QWidget, QVBoxLayout, QLabel, QScrollArea, QFrame HEADER_FONT = QFont("Segoe UI", pointSize=20, weight=QFont.Weight.Bold) SUBHEADER_FONT = QFont("Segoe UI", pointSize=14, weight=QFont.Weight.DemiBold) LABEL_FONT = QFont("Segoe UI", pointSize=11) LABEL_FONT_BOLD = QFont("Segoe UI", pointSize=11, weight=QFont.Weight.Bold) LABEL_FONT_ITALIC = QFont("Segoe UI", pointSize=11, italic=True) CODE_FONT = QFont("Consolas", pointSize=12) CODE_FONT_BOLD = QFont("Consolas", pointSize=12, weight=QFont.Weight.Bold) MENU_FONT = QFont("Segoe UI", pointSize=11) STATUS_BAR_FONT = QFont("Segoe UI", pointSize=11) BUTTON_FONT = QFont("Segoe UI", pointSize=11) class MainWindowContent(QWidget): def __init__(self, main_window, header_text): super(MainWindowContent, self).__init__() self.main_window = main_window self.layout = QVBoxLayout(self) self.layout.setContentsMargins(10, 5, 10, 5) self.layout.setAlignment(Qt.AlignmentFlag.AlignTop) self.layout.setSpacing(20) self.header = QLabel(header_text) self.header.setFont(HEADER_FONT)
def drawText(self, event, qp): qp.setPen(QColor(168, 34, 3)) qp.setFont(QFont('Decorative', 10)) qp.drawText(event.rect(), Qt.Alignment.AlignCenter, self.text)
def load(self, path: str, is_first_call: bool = True) -> None: if path == self._path: return theme_full_path = os.path.join(path, "theme.json") Logger.log( "d", "Loading theme file: {theme_full_path}".format( theme_full_path=theme_full_path)) try: with open(theme_full_path, encoding="utf-8") as f: data = json.load(f) except EnvironmentError as e: Logger.error( "Unable to load theme file at {theme_full_path}: {err}".format( theme_full_path=theme_full_path, err=e)) return except UnicodeDecodeError: Logger.error( "Theme file at {theme_full_path} is corrupt (invalid UTF-8 bytes)." .format(theme_full_path=theme_full_path)) return except json.JSONDecodeError: Logger.error( "Theme file at {theme_full_path} is corrupt (invalid JSON syntax)." .format(theme_full_path=theme_full_path)) return # Iteratively load inherited themes try: theme_id = data["metadata"]["inherits"] self.load(Resources.getPath(Resources.Themes, theme_id), is_first_call=False) except FileNotFoundError: Logger.log("e", "Could not find inherited theme %s", theme_id) except KeyError: pass # No metadata or no inherits keyword in the theme.json file if "colors" in data: for name, value in data["colors"].items(): if not is_first_call and isinstance(value, str): # Keep parent theme string colors as strings and parse later self._colors[name] = value continue if isinstance(value, str) and is_first_call: # value is reference to base_colors color name try: color = data["base_colors"][value] except IndexError: Logger.log( "w", "Colour {value} could not be found in base_colors". format(value=value)) continue else: color = value try: c = QColor(color[0], color[1], color[2], color[3]) except IndexError: # Color doesn't have enough components. Logger.log( "w", "Colour {name} doesn't have enough components. Need to have 4, but had {num_components}." .format(name=name, num_components=len(color))) continue # Skip this one then. self._colors[name] = c if "base_colors" in data: for name, color in data["base_colors"].items(): try: c = QColor(color[0], color[1], color[2], color[3]) except IndexError: # Color doesn't have enough components. Logger.log( "w", "Colour {name} doesn't have enough components. Need to have 4, but had {num_components}." .format(name=name, num_components=len(color))) continue # Skip this one then. self._colors[name] = c if is_first_call and self._colors: #Convert all string value colors to their referenced color for name, color in self._colors.items(): if isinstance(color, str): try: c = self._colors[color] self._colors[name] = c except: Logger.log( "w", "Colour {name} {color} does".format(name=name, color=color)) fonts_dir = os.path.join(path, "fonts") if os.path.isdir(fonts_dir): for root, dirnames, filenames in os.walk(fonts_dir): for filename in filenames: if filename.lower().endswith(".ttf"): QFontDatabase.addApplicationFont( os.path.join(root, filename)) if "fonts" in data: system_font_size = QCoreApplication.instance().font().pointSize() for name, font in data["fonts"].items(): q_font = QFont() q_font.setFamily( font.get("family", QCoreApplication.instance().font().family())) if font.get("bold"): q_font.setBold(font.get("bold", False)) else: q_font.setWeight(font.get("weight", 500)) q_font.setLetterSpacing(QFont.SpacingType.AbsoluteSpacing, font.get("letterSpacing", 0)) q_font.setItalic(font.get("italic", False)) q_font.setPointSize(int( font.get("size", 1) * system_font_size)) q_font.setCapitalization(QFont.Capitalization.AllUppercase if font.get("capitalize", False) else QFont.Capitalization.MixedCase) self._fonts[name] = q_font if "sizes" in data: for name, size in data["sizes"].items(): s = QSizeF() s.setWidth(round(size[0] * self._em_width)) s.setHeight(round(size[1] * self._em_height)) self._sizes[name] = s iconsdir = os.path.join(path, "icons") if os.path.isdir(iconsdir): try: for base_path, _, icons in os.walk(iconsdir): detail_level = base_path.split(os.sep)[-1] if detail_level not in self._icons: self._icons[detail_level] = {} for icon in icons: name = os.path.splitext(icon)[0] self._icons[detail_level][name] = QUrl.fromLocalFile( os.path.join(base_path, icon)) except EnvironmentError as err: # Exception when calling os.walk, e.g. no access rights. Logger.error( f"Can't access icons of theme ({iconsdir}): {err}") # Won't get any icons then. Images will show as black squares. deprecated_icons_file = os.path.join(iconsdir, "deprecated_icons.json") if os.path.isfile(deprecated_icons_file): try: with open(deprecated_icons_file, encoding="utf-8") as f: data = json.load(f) for icon in data: self._deprecated_icons[icon] = data[icon] except (UnicodeDecodeError, json.decoder.JSONDecodeError, EnvironmentError): Logger.logException( "w", "Could not parse deprecated icons list %s", deprecated_icons_file) imagesdir = os.path.join(path, "images") if os.path.isdir(imagesdir): try: for image in os.listdir(imagesdir): name = os.path.splitext(image)[0] self._images[name] = QUrl.fromLocalFile( os.path.join(imagesdir, image)) except EnvironmentError as err: # Exception when calling os.listdir, e.g. no access rights. Logger.error( f"Can't access image of theme ({imagesdir}): {err}") # Won't get any images then. They will show as black squares. Logger.log("d", "Loaded theme %s", path) Logger.info(f"System's em size is {self._em_height}px.") self._path = path # only emit the theme loaded signal once after all the themes in the inheritance chain have been loaded if is_first_call: self.themeLoaded.emit()
def generate_itemGroup(self, xs, ys, label, type): gItemGroup = QGraphicsItemGroup() pointBbx = QRectF() pointBbx.setSize(QSizeF(self.gView.labelSize, self.gView.labelSize)) textLabel = QGraphicsTextItem(label) if len(xs) == 1: pointBbx.moveCenter(QPointF(xs[0], ys[0])) textLabel.setPos(xs[0] - (textLabel.boundingRect().width() / 2), ys[0] - (textLabel.boundingRect().height() / 2)) pointShape = QGraphicsEllipseItem(pointBbx) shapeColor = Qt.GlobalColor.white textColor = Qt.GlobalColor.black tooltip = 'P{}:{}' elif len(xs) == 2: pointBbx.moveCenter(QPointF(xs[1], ys[1])) textLabel.setPos(xs[1] - (textLabel.boundingRect().width() / 2), ys[1] - (textLabel.boundingRect().height() / 2)) r, g, b = np.random.choice(range(256), size=3) line_item = QGraphicsLineItem(xs[0], ys[0], xs[1], ys[1]) line_item.setPen( QPen(QColor(r, g, b, 128), self.gView.labelSize / 6)) gItemGroup.addToGroup(line_item) # line_end = QGraphicsEllipseItem(xs[1], ys[1], # int(self.gView.labelSize/3), int(self.gView.labelSize/3)) # line_end.setPen(QPen(QColor(r, g, b), 0.5)) # line_end.setBrush(QBrush(QColor(r, g, b))) # gItemGroup.addToGroup(line_end) pointShape = QGraphicsEllipseItem(pointBbx) shapeColor = QColor(r, g, b, 128) textColor = Qt.GlobalColor.black tooltip = 'L{}:{}' # textLabel.setRotation(np.arctan((ys[1] - ys[0])/(xs[1] - xs[0]))*(180/3.14)) else: pointBbx.moveCenter(QPointF(np.mean(xs), np.mean(ys))) textLabel.setPos( np.mean(xs) - (textLabel.boundingRect().width() / 2), np.mean(ys) - (textLabel.boundingRect().height() / 2)) points = [QPointF(x, y) for x, y in zip(xs, ys)] polygon = QPolygonF(points) r, g, b = np.random.choice(range(256), size=3) zone_item = QGraphicsPolygonItem(polygon) zone_item.setPen(QPen(QColor(r, g, b), self.gView.labelSize / 10)) zone_item.setBrush(QBrush(QColor(r, g, b, 40))) gItemGroup.addToGroup(zone_item) pointShape = QGraphicsRectItem(pointBbx) shapeColor = Qt.GlobalColor.darkBlue textColor = Qt.GlobalColor.white tooltip = 'Z{}:{}' pointShape.setPen(QPen(Qt.GlobalColor.white, 0.5)) pointShape.setBrush(QBrush(shapeColor)) # self.gView.scene().addEllipse(pointBbx, QPen(Qt.white, 0.5), QBrush(Qt.black)) gItemGroup.setToolTip(tooltip.format(label, type)) gItemGroup.addToGroup(pointShape) labelFont = QFont() labelFont.setPointSize(round(self.gView.labelSize / 2)) labelFont.setBold(True) textLabel.setFont(labelFont) textLabel.setDefaultTextColor(textColor) gItemGroup.addToGroup(textLabel) return gItemGroup
class TabTree(QTreeWidget): tab_activated = pyqtSignal(object) tab_close_requested = pyqtSignal(object) delete_tabs = pyqtSignal(object) def __init__(self, parent): QTreeWidget.__init__(self, parent) self.deleted_parent_map = {} pal = self.palette() pal.setColor(QPalette.ColorRole.Highlight, pal.color(QPalette.ColorRole.Base)) pal.setColor(QPalette.ColorRole.HighlightedText, pal.color(QPalette.ColorRole.Text)) self.setPalette(pal) self.setStyleSheet(''' QTreeView { background: BG; color: FG; border: none; } QTreeView::item { border: 1px solid transparent; padding-top:0.5ex; padding-bottom:0.5ex; } QTreeView::item:hover { background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 GS, stop: 1 GE); border: 1px solid BC; border-radius: 6px; } QTreeView::branch { background: BG; } QTreeView::branch:has-children:!has-siblings:closed, QTreeView::branch:closed:has-children:has-siblings { image: url(CLOSED); } QTreeView::branch:open:has-children:!has-siblings, QTreeView::branch:open:has-children:has-siblings { image: url(OPEN); } '''.replace( 'CLOSED', get_data_as_path('images/tree-closed.svg')).replace( 'OPEN', get_data_as_path('images/tree-open.svg')).replace( 'BG', color('tab tree background', 'palette(window)')).replace( 'FG', color('tab tree foreground', 'palette(window-text)')).replace( 'GS', color( 'tab tree hover gradient start', '#e7effd')).replace( 'GE', color( 'tab tree hover gradient end', '#cbdaf1')).replace( 'BC', color( 'tab tree hover border', '#bfcde4'))) self.setIconSize(QSize(ICON_SIZE, ICON_SIZE)) self.setAutoScrollMargin(ICON_SIZE * 2) self.setAnimated(True) self.setHeaderHidden(True) self.setSelectionMode(QAbstractItemView.SelectionMode.SingleSelection) self.setDragEnabled(True) self.viewport().setAcceptDrops(True) self.setDropIndicatorShown(True) self.setDragDropMode(QAbstractItemView.DragDropMode.InternalMove) self.setDefaultDropAction(Qt.DropAction.MoveAction) self.invisibleRootItem().setFlags(Qt.ItemFlag.ItemIsDragEnabled | Qt.ItemFlag.ItemIsDropEnabled | self.invisibleRootItem().flags()) self.itemClicked.connect(self.item_clicked) self.current_item = None self.emphasis_font = QFont(self.font()) self.emphasis_font.setItalic(True) self.setFocusPolicy(Qt.FocusPolicy.NoFocus) self.loading_items = set() self.delegate = TabDelegate(self) self.setItemDelegate(self.delegate) self.loading_animation_timer = t = QTimer(self) t.setInterval(1000 // 60) t.timeout.connect(self.repaint_loading_items) self.setMouseTracking(True) self._last_item = lambda: None self.itemEntered.connect(self.item_entered) self.setCursor(Qt.CursorShape.PointingHandCursor) self.viewport().installEventFilter(self) self.setContextMenuPolicy(Qt.ContextMenuPolicy.CustomContextMenu) self.customContextMenuRequested.connect(self.show_context_menu) def item_entered(self, item, col): item.set_data(HOVER_ROLE, True) def show_context_menu(self, pos): item = self.itemAt(pos) if not item: return m = QMenu(self) m.addAction(_('Close tabs to the bottom'), partial(self.close_tabs_to_bottom, item)) m.addAction(_('Close other tabs'), partial(self.close_other_tabs, item)) m.addAction(_('Close this tree'), partial(self.close_tree, item)) m.exec(self.mapToGlobal(pos)) def close_tabs_to_bottom(self, item_or_tab): item = item_or_tab if isinstance( item_or_tab, TabItem) else self.item_for_tab(item_or_tab) if item: tabs_to_delete = [] found_self = False for i in tuple(self): found_self = found_self or i is item if found_self: parent = i.parent() or self.invisibleRootItem() self.deleted_parent_map[i.view_id] = (getattr( parent, 'view_id', -1), parent.indexOfChild(i)) parent.removeChild(i) tabs_to_delete.append(i.tab) self.delete_tabs.emit(tuple(filter(None, tabs_to_delete))) def close_other_tabs(self, item_or_tab): item = item_or_tab if isinstance( item_or_tab, TabItem) else self.item_for_tab(item_or_tab) if item: tabs_to_delete = [] keep_children = not item.isExpanded() for i in tuple(self): if i is not item and (not keep_children or not i.has_ancestor(item)): p = i.parent() or self.invisibleRootItem() self.deleted_parent_map[i.view_id] = (getattr( p, 'view_id', -1), p.indexOfChild(i)) p.removeChild(i) tabs_to_delete.append(i.tab) p = (item.parent() or self.invisibleRootItem()) self.deleted_parent_map[item.view_id] = (getattr(p, 'view_id', -1), p.indexOfChild(item)) p.removeChild(item) self.addTopLevelItem(item) self.delete_tabs.emit(tuple(filter(None, tabs_to_delete))) def close_tree(self, item_or_tab): item = item_or_tab if isinstance( item_or_tab, TabItem) else self.item_for_tab(item_or_tab) if item: p = (item.parent() or self.invisibleRootItem()) self.deleted_parent_map[item.view_id] = (getattr(p, 'view_id', -1), p.indexOfChild(item)) p.removeChild(item) tabs_to_delete = [item.tab] for i in tuple(item): p = i.parent() self.deleted_parent_map[i.view_id] = (getattr( p, 'view_id', -1), p.indexOfChild(i)) p.removeChild(i) tabs_to_delete.append(i.tab) self.delete_tabs.emit(tuple(filter(None, tabs_to_delete))) def eventFilter(self, widget, event): if widget is self.viewport(): etype = event.type() item = last_item = self._last_item() if etype == QEvent.Type.MouseMove: pos = event.pos() item = self.itemAt(pos) if item is not None: item.setData(0, CLOSE_HOVER_ROLE, self.over_close(item, pos)) elif etype == QEvent.Type.Leave: item = None if item is not last_item: if last_item is not None: last_item.set_data(HOVER_ROLE, False) last_item.set_data(CLOSE_HOVER_ROLE, False) self._last_item = ( lambda: None) if item is None else weakref.ref(item) return QTreeWidget.eventFilter(self, widget, event) def over_close(self, item, pos): rect = self.visualItemRect(item) rect.setLeft(rect.right() - rect.height()) return rect.contains(pos) def mouseReleaseEvent(self, ev): if ev.button() == Qt.MouseButton.LeftButton: item = self.itemAt(ev.pos()) if item is not None: if self.over_close(item, ev.pos()): tab = item.tabref() if tab is not None: self.tab_close_requested.emit(tab) ev.accept() return return QTreeWidget.mouseReleaseEvent(self, ev) def __iter__(self): for i in range(self.topLevelItemCount()): item = self.topLevelItem(i) if isinstance(item, TabItem): yield item yield from item def item_for_tab(self, tab): for q in self: if q.tab is tab: return q def add_tab(self, tab, parent=None): i = TabItem(tab, self.loading_status_changed) if parent is None: self.addTopLevelItem(i) else: self.item_for_tab(parent).addChild(i) self.scrollToItem(i) def undelete_tab(self, tab, stab): old_tab_id = stab['view_id'] parent_id, pos = self.deleted_parent_map.pop(old_tab_id, (None, None)) parent = self.invisibleRootItem() item = self.item_for_tab(tab) if parent_id is not None and parent_id >= 0: for q in self: if q.view_id == parent_id: parent = q break (item.parent() or self.invisibleRootItem()).removeChild(item) if pos > -1 and pos < parent.childCount(): parent.insertChild(pos, item) else: parent.addChild(item) self.scrollToItem(item) def replace_view_in_tab(self, tab, replacement): item = self.item_for_tab(tab) if item is not None: item.set_view(replacement) def remove_tab(self, tab): item = self.item_for_tab(tab) closing_current_tab = item is self.current_item children_to_close = () if item is not None: p = item.parent() or self.invisibleRootItem() if item.isExpanded(): if closing_current_tab: self.next_tab(wrap=False) surviving_children = tuple(item.takeChildren()) if surviving_children: p.insertChild(p.indexOfChild(item), surviving_children[0]) tuple( map(surviving_children[0].addChild, surviving_children[1:])) surviving_children[0].setExpanded(True) else: children_to_close = tuple(i.tab for i in item.takeChildren()) if closing_current_tab: self.next_tab(wrap=False) self.deleted_parent_map[item.view_id] = (getattr(p, 'view_id', -1), p.indexOfChild(item)) p.removeChild(item) return children_to_close + (tab, ) def loading_status_changed(self, item, loading): if loading: self.loading_items.add(item) # this is disabled as it causes loading to become very slow # when many tabs are loading, this happens even if the delegate # paint() method does nothing. On the other hand if # repaint_loading_items() does not call set_data there is no # performance impact, so is a Qt bug of some kind. if False: self.loading_animation_timer.start() else: item.set_data(LOADING_ROLE, 1) else: self.loading_items.discard(item) item.set_data(LOADING_ROLE, 0) if not self.loading_items: self.loading_animation_timer.stop() def repaint_loading_items(self): n = self.delegate.next_loading_frame() for item in self.loading_items: item.set_data(LOADING_ROLE, n + 2) def item_clicked(self, item, column): if item is not None: tab = item.tab if tab is not None: self.tab_activated.emit(item.tab) def _activate_item(self, item, tab, expand=True): self.scrollToItem(item) self.tab_activated.emit(item.tab) if expand and not item.isExpanded(): item.setExpanded(True) def item_for_text(self, text): text = text.strip() for item in self: tab = item.tab if tab is not None and item.data(0, DISPLAY_ROLE).strip() == text: return item def activate_tab(self, text): item = self.item_for_text(text) if item is not None: self._activate_item(item, item.tab) return True def next_tab(self, forward=True, wrap=True): tabs = self if forward else reversed(tuple(self)) found = self.current_item is None item = None for item in tabs: tab = item.tab if found and tab is not None: self._activate_item(item, tab) return True if self.current_item == item: found = True if wrap: tabs = self if forward else reversed(tuple(self)) else: tabs = reversed(tuple(self)) if forward else self for item in tabs: tab = item.tab if tab is not None and item is not self.current_item: self._activate_item(item, tab) return True return False def current_changed(self, tab): if self.current_item is not None: self.current_item.set_data(Qt.ItemDataRole.FontRole, None) self.current_item = None item = self.item_for_tab(tab) if item is not None: self.current_item = item item.set_data(Qt.ItemDataRole.FontRole, self.emphasis_font) def mark_tabs(self, unmark=False): for item in self: item.set_data(MARK_ROLE, None) if not unmark: names = iter(mark_map) item = self.topLevelItem(0) while item is not None: item.set_data(MARK_ROLE, next(names)) item = self.itemBelow(item) def activate_marked_tab(self, key): m = mark_rmap.get(key.toCombined()) if m is None: return False for item in self: if item.data(0, MARK_ROLE) == m: tab = item.tab if tab is not None: self._activate_item(item, tab) return True return False def serialize_state(self): ans = {'children': []} def process_node(node, sparent=ans): for child in (node.child(i) for i in range(node.childCount())): view_id = getattr(child, 'view_id', -1) if view_id > -1: sparent['children'].append({ 'view_id': view_id, 'is_expanded': child.isExpanded(), 'children': [] }) process_node(child, sparent['children'][-1]) process_node(self.invisibleRootItem()) return ans def unserialize_state(self, state, tab): self.item_for_tab(tab).setExpanded(state['is_expanded'])
def __init__(self, parent): QTreeWidget.__init__(self, parent) self.deleted_parent_map = {} pal = self.palette() pal.setColor(QPalette.ColorRole.Highlight, pal.color(QPalette.ColorRole.Base)) pal.setColor(QPalette.ColorRole.HighlightedText, pal.color(QPalette.ColorRole.Text)) self.setPalette(pal) self.setStyleSheet(''' QTreeView { background: BG; color: FG; border: none; } QTreeView::item { border: 1px solid transparent; padding-top:0.5ex; padding-bottom:0.5ex; } QTreeView::item:hover { background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 GS, stop: 1 GE); border: 1px solid BC; border-radius: 6px; } QTreeView::branch { background: BG; } QTreeView::branch:has-children:!has-siblings:closed, QTreeView::branch:closed:has-children:has-siblings { image: url(CLOSED); } QTreeView::branch:open:has-children:!has-siblings, QTreeView::branch:open:has-children:has-siblings { image: url(OPEN); } '''.replace( 'CLOSED', get_data_as_path('images/tree-closed.svg')).replace( 'OPEN', get_data_as_path('images/tree-open.svg')).replace( 'BG', color('tab tree background', 'palette(window)')).replace( 'FG', color('tab tree foreground', 'palette(window-text)')).replace( 'GS', color( 'tab tree hover gradient start', '#e7effd')).replace( 'GE', color( 'tab tree hover gradient end', '#cbdaf1')).replace( 'BC', color( 'tab tree hover border', '#bfcde4'))) self.setIconSize(QSize(ICON_SIZE, ICON_SIZE)) self.setAutoScrollMargin(ICON_SIZE * 2) self.setAnimated(True) self.setHeaderHidden(True) self.setSelectionMode(QAbstractItemView.SelectionMode.SingleSelection) self.setDragEnabled(True) self.viewport().setAcceptDrops(True) self.setDropIndicatorShown(True) self.setDragDropMode(QAbstractItemView.DragDropMode.InternalMove) self.setDefaultDropAction(Qt.DropAction.MoveAction) self.invisibleRootItem().setFlags(Qt.ItemFlag.ItemIsDragEnabled | Qt.ItemFlag.ItemIsDropEnabled | self.invisibleRootItem().flags()) self.itemClicked.connect(self.item_clicked) self.current_item = None self.emphasis_font = QFont(self.font()) self.emphasis_font.setItalic(True) self.setFocusPolicy(Qt.FocusPolicy.NoFocus) self.loading_items = set() self.delegate = TabDelegate(self) self.setItemDelegate(self.delegate) self.loading_animation_timer = t = QTimer(self) t.setInterval(1000 // 60) t.timeout.connect(self.repaint_loading_items) self.setMouseTracking(True) self._last_item = lambda: None self.itemEntered.connect(self.item_entered) self.setCursor(Qt.CursorShape.PointingHandCursor) self.viewport().installEventFilter(self) self.setContextMenuPolicy(Qt.ContextMenuPolicy.CustomContextMenu) self.customContextMenuRequested.connect(self.show_context_menu)
def test_unknownFont(theme): assert theme.getFont("whatever") == QFont()
window_size = 500 n = 8 # even integer CELLRATIO = 3 / 5 FONTSIZE = 10 BLUE = QColor("#031591") YELLOW = QColor("#ffcc00") RED = QColor("#ff0000") BLACK = QColor("#000000") GREY = QColor("#505050") WHITE = QColor("#ffffff") GREEN = QColor("#33cc33") BOARDSIZE = (6, 6) CATFONT = QFont() CATFONT.setBold(True) CATFONT.setPixelSize(24) CATPEN = QPen(WHITE) MONFONT = QFont(CATFONT) MONFONT.setPixelSize(50) MONPEN = QPen(YELLOW) TEXTPADDING = 20 QUFONT = QFont() QUFONT.setPixelSize(70) QUMARGIN = 50 NAMEHEIGHT = 50 NAMEFONT = QFont()
def __init__(self, *args, **kwargs): super(MainWindow, self).__init__(*args, **kwargs) layout = QVBoxLayout() self.editor = TextEdit() self.editor.setAutoFormatting(QTextEdit.AutoFormatting.AutoAll) self.editor.selectionChanged.connect(self.update_format) font = QFont("Times", 12) self.editor.setFont(font) self.editor.setFontPointSize(12) self.path = None layout.addWidget(self.editor) container = QWidget() container.setLayout(layout) self.setCentralWidget(container) self.status = QStatusBar() self.setStatusBar(self.status) file_toolbar = QToolBar("File") file_toolbar.setIconSize(QSize(14, 14)) self.addToolBar(file_toolbar) file_menu = self.menuBar().addMenu("&File") open_file_action = QAction( QIcon(os.path.join("images", "blue-folder-open-document.png")), "Open file...", self, ) open_file_action.setStatusTip("Open file") open_file_action.triggered.connect(self.file_open) file_menu.addAction(open_file_action) file_toolbar.addAction(open_file_action) save_file_action = QAction(QIcon(os.path.join("images", "disk.png")), "Save", self) save_file_action.setStatusTip("Save current page") save_file_action.triggered.connect(self.file_save) file_menu.addAction(save_file_action) file_toolbar.addAction(save_file_action) save_as_file_action = QAction( QIcon(os.path.join("images", "disk--pencil.png")), "Save As...", self) save_as_file_action.setStatusTip("Save current page to specified file") save_as_file_action.triggered.connect(self.file_save_as) file_menu.addAction(save_as_file_action) file_toolbar.addAction(save_as_file_action) print_action = QAction(QIcon(os.path.join("images", "printer.png")), "Print...", self) print_action.setStatusTip("Print current page") print_action.triggered.connect(self.file_print) file_menu.addAction(print_action) file_toolbar.addAction(print_action) edit_toolbar = QToolBar("Edit") edit_toolbar.setIconSize(QSize(16, 16)) self.addToolBar(edit_toolbar) edit_menu = self.menuBar().addMenu("&Edit") undo_action = QAction( QIcon(os.path.join("images", "arrow-curve-180-left.png")), "Undo", self) undo_action.setStatusTip("Undo last change") undo_action.triggered.connect(self.editor.undo) edit_menu.addAction(undo_action) redo_action = QAction(QIcon(os.path.join("images", "arrow-curve.png")), "Redo", self) redo_action.setStatusTip("Redo last change") redo_action.triggered.connect(self.editor.redo) edit_toolbar.addAction(redo_action) edit_menu.addAction(redo_action) edit_menu.addSeparator() cut_action = QAction(QIcon(os.path.join("images", "scissors.png")), "Cut", self) cut_action.setStatusTip("Cut selected text") cut_action.setShortcut(QKeySequence.StandardKey.Cut) cut_action.triggered.connect(self.editor.cut) edit_toolbar.addAction(cut_action) edit_menu.addAction(cut_action) copy_action = QAction( QIcon(os.path.join("images", "document-copy.png")), "Copy", self) copy_action.setStatusTip("Copy selected text") cut_action.setShortcut(QKeySequence.StandardKey.Copy) copy_action.triggered.connect(self.editor.copy) edit_toolbar.addAction(copy_action) edit_menu.addAction(copy_action) paste_action = QAction( QIcon(os.path.join("images", "clipboard-paste-document-text.png")), "Paste", self, ) paste_action.setStatusTip("Paste from clipboard") cut_action.setShortcut(QKeySequence.StandardKey.Paste) paste_action.triggered.connect(self.editor.paste) edit_toolbar.addAction(paste_action) edit_menu.addAction(paste_action) select_action = QAction( QIcon(os.path.join("images", "selection-input.png")), "Select all", self) select_action.setStatusTip("Select all text") cut_action.setShortcut(QKeySequence.StandardKey.SelectAll) select_action.triggered.connect(self.editor.selectAll) edit_menu.addAction(select_action) edit_menu.addSeparator() wrap_action = QAction( QIcon(os.path.join("images", "arrow-continue.png")), "Wrap text to window", self, ) wrap_action.setStatusTip("Toggle wrap text to window") wrap_action.setCheckable(True) wrap_action.setChecked(True) wrap_action.triggered.connect(self.edit_toggle_wrap) edit_menu.addAction(wrap_action) format_toolbar = QToolBar("Format") format_toolbar.setIconSize(QSize(16, 16)) self.addToolBar(format_toolbar) format_menu = self.menuBar().addMenu("&Format") self.fonts = QFontComboBox() self.fonts.currentFontChanged.connect(self.editor.setCurrentFont) format_toolbar.addWidget(self.fonts) self.fontsize = QComboBox() self.fontsize.addItems([str(s) for s in FONT_SIZES]) self.fontsize.currentTextChanged[str].connect( lambda s: self.editor.setFontPointSize(float(s))) format_toolbar.addWidget(self.fontsize) self.bold_action = QAction( QIcon(os.path.join("images", "edit-bold.png")), "Bold", self) self.bold_action.setStatusTip("Bold") self.bold_action.setShortcut(QKeySequence.StandardKey.Bold) self.bold_action.setCheckable(True) self.bold_action.toggled.connect(lambda x: self.editor.setFontWeight( QFont.Weight.Bold if x else QFont.Weight.Normal)) format_toolbar.addAction(self.bold_action) format_menu.addAction(self.bold_action) self.italic_action = QAction( QIcon(os.path.join("images", "edit-italic.png")), "Italic", self) self.italic_action.setStatusTip("Italic") self.italic_action.setShortcut(QKeySequence.StandardKey.Italic) self.italic_action.setCheckable(True) self.italic_action.toggled.connect(self.editor.setFontItalic) format_toolbar.addAction(self.italic_action) format_menu.addAction(self.italic_action) self.underline_action = QAction( QIcon(os.path.join("images", "edit-underline.png")), "Underline", self) self.underline_action.setStatusTip("Underline") self.underline_action.setShortcut(QKeySequence.StandardKey.Underline) self.underline_action.setCheckable(True) self.underline_action.toggled.connect(self.editor.setFontUnderline) format_toolbar.addAction(self.underline_action) format_menu.addAction(self.underline_action) format_menu.addSeparator() self.align_left_action = QAction( QIcon(os.path.join("images", "edit-alignment.png")), "Align left", self) self.align_left_action.setStatusTip("Align text left") self.align_left_action.setCheckable(True) self.align_left_action.triggered.connect( lambda: self.editor.setAlignment(Qt.Alignment.AlignLeft)) format_toolbar.addAction(self.align_left_action) format_menu.addAction(self.align_left_action) self.align_center_action = QAction( QIcon(os.path.join("images", "edit-alignment-center.png")), "Align center", self, ) self.align_center_action.setStatusTip("Align text center") self.align_center_action.setCheckable(True) self.align_center_action.triggered.connect( lambda: self.editor.setAlignment(Qt.Alignment.AlignCenter)) format_toolbar.addAction(self.align_center_action) format_menu.addAction(self.align_center_action) self.align_right_action = QAction( QIcon(os.path.join("images", "edit-alignment-right.png")), "Align right", self, ) self.align_right_action.setStatusTip("Align text right") self.align_right_action.setCheckable(True) self.align_right_action.triggered.connect( lambda: self.editor.setAlignment(Qt.Alignment.AlignRight)) format_toolbar.addAction(self.align_right_action) format_menu.addAction(self.align_right_action) self.align_justify_action = QAction( QIcon(os.path.join("images", "edit-alignment-justify.png")), "Justify", self) self.align_justify_action.setStatusTip("Justify text") self.align_justify_action.setCheckable(True) self.align_justify_action.triggered.connect( lambda: self.editor.setAlignment(Qt.Alignment.AlignJustify)) format_toolbar.addAction(self.align_justify_action) format_menu.addAction(self.align_justify_action) format_group = QActionGroup(self) format_group.setExclusive(True) format_group.addAction(self.align_left_action) format_group.addAction(self.align_center_action) format_group.addAction(self.align_right_action) format_group.addAction(self.align_justify_action) format_menu.addSeparator() self._format_actions = [ self.fonts, self.fontsize, self.bold_action, self.italic_action, self.underline_action, ] self.update_format() self.update_title() self.show()