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