Source code for UI.texteditor

#!/usr/bin/python3
# -*- coding: utf-8 -*-

'''Pychemqt, Chemical Engineering Process simulator
Copyright (C) 2009-2025, Juan José Gómez Romera <jjgomera@gmail.com>

This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program.  If not, see <http://www.gnu.org/licenses/>.


Module to define TextEditor widget, define common text functionality: \
fontcolor, fontstyle, fontweigh, alignment, bold, italic...
This widget is useful to show/edit note properties of stream, equipment... or \
whatever a rich text could be used
'''


import os
from tools.qt import QtCore, QtGui, QtWidgets
from UI.widgets import createAction


[docs] class TextEditor(QtWidgets.QWidget): """Text editor widget""" textChanged = QtCore.pyqtSignal(str, str)
[docs] def __init__(self, text="", parent=None): """Constructor, opcional parameter text to set initial value""" super().__init__(parent) self.text = text self.setWindowTitle(self.tr("Notes")) gridLayout = QtWidgets.QVBoxLayout(self) toolbar = QtWidgets.QToolBar() toolbar.setIconSize(QtCore.QSize(16, 16)) gridLayout.addWidget(toolbar) self.fontComboBox = QtWidgets.QFontComboBox() self.fontComboBox.setToolTip(self.tr("Font name")) self.fontComboBox.textActivated.connect(self.font) toolbar.addWidget(self.fontComboBox) self.fontColor = QtWidgets.QPushButton() self.fontColor.setFixedSize(22, 22) self.fontColor.setPalette(QtGui.QPalette(QtGui.QColor("black"))) self.fontColor.setToolTip(self.tr("Font color")) self.fontColor.clicked.connect(self.colordialog) toolbar.addWidget(self.fontColor) self.fontSize = QtWidgets.QComboBox() for i in QtGui.QFontDatabase.standardSizes(): self.fontSize.addItem(str(i)) self.fontSize.setToolTip(self.tr("Font size")) self.fontSize.textActivated.connect(self.pointSize) toolbar.addWidget(self.fontSize) self.actionBold = createAction( icon=os.path.join("button", "format-text-bold.png"), text=self.tr("Bold"), slot=self.bold, checkable=True) toolbar.addAction(self.actionBold) self.actionItalic = createAction( icon=os.path.join("button", "format-text-italic.png"), text=self.tr("Italic"), slot=self.italic, checkable=True) toolbar.addAction(self.actionItalic) self.actionUnderline = createAction( icon=os.path.join("button", "format-text-underline.png"), text=self.tr("Underline"), slot=self.underline, checkable=True) toolbar.addAction(self.actionUnderline) self.actionStrikeout = createAction( icon=os.path.join("button", "format-text-strikethrough.png"), text=self.tr("Strike through"), slot=self.strikethrough, checkable=True) toolbar.addAction(self.actionStrikeout) self.actionSuperScript = createAction( icon=os.path.join("button", "font-superscript.png"), text=self.tr("Superscript"), slot=self.superscript, checkable=True) toolbar.addAction(self.actionSuperScript) self.actionSubScript = createAction( icon=os.path.join("button", "font-subscript.png"), text=self.tr("Subscript"), slot=self.subscript, checkable=True) toolbar.addAction(self.actionSubScript) toolbar.addSeparator() self.actionAlignLeft = createAction( icon=os.path.join("button", "format-justify-left.png"), text=self.tr("Align left"), slot=self.left, checkable=True) toolbar.addAction(self.actionAlignLeft) self.actionCenter = createAction( icon=os.path.join("button", "format-justify-center.png"), text=self.tr("Center"), slot=self.center, checkable=True) toolbar.addAction(self.actionCenter) self.actionJustify = createAction( icon=os.path.join("button", "format-justify-fill.png"), text=self.tr("Justify"), slot=self.justify, checkable=True) toolbar.addAction(self.actionJustify) self.actionAlignRight = createAction( icon=os.path.join("button", "format-justify-right.png"), text=self.tr("Align right"), slot=self.right, checkable=True) toolbar.addAction(self.actionAlignRight) self.notes = QtWidgets.QTextEdit(text) self.notes.setMinimumWidth(450) self.notes.textChanged.connect(self.setText) self.notes.cursorPositionChanged.connect(self.updateUI) gridLayout.addWidget(self.notes) group = QtGui.QActionGroup(self) group.addAction(self.actionAlignLeft) group.addAction(self.actionCenter) group.addAction(self.actionJustify) group.addAction(self.actionAlignRight) self.notes.setFocus() self.pointSize("10") self.fontSize.setCurrentIndex(self.fontSize.findText("10")) self.font(self.fontComboBox.currentFont().family())
[docs] def setText(self, text=None): """Set text value""" if text: self.notes.setHtml(text) else: text = self.notes.toHtml() self.textChanged.emit(text, self.notes.toPlainText()) self.text = text
[docs] def MergeFormat(self, fmt): """Merge format to current text""" cursor = self.notes.textCursor() if not cursor.hasSelection(): cursor.select(QtGui.QTextCursor.SelectionType.Document) cursor.mergeCharFormat(fmt) self.notes.mergeCurrentCharFormat(fmt)
[docs] def font(self, family): """Change font of text""" fmt = QtGui.QTextCharFormat() fmt.setFontFamily(family) self.MergeFormat(fmt)
[docs] def left(self): """Left align of text""" self.notes.setAlignment(QtCore.Qt.AlignmentFlag.AlignLeft | QtCore.Qt.AlignmentFlag.AlignAbsolute)
[docs] def center(self): """Center align of text""" self.notes.setAlignment(QtCore.Qt.AlignmentFlag.AlignHCenter)
[docs] def right(self): """Right align of text""" self.notes.setAlignment(QtCore.Qt.AlignmentFlag.AlignRight | QtCore.Qt.AlignmentFlag.AlignAbsolute)
[docs] def justify(self): """Justify text to end of line""" self.notes.setAlignment(QtCore.Qt.AlignmentFlag.AlignJustify)
[docs] def pointSize(self, size): """Change point size of font""" points = int(size) if points> 0: fmt = QtGui.QTextCharFormat() fmt.setFontPointSize(points) self.MergeFormat(fmt)
[docs] def bold(self): """Set bold property of font""" fmt = QtGui.QTextCharFormat() if self.actionBold.isChecked(): fmt.setFontWeight(QtGui.QFont.Weight.Bold) else: fmt.setFontWeight(QtGui.QFont.Weight.Normal) self.MergeFormat(fmt)
[docs] def italic(self): """Set italic property of font""" fmt = QtGui.QTextCharFormat() fmt.setFontItalic(self.actionItalic.isChecked()) self.MergeFormat(fmt)
[docs] def underline(self): """Set underline property of font""" fmt = QtGui.QTextCharFormat() fmt.setFontUnderline(self.actionUnderline.isChecked()) self.MergeFormat(fmt)
[docs] def strikethrough(self): """Set strikethrough property of font""" fmt = QtGui.QTextCharFormat() fmt.setFontStrikeOut(self.actionStrikeout.isChecked()) self.MergeFormat(fmt)
[docs] def superscript(self): """Set superscript property of font""" if self.actionSubScript.isChecked(): self.actionSubScript.blockSignals(True) self.actionSubScript.setChecked(False) self.actionSubScript.blockSignals(False) fmt = QtGui.QTextCharFormat() if self.actionSuperScript.isChecked(): fmt.setVerticalAlignment( QtGui.QTextCharFormat.VerticalAlignment.AlignSuperScript) else: fmt.setVerticalAlignment( QtGui.QTextCharFormat.VerticalAlignment.AlignNormal) self.MergeFormat(fmt)
[docs] def subscript(self): """Set subscript property of font""" if self.actionSuperScript.isChecked(): self.actionSuperScript.blockSignals(True) self.actionSuperScript.setChecked(False) self.actionSuperScript.blockSignals(False) fmt = QtGui.QTextCharFormat() if self.actionSubScript.isChecked(): fmt.setVerticalAlignment( QtGui.QTextCharFormat.VerticalAlignment.AlignSubScript) else: fmt.setVerticalAlignment( QtGui.QTextCharFormat.VerticalAlignment.AlignNormal) self.MergeFormat(fmt)
[docs] def updateUI(self): """Update button status when cursor move""" self.fontComboBox.setCurrentIndex(self.fontComboBox.findText( self.notes.fontFamily())) self.fontColor.setPalette(QtGui.QPalette(self.notes.textColor())) self.fontSize.setCurrentIndex(self.fontSize.findText( str(int(self.notes.fontPointSize())))) self.actionBold.setChecked( self.notes.fontWeight() == QtGui.QFont.Weight.Bold) self.actionItalic.setChecked(self.notes.fontItalic()) self.actionUnderline.setChecked(self.notes.fontUnderline()) fmt = self.notes.currentCharFormat() self.actionStrikeout.setChecked(fmt.fontStrikeOut()) self.actionSuperScript.setChecked(False) self.actionSubScript.setChecked(False) if fmt.verticalAlignment() == \ QtGui.QTextCharFormat.VerticalAlignment.AlignSuperScript: self.actionSuperScript.setChecked(True) elif fmt.verticalAlignment() == \ QtGui.QTextCharFormat.VerticalAlignment.AlignSubScript: self.actionSubScript.setChecked(True) self.actionAlignLeft.setChecked( self.notes.alignment() == QtCore.Qt.AlignmentFlag.AlignLeft) self.actionCenter.setChecked( self.notes.alignment() == QtCore.Qt.AlignmentFlag.AlignHCenter) self.actionJustify.setChecked( self.notes.alignment() == QtCore.Qt.AlignmentFlag.AlignJustify) self.actionAlignRight.setChecked( self.notes.alignment() == QtCore.Qt.AlignmentFlag.AlignRight)
[docs] def colordialog(self): """Show dialog to choose font color""" dialog = QtWidgets.QColorDialog(self.notes.textColor(), self) if dialog.exec(): self.fontColor.setPalette(QtGui.QPalette(dialog.currentColor())) self.notes.setTextColor(dialog.currentColor()) fmt = QtGui.QTextCharFormat() fmt.setForeground(dialog.currentColor()) self.MergeFormat(fmt)
if __name__ == "__main__": import sys app = QtWidgets.QApplication(sys.argv) Form = TextEditor("Ejemplo") Form.show() sys.exit(app.exec())