Package Camelot :: Package camelot :: Package view :: Package controls :: Package editors :: Module richtexteditor
[frames] | no frames]

Source Code for Module Camelot.camelot.view.controls.editors.richtexteditor

  1  from customeditor import CustomEditor, QtCore, QtGui, Qt 
  2  from wideeditor import WideEditor 
  3  from camelot.view.art import Icon 
  4  
 
5 -class RichTextEditor(CustomEditor, WideEditor):
6
7 - def __init__(self, parent=None, editable=True, **kwargs):
8 CustomEditor.__init__(self, parent) 9 self.layout = QtGui.QVBoxLayout(self) 10 self.layout.setSpacing(0) 11 self.layout.setMargin(0) 12 self.editable = editable 13 self.setSizePolicy( QtGui.QSizePolicy.Expanding, 14 QtGui.QSizePolicy.Expanding ) 15 16 class CustomTextEdit(QtGui.QTextEdit): 17 """A TextEdit editor that sends editingFinished events when the text was changed 18 and focus is lost 19 """ 20 21 def __init__(self, parent): 22 super(CustomTextEdit, self).__init__(parent) 23 self._changed = False 24 self.connect(self, QtCore.SIGNAL('textChanged()'), self.setTextChanged)
25 26 def focusOutEvent(self, event): 27 if self._changed: 28 self.emit(QtCore.SIGNAL('editingFinished()'))
29 30 def textChanged(self): 31 return self._changed 32 33 def setTextChanged(self, state=True): 34 self._changed = state 35 36 def setHtml(self, html): 37 QtGui.QTextEdit.setHtml(self, html) 38 self._changed = False 39 40 self.textedit = CustomTextEdit(self) 41 42 self.connect(self.textedit, 43 QtCore.SIGNAL('editingFinished()'), 44 self.editingFinished) 45 self.textedit.setAcceptRichText(True) 46 47 if not self.editable: 48 self.textedit.setReadOnly(True) 49 else: 50 self.initButtons(editable) 51 52 53 # # 54 # # Buttons setup 55 # # 56 # self.toolbar = QtGui.QToolBar(self) 57 # self.toolbar.setContentsMargins(0, 0, 0, 0) 58 # self.toolbar.setEnabled(editable) 59 # 60 # self.bold_button = QtGui.QToolButton(self) 61 # icon = Icon('tango/16x16/actions/format-text-bold.png').getQIcon() 62 # self.bold_button.setIcon(icon) 63 # self.bold_button.setAutoRaise(True) 64 # self.bold_button.setCheckable(True) 65 # self.bold_button.setEnabled(editable) 66 # self.bold_button.setMaximumSize(QtCore.QSize(20, 20)) 67 # self.bold_button.setShortcut(QtGui.QKeySequence('Ctrl+B')) 68 # self.connect(self.bold_button, QtCore.SIGNAL('clicked()'), self.set_bold) 69 # 70 # self.italic_button = QtGui.QToolButton(self) 71 # icon = Icon('tango/16x16/actions/format-text-italic.png').getQIcon() 72 # self.italic_button.setIcon(icon) 73 # self.italic_button.setAutoRaise(True) 74 # self.italic_button.setCheckable(True) 75 # self.italic_button.setEnabled(editable) 76 # self.italic_button.setMaximumSize(QtCore.QSize(20, 20)) 77 # self.italic_button.setShortcut(QtGui.QKeySequence('Ctrl+I')) 78 # self.connect(self.italic_button, 79 # QtCore.SIGNAL('clicked(bool)'), 80 # self.set_italic) 81 # 82 # self.underline_button = QtGui.QToolButton(self) 83 # icon = Icon('tango/16x16/actions/format-text-underline.png').getQIcon() 84 # self.underline_button.setIcon(icon) 85 # self.underline_button.setAutoRaise(True) 86 # self.underline_button.setCheckable(True) 87 # self.underline_button.setEnabled(editable) 88 # self.underline_button.setMaximumSize(QtCore.QSize(20, 20)) 89 # self.underline_button.setShortcut(QtGui.QKeySequence('Ctrl+U')) 90 # self.connect(self.underline_button, 91 # QtCore.SIGNAL('clicked(bool)'), 92 # self.set_underline) 93 # 94 # self.copy_button = QtGui.QToolButton(self) 95 # icon = Icon('tango/16x16/actions/edit-copy.png').getQIcon() 96 # self.copy_button.setIcon(icon) 97 # self.copy_button.setAutoRaise(True) 98 # self.copy_button.setEnabled(editable) 99 # self.copy_button.setMaximumSize(QtCore.QSize(20, 20)) 100 # self.connect(self.copy_button, 101 # QtCore.SIGNAL('clicked(bool)'), 102 # self.textedit.copy) 103 # 104 # self.cut_button = QtGui.QToolButton(self) 105 # icon = Icon('tango/16x16/actions/edit-cut.png').getQIcon() 106 # self.cut_button.setIcon(icon) 107 # self.cut_button.setAutoRaise(True) 108 # self.cut_button.setEnabled(editable) 109 # self.cut_button.setMaximumSize(QtCore.QSize(20, 20)) 110 # self.connect(self.cut_button, 111 # QtCore.SIGNAL('clicked(bool)'), 112 # self.textedit.cut) 113 # 114 # self.paste_button = QtGui.QToolButton(self) 115 # icon = Icon('tango/16x16/actions/edit-paste.png').getQIcon() 116 # self.paste_button.setIcon(icon) 117 # self.paste_button.setAutoRaise(True) 118 # self.paste_button.setEnabled(editable) 119 # self.paste_button.setMaximumSize(QtCore.QSize(20, 20)) 120 # self.connect(self.paste_button, 121 # QtCore.SIGNAL('clicked(bool)'), 122 # self.textedit.paste) 123 # 124 # self.alignleft_button = QtGui.QToolButton(self) 125 # icon = Icon('tango/16x16/actions/format-justify-left.png').getQIcon() 126 # self.alignleft_button.setIcon(icon) 127 # self.alignleft_button.setAutoRaise(True) 128 # self.alignleft_button.setCheckable(True) 129 # self.alignleft_button.setEnabled(editable) 130 # self.alignleft_button.setMaximumSize(QtCore.QSize(20, 20)) 131 # self.connect(self.alignleft_button, 132 # QtCore.SIGNAL('clicked(bool)'), 133 # self.set_alignleft) 134 # 135 # self.aligncenter_button = QtGui.QToolButton(self) 136 # icon = Icon('tango/16x16/actions/format-justify-center.png').getQIcon() 137 # self.aligncenter_button.setIcon(icon) 138 # self.aligncenter_button.setAutoRaise(True) 139 # self.aligncenter_button.setCheckable(True) 140 # self.aligncenter_button.setEnabled(editable) 141 # self.aligncenter_button.setMaximumSize(QtCore.QSize(20, 20)) 142 # self.connect(self.aligncenter_button, 143 # QtCore.SIGNAL('clicked(bool)'), 144 # self.set_aligncenter) 145 # 146 # self.alignright_button = QtGui.QToolButton(self) 147 # icon = Icon('tango/16x16/actions/format-justify-right.png').getQIcon() 148 # self.alignright_button.setIcon(icon) 149 # self.alignright_button.setAutoRaise(True) 150 # self.alignright_button.setCheckable(True) 151 # self.alignright_button.setEnabled(editable) 152 # self.alignright_button.setMaximumSize(QtCore.QSize(20, 20)) 153 # self.connect(self.alignright_button, 154 # QtCore.SIGNAL('clicked(bool)'), 155 # self.set_alignright) 156 # 157 # self.color_button = QtGui.QToolButton(self) 158 # self.color_button.setAutoRaise(True) 159 # self.color_button.setEnabled(editable) 160 # self.color_button.setMaximumSize(QtCore.QSize(20, 20)) 161 # self.connect(self.color_button, 162 # QtCore.SIGNAL('clicked(bool)'), 163 # self.set_color) 164 # 165 # self.toolbar.addWidget(self.copy_button) 166 # self.toolbar.addWidget(self.cut_button) 167 # self.toolbar.addWidget(self.paste_button) 168 # self.toolbar.addSeparator() 169 # self.toolbar.addWidget(self.bold_button) 170 # self.toolbar.addWidget(self.italic_button) 171 # self.toolbar.addWidget(self.underline_button) 172 # self.toolbar.addSeparator() 173 # self.toolbar.addWidget(self.alignleft_button) 174 # self.toolbar.addWidget(self.aligncenter_button) 175 # self.toolbar.addWidget(self.alignright_button) 176 # self.toolbar.addSeparator() 177 # self.toolbar.addWidget(self.color_button) 178 # 179 # # 180 # # Layout 181 # # 182 # self.layout.addWidget(self.toolbar) 183 self.layout.addWidget(self.textedit) 184 185 self.setLayout(self.layout) 186 187 # 188 # Format 189 # 190 self.textedit.setFontWeight(QtGui.QFont.Normal) 191 self.textedit.setFontItalic(False) 192 self.textedit.setFontUnderline(False) 193 self.textedit.setFocus(Qt.OtherFocusReason) 194 self.update_alignment() 195 196 if self.editable: 197 self.connect(self.textedit, 198 QtCore.SIGNAL('currentCharFormatChanged(const QTextCharFormat&)'), 199 self.update_format) 200 self.connect(self.textedit, 201 QtCore.SIGNAL('cursorPositionChanged()'), 202 self.update_text) 203
204 - def editingFinished(self):
205 if self.textedit.textChanged(): 206 self.emit(QtCore.SIGNAL('editingFinished()'))
207 208 209 210 211 212
213 - def initButtons(self, editable=True):
214 self.toolbar = QtGui.QToolBar(self) 215 self.toolbar.setContentsMargins(0, 0, 0, 0) 216 self.toolbar.setEnabled(editable) 217 218 self.bold_button = QtGui.QToolButton(self) 219 icon = Icon('tango/16x16/actions/format-text-bold.png').getQIcon() 220 self.bold_button.setIcon(icon) 221 self.bold_button.setAutoRaise(True) 222 self.bold_button.setCheckable(True) 223 self.bold_button.setEnabled(editable) 224 self.bold_button.setMaximumSize(QtCore.QSize(20, 20)) 225 self.bold_button.setShortcut(QtGui.QKeySequence('Ctrl+B')) 226 self.connect(self.bold_button, QtCore.SIGNAL('clicked()'), self.set_bold) 227 228 self.italic_button = QtGui.QToolButton(self) 229 icon = Icon('tango/16x16/actions/format-text-italic.png').getQIcon() 230 self.italic_button.setIcon(icon) 231 self.italic_button.setAutoRaise(True) 232 self.italic_button.setCheckable(True) 233 self.italic_button.setEnabled(editable) 234 self.italic_button.setMaximumSize(QtCore.QSize(20, 20)) 235 self.italic_button.setShortcut(QtGui.QKeySequence('Ctrl+I')) 236 self.connect(self.italic_button, 237 QtCore.SIGNAL('clicked(bool)'), 238 self.set_italic) 239 240 self.underline_button = QtGui.QToolButton(self) 241 icon = Icon('tango/16x16/actions/format-text-underline.png').getQIcon() 242 self.underline_button.setIcon(icon) 243 self.underline_button.setAutoRaise(True) 244 self.underline_button.setCheckable(True) 245 self.underline_button.setEnabled(editable) 246 self.underline_button.setMaximumSize(QtCore.QSize(20, 20)) 247 self.underline_button.setShortcut(QtGui.QKeySequence('Ctrl+U')) 248 self.connect(self.underline_button, 249 QtCore.SIGNAL('clicked(bool)'), 250 self.set_underline) 251 252 self.copy_button = QtGui.QToolButton(self) 253 icon = Icon('tango/16x16/actions/edit-copy.png').getQIcon() 254 self.copy_button.setIcon(icon) 255 self.copy_button.setAutoRaise(True) 256 self.copy_button.setEnabled(editable) 257 self.copy_button.setMaximumSize(QtCore.QSize(20, 20)) 258 self.connect(self.copy_button, 259 QtCore.SIGNAL('clicked(bool)'), 260 self.textedit.copy) 261 262 self.cut_button = QtGui.QToolButton(self) 263 icon = Icon('tango/16x16/actions/edit-cut.png').getQIcon() 264 self.cut_button.setIcon(icon) 265 self.cut_button.setAutoRaise(True) 266 self.cut_button.setEnabled(editable) 267 self.cut_button.setMaximumSize(QtCore.QSize(20, 20)) 268 self.connect(self.cut_button, 269 QtCore.SIGNAL('clicked(bool)'), 270 self.textedit.cut) 271 272 self.paste_button = QtGui.QToolButton(self) 273 icon = Icon('tango/16x16/actions/edit-paste.png').getQIcon() 274 self.paste_button.setIcon(icon) 275 self.paste_button.setAutoRaise(True) 276 self.paste_button.setEnabled(editable) 277 self.paste_button.setMaximumSize(QtCore.QSize(20, 20)) 278 self.connect(self.paste_button, 279 QtCore.SIGNAL('clicked(bool)'), 280 self.textedit.paste) 281 282 self.alignleft_button = QtGui.QToolButton(self) 283 icon = Icon('tango/16x16/actions/format-justify-left.png').getQIcon() 284 self.alignleft_button.setIcon(icon) 285 self.alignleft_button.setAutoRaise(True) 286 self.alignleft_button.setCheckable(True) 287 self.alignleft_button.setEnabled(editable) 288 self.alignleft_button.setMaximumSize(QtCore.QSize(20, 20)) 289 self.connect(self.alignleft_button, 290 QtCore.SIGNAL('clicked(bool)'), 291 self.set_alignleft) 292 293 self.aligncenter_button = QtGui.QToolButton(self) 294 icon = Icon('tango/16x16/actions/format-justify-center.png').getQIcon() 295 self.aligncenter_button.setIcon(icon) 296 self.aligncenter_button.setAutoRaise(True) 297 self.aligncenter_button.setCheckable(True) 298 self.aligncenter_button.setEnabled(editable) 299 self.aligncenter_button.setMaximumSize(QtCore.QSize(20, 20)) 300 self.connect(self.aligncenter_button, 301 QtCore.SIGNAL('clicked(bool)'), 302 self.set_aligncenter) 303 304 self.alignright_button = QtGui.QToolButton(self) 305 icon = Icon('tango/16x16/actions/format-justify-right.png').getQIcon() 306 self.alignright_button.setIcon(icon) 307 self.alignright_button.setAutoRaise(True) 308 self.alignright_button.setCheckable(True) 309 self.alignright_button.setEnabled(editable) 310 self.alignright_button.setMaximumSize(QtCore.QSize(20, 20)) 311 self.connect(self.alignright_button, 312 QtCore.SIGNAL('clicked(bool)'), 313 self.set_alignright) 314 315 self.color_button = QtGui.QToolButton(self) 316 self.color_button.setAutoRaise(True) 317 self.color_button.setEnabled(editable) 318 self.color_button.setMaximumSize(QtCore.QSize(20, 20)) 319 self.connect(self.color_button, 320 QtCore.SIGNAL('clicked(bool)'), 321 self.set_color) 322 323 self.toolbar.addWidget(self.copy_button) 324 self.toolbar.addWidget(self.cut_button) 325 self.toolbar.addWidget(self.paste_button) 326 self.toolbar.addSeparator() 327 self.toolbar.addWidget(self.bold_button) 328 self.toolbar.addWidget(self.italic_button) 329 self.toolbar.addWidget(self.underline_button) 330 self.toolbar.addSeparator() 331 self.toolbar.addWidget(self.alignleft_button) 332 self.toolbar.addWidget(self.aligncenter_button) 333 self.toolbar.addWidget(self.alignright_button) 334 self.toolbar.addSeparator() 335 self.toolbar.addWidget(self.color_button) 336 337 # 338 # Layout 339 # 340 self.layout.addWidget(self.toolbar)
341 342 343 344
345 - def set_enabled(self, editable=True):
346 if self.textedit.isEnabled() != editable: 347 if not editable: 348 self.layout().removeWidget(self.bold_button) 349 self.layout().removeWidget(self.italic_button) 350 self.layout().removeWidget(self.underline_button) 351 self.layout().removeWidget(self.toolbar) 352 self.layout().removeWidget(self.color_button) 353 self.layout().removeWidget(self.aligncenter_button) 354 self.layout().removeWidget(self.alignleft_button) 355 self.layout().removeWidget(self.alignright_button) 356 self.layout().removeWidget(self.copy_button) 357 self.layout().removeWidget(self.cut_button) 358 self.layout().removeWidget(self.paste_button) 359 else: 360 value = self.get_value() 361 self.layout.removeWidget(self.textedit) 362 self.initButtons(editable) 363 self.layout.addWidget(self.textedit) 364 self.set_value(value) 365 self.textedit.setEnabled(editable)
366 367 368 369 # 370 # Button methods 371 #
372 - def set_bold(self):
373 if self.bold_button.isChecked(): 374 self.textedit.setFocus(Qt.OtherFocusReason) 375 self.textedit.setFontWeight(QtGui.QFont.Bold) 376 else: 377 self.textedit.setFocus(Qt.OtherFocusReason) 378 self.textedit.setFontWeight(QtGui.QFont.Normal)
379
380 - def set_italic(self, bool):
381 if bool: 382 self.textedit.setFocus(Qt.OtherFocusReason) 383 self.textedit.setFontItalic(True) 384 else: 385 self.textedit.setFocus(Qt.OtherFocusReason) 386 self.textedit.setFontItalic(False)
387
388 - def set_underline(self, bool):
389 if bool: 390 self.textedit.setFocus(Qt.OtherFocusReason) 391 self.textedit.setFontUnderline(True) 392 else: 393 self.textedit.setFocus(Qt.OtherFocusReason) 394 self.textedit.setFontUnderline(False)
395 396
397 - def set_alignleft(self, bool):
398 if bool: 399 self.textedit.setFocus(Qt.OtherFocusReason) 400 self.textedit.setAlignment(Qt.AlignLeft) 401 self.update_alignment(Qt.AlignLeft)
402
403 - def set_aligncenter(self, bool):
404 if bool: 405 self.textedit.setFocus(Qt.OtherFocusReason) 406 self.textedit.setAlignment(Qt.AlignCenter) 407 self.update_alignment(Qt.AlignCenter)
408
409 - def set_alignright(self, bool):
410 if bool: 411 self.textedit.setFocus(Qt.OtherFocusReason) 412 self.textedit.setAlignment(Qt.AlignRight) 413 self.update_alignment(Qt.AlignRight)
414
415 - def update_alignment(self, al=None):
416 if self.editable: 417 if al is None: 418 al = self.textedit.alignment() 419 if al == Qt.AlignLeft: 420 self.alignleft_button.setChecked(True) 421 self.aligncenter_button.setChecked(False) 422 self.alignright_button.setChecked(False) 423 elif al == Qt.AlignCenter: 424 self.aligncenter_button.setChecked(True) 425 self.alignleft_button.setChecked(False) 426 self.alignright_button.setChecked(False) 427 elif al == Qt.AlignRight: 428 self.alignright_button.setChecked(True) 429 self.alignleft_button.setChecked(False) 430 self.aligncenter_button.setChecked(False)
431
432 - def set_color(self):
433 color = QtGui.QColorDialog.getColor(self.textedit.textColor()) 434 if color.isValid(): 435 self.textedit.setFocus(Qt.OtherFocusReason) 436 self.textedit.setTextColor(color) 437 pixmap = QtGui.QPixmap(16, 16) 438 pixmap.fill(color) 439 self.color_button.setIcon(QtGui.QIcon(pixmap))
440
441 - def update_color(self):
442 if self.editable: 443 color = self.textedit.textColor() 444 pixmap = QtGui.QPixmap(16, 16) 445 pixmap.fill(color) 446 self.color_button.setIcon(QtGui.QIcon(pixmap))
447
448 - def update_format(self, format):
449 if self.editable: 450 font = format.font() 451 self.bold_button.setChecked(font.bold()) 452 self.italic_button.setChecked(font.italic()) 453 self.underline_button.setChecked(font.underline()) 454 self.update_alignment(self.textedit.alignment())
455
456 - def update_text(self):
457 if self.editable: 458 self.update_alignment() 459 self.update_color()
460
461 - def get_value(self):
462 from xml.dom import minidom 463 tree = minidom.parseString(unicode(self.textedit.toHtml()).encode('utf-8')) 464 value = u''.join([node.toxml() for node in tree.getElementsByTagName('html')[0].getElementsByTagName('body')[0].childNodes]) 465 return CustomEditor.get_value(self) or value
466
467 - def set_value(self, value):
468 value = CustomEditor.set_value(self, value) 469 if value!=None: 470 if unicode(self.textedit.toHtml())!=value: 471 self.update_alignment() 472 self.textedit.setHtml(value) 473 self.update_color() 474 else: 475 self.textedit.clear()
476