bouquin 0.1.10__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
bouquin/toolbar.py ADDED
@@ -0,0 +1,221 @@
1
+ from __future__ import annotations
2
+
3
+ from PySide6.QtCore import Signal, Qt
4
+ from PySide6.QtGui import QAction, QKeySequence, QFont, QFontDatabase, QActionGroup
5
+ from PySide6.QtWidgets import QToolBar
6
+
7
+
8
+ class ToolBar(QToolBar):
9
+ boldRequested = Signal()
10
+ italicRequested = Signal()
11
+ underlineRequested = Signal()
12
+ strikeRequested = Signal()
13
+ codeRequested = Signal()
14
+ headingRequested = Signal(int)
15
+ bulletsRequested = Signal()
16
+ numbersRequested = Signal()
17
+ checkboxesRequested = Signal()
18
+ alignRequested = Signal(Qt.AlignmentFlag)
19
+ historyRequested = Signal()
20
+ insertImageRequested = Signal()
21
+
22
+ def __init__(self, parent=None):
23
+ super().__init__("Format", parent)
24
+ self.setObjectName("Format")
25
+ self.setToolButtonStyle(Qt.ToolButtonTextOnly)
26
+ self._build_actions()
27
+ self._apply_toolbar_styles()
28
+
29
+ def _build_actions(self):
30
+ self.actBold = QAction("B", self)
31
+ self.actBold.setToolTip("Bold")
32
+ self.actBold.setCheckable(True)
33
+ self.actBold.setShortcut(QKeySequence.Bold)
34
+ self.actBold.triggered.connect(self.boldRequested)
35
+
36
+ self.actItalic = QAction("I", self)
37
+ self.actItalic.setToolTip("Italic")
38
+ self.actItalic.setCheckable(True)
39
+ self.actItalic.setShortcut(QKeySequence.Italic)
40
+ self.actItalic.triggered.connect(self.italicRequested)
41
+
42
+ self.actUnderline = QAction("U", self)
43
+ self.actUnderline.setToolTip("Underline")
44
+ self.actUnderline.setCheckable(True)
45
+ self.actUnderline.setShortcut(QKeySequence.Underline)
46
+ self.actUnderline.triggered.connect(self.underlineRequested)
47
+
48
+ self.actStrike = QAction("S", self)
49
+ self.actStrike.setToolTip("Strikethrough")
50
+ self.actStrike.setCheckable(True)
51
+ self.actStrike.setShortcut("Ctrl+-")
52
+ self.actStrike.triggered.connect(self.strikeRequested)
53
+
54
+ self.actCode = QAction("</>", self)
55
+ self.actCode.setToolTip("Code block")
56
+ self.actCode.setShortcut("Ctrl+`")
57
+ self.actCode.triggered.connect(self.codeRequested)
58
+
59
+ # Headings
60
+ self.actH1 = QAction("H1", self)
61
+ self.actH1.setToolTip("Heading 1")
62
+ self.actH1.setCheckable(True)
63
+ self.actH1.setShortcut("Ctrl+1")
64
+ self.actH1.triggered.connect(lambda: self.headingRequested.emit(24))
65
+ self.actH2 = QAction("H2", self)
66
+ self.actH2.setToolTip("Heading 2")
67
+ self.actH2.setCheckable(True)
68
+ self.actH2.setShortcut("Ctrl+2")
69
+ self.actH2.triggered.connect(lambda: self.headingRequested.emit(18))
70
+ self.actH3 = QAction("H3", self)
71
+ self.actH3.setToolTip("Heading 3")
72
+ self.actH3.setCheckable(True)
73
+ self.actH3.setShortcut("Ctrl+3")
74
+ self.actH3.triggered.connect(lambda: self.headingRequested.emit(14))
75
+ self.actNormal = QAction("N", self)
76
+ self.actNormal.setToolTip("Normal paragraph text")
77
+ self.actNormal.setCheckable(True)
78
+ self.actNormal.setShortcut("Ctrl+N")
79
+ self.actNormal.triggered.connect(lambda: self.headingRequested.emit(0))
80
+
81
+ # Lists
82
+ self.actBullets = QAction("•", self)
83
+ self.actBullets.setToolTip("Bulleted list")
84
+ self.actBullets.setCheckable(True)
85
+ self.actBullets.triggered.connect(self.bulletsRequested)
86
+ self.actNumbers = QAction("1.", self)
87
+ self.actNumbers.setToolTip("Numbered list")
88
+ self.actNumbers.setCheckable(True)
89
+ self.actNumbers.triggered.connect(self.numbersRequested)
90
+ self.actCheckboxes = QAction("☐", self)
91
+ self.actCheckboxes.setToolTip("Toggle checkboxes")
92
+ self.actCheckboxes.triggered.connect(self.checkboxesRequested)
93
+
94
+ # Images
95
+ self.actInsertImg = QAction("Image", self)
96
+ self.actInsertImg.setToolTip("Insert image")
97
+ self.actInsertImg.setShortcut("Ctrl+Shift+I")
98
+ self.actInsertImg.triggered.connect(self.insertImageRequested)
99
+
100
+ # Alignment
101
+ self.actAlignL = QAction("L", self)
102
+ self.actAlignL.setToolTip("Align Left")
103
+ self.actAlignL.setCheckable(True)
104
+ self.actAlignL.triggered.connect(lambda: self.alignRequested.emit(Qt.AlignLeft))
105
+ self.actAlignC = QAction("C", self)
106
+ self.actAlignC.setToolTip("Align Center")
107
+ self.actAlignC.setCheckable(True)
108
+ self.actAlignC.triggered.connect(
109
+ lambda: self.alignRequested.emit(Qt.AlignHCenter)
110
+ )
111
+ self.actAlignR = QAction("R", self)
112
+ self.actAlignR.setToolTip("Align Right")
113
+ self.actAlignR.setCheckable(True)
114
+ self.actAlignR.triggered.connect(
115
+ lambda: self.alignRequested.emit(Qt.AlignRight)
116
+ )
117
+
118
+ # History button
119
+ self.actHistory = QAction("History", self)
120
+ self.actHistory.triggered.connect(self.historyRequested)
121
+
122
+ # Set exclusive buttons in QActionGroups
123
+ self.grpHeadings = QActionGroup(self)
124
+ self.grpHeadings.setExclusive(True)
125
+ for a in (
126
+ self.actBold,
127
+ self.actItalic,
128
+ self.actUnderline,
129
+ self.actStrike,
130
+ self.actH1,
131
+ self.actH2,
132
+ self.actH3,
133
+ self.actNormal,
134
+ ):
135
+ a.setCheckable(True)
136
+ a.setActionGroup(self.grpHeadings)
137
+
138
+ self.grpAlign = QActionGroup(self)
139
+ self.grpAlign.setExclusive(True)
140
+ for a in (self.actAlignL, self.actAlignC, self.actAlignR):
141
+ a.setActionGroup(self.grpAlign)
142
+
143
+ # Add actions
144
+ self.addActions(
145
+ [
146
+ self.actBold,
147
+ self.actItalic,
148
+ self.actUnderline,
149
+ self.actStrike,
150
+ self.actCode,
151
+ self.actH1,
152
+ self.actH2,
153
+ self.actH3,
154
+ self.actNormal,
155
+ self.actBullets,
156
+ self.actNumbers,
157
+ self.actCheckboxes,
158
+ self.actInsertImg,
159
+ self.actAlignL,
160
+ self.actAlignC,
161
+ self.actAlignR,
162
+ self.actHistory,
163
+ ]
164
+ )
165
+
166
+ def _apply_toolbar_styles(self):
167
+ self._style_letter_button(self.actBold, "B", bold=True)
168
+ self._style_letter_button(self.actItalic, "I", italic=True)
169
+ self._style_letter_button(self.actUnderline, "U", underline=True)
170
+ self._style_letter_button(self.actStrike, "S", strike=True)
171
+ # Monospace look for code; use a fixed font
172
+ code_font = QFontDatabase.systemFont(QFontDatabase.FixedFont)
173
+ self._style_letter_button(self.actCode, "</>", custom_font=code_font)
174
+
175
+ # Headings
176
+ self._style_letter_button(self.actH1, "H1")
177
+ self._style_letter_button(self.actH2, "H2")
178
+ self._style_letter_button(self.actH3, "H3")
179
+ self._style_letter_button(self.actNormal, "N")
180
+
181
+ # Lists
182
+ self._style_letter_button(self.actBullets, "•")
183
+ self._style_letter_button(self.actNumbers, "1.")
184
+
185
+ # Alignment
186
+ self._style_letter_button(self.actAlignL, "L")
187
+ self._style_letter_button(self.actAlignC, "C")
188
+ self._style_letter_button(self.actAlignR, "R")
189
+
190
+ # History
191
+ self._style_letter_button(self.actHistory, "View History")
192
+
193
+ def _style_letter_button(
194
+ self,
195
+ action: QAction,
196
+ text: str,
197
+ *,
198
+ bold: bool = False,
199
+ italic: bool = False,
200
+ underline: bool = False,
201
+ strike: bool = False,
202
+ custom_font: QFont | None = None,
203
+ tooltip: str | None = None,
204
+ ):
205
+ btn = self.widgetForAction(action)
206
+ if not btn:
207
+ return
208
+ btn.setText(text)
209
+
210
+ f = custom_font if custom_font is not None else QFont(btn.font())
211
+ if custom_font is None:
212
+ f.setBold(bold)
213
+ f.setItalic(italic)
214
+ f.setUnderline(underline)
215
+ f.setStrikeOut(strike)
216
+ btn.setFont(f)
217
+
218
+ # Keep accessibility/tooltip readable
219
+ if tooltip:
220
+ btn.setToolTip(tooltip)
221
+ btn.setAccessibleName(tooltip)