Пример #1
0
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
Пример #2
0
    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()
Пример #3
0
 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)
Пример #4
0
    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)
Пример #5
0
    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)
Пример #7
0
 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)
Пример #8
0
    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()
Пример #9
0
    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()
Пример #10
0
 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
Пример #12
0
    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()
Пример #13
0
    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()
Пример #14
0
    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
Пример #15
0
    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)
Пример #16
0
    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()
Пример #17
0
    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!')
Пример #18
0
def main():
    app = QApplication(sys.argv)
    font = QFont("Courier", 15)
    app.setFont(font)
    ex = AbacusWalletBridge()
    sys.exit(app.exec())
Пример #19
0
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)
Пример #20
0
    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)
Пример #21
0
    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()
Пример #22
0
    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
Пример #23
0
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'])
Пример #24
0
    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)
Пример #25
0
def test_unknownFont(theme):
    assert theme.getFont("whatever") == QFont()
Пример #26
0
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()
Пример #27
0
    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()