1#!/usr/bin/env python 2 3 4############################################################################# 5## 6## Copyright (C) 2013 Riverbank Computing Limited 7## Copyright (C) 2010 Hans-Peter Jansen <hpj@urpla.net>. 8## Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). 9## All rights reserved. 10## 11## This file is part of the examples of PyQt. 12## 13## $QT_BEGIN_LICENSE:LGPL$ 14## Commercial Usage 15## Licensees holding valid Qt Commercial licenses may use this file in 16## accordance with the Qt Commercial License Agreement provided with the 17## Software or, alternatively, in accordance with the terms contained in 18## a written agreement between you and Nokia. 19## 20## GNU Lesser General Public License Usage 21## Alternatively, this file may be used under the terms of the GNU Lesser 22## General Public License version 2.1 as published by the Free Software 23## Foundation and appearing in the file LICENSE.LGPL included in the 24## packaging of this file. Please review the following information to 25## ensure the GNU Lesser General Public License version 2.1 requirements 26## will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. 27## 28## In addition, as a special exception, Nokia gives you certain additional 29## rights. These rights are described in the Nokia Qt LGPL Exception 30## version 1.1, included in the file LGPL_EXCEPTION.txt in this package. 31## 32## GNU General Public License Usage 33## Alternatively, this file may be used under the terms of the GNU 34## General Public License version 3.0 as published by the Free Software 35## Foundation and appearing in the file LICENSE.GPL included in the 36## packaging of this file. Please review the following information to 37## ensure the GNU General Public License version 3.0 requirements will be 38## met: http://www.gnu.org/copyleft/gpl.html. 39## 40## If you have questions regarding the use of this file, please contact 41## Nokia at qt-info@nokia.com. 42## $QT_END_LICENSE$ 43## 44############################################################################# 45 46 47import sys 48 49from PyQt5.QtCore import QFile, QFileInfo, Qt, QTextCodec 50from PyQt5.QtGui import (QFont, QFontDatabase, QFontInfo, QIcon, QKeySequence, 51 QPixmap, QTextBlockFormat, QTextCharFormat, QTextCursor, 52 QTextDocumentWriter, QTextListFormat) 53from PyQt5.QtWidgets import (QAction, QActionGroup, QApplication, QColorDialog, 54 QComboBox, QFileDialog, QFontComboBox, QMainWindow, QMenu, QMessageBox, 55 QTextEdit, QToolBar) 56from PyQt5.QtPrintSupport import QPrintDialog, QPrinter, QPrintPreviewDialog 57 58import textedit_rc 59 60 61if sys.platform.startswith('darwin'): 62 rsrcPath = ":/images/mac" 63else: 64 rsrcPath = ":/images/win" 65 66 67class TextEdit(QMainWindow): 68 def __init__(self, fileName=None, parent=None): 69 super(TextEdit, self).__init__(parent) 70 71 self.setWindowIcon(QIcon(':/images/logo.png')) 72 self.setToolButtonStyle(Qt.ToolButtonFollowStyle) 73 self.setupFileActions() 74 self.setupEditActions() 75 self.setupTextActions() 76 77 helpMenu = QMenu("Help", self) 78 self.menuBar().addMenu(helpMenu) 79 helpMenu.addAction("About", self.about) 80 helpMenu.addAction("About &Qt", QApplication.instance().aboutQt) 81 82 self.textEdit = QTextEdit(self) 83 self.textEdit.currentCharFormatChanged.connect( 84 self.currentCharFormatChanged) 85 self.textEdit.cursorPositionChanged.connect(self.cursorPositionChanged) 86 self.setCentralWidget(self.textEdit) 87 self.textEdit.setFocus() 88 self.setCurrentFileName() 89 self.fontChanged(self.textEdit.font()) 90 self.colorChanged(self.textEdit.textColor()) 91 self.alignmentChanged(self.textEdit.alignment()) 92 self.textEdit.document().modificationChanged.connect( 93 self.actionSave.setEnabled) 94 self.textEdit.document().modificationChanged.connect( 95 self.setWindowModified) 96 self.textEdit.document().undoAvailable.connect( 97 self.actionUndo.setEnabled) 98 self.textEdit.document().redoAvailable.connect( 99 self.actionRedo.setEnabled) 100 self.setWindowModified(self.textEdit.document().isModified()) 101 self.actionSave.setEnabled(self.textEdit.document().isModified()) 102 self.actionUndo.setEnabled(self.textEdit.document().isUndoAvailable()) 103 self.actionRedo.setEnabled(self.textEdit.document().isRedoAvailable()) 104 self.actionUndo.triggered.connect(self.textEdit.undo) 105 self.actionRedo.triggered.connect(self.textEdit.redo) 106 self.actionCut.setEnabled(False) 107 self.actionCopy.setEnabled(False) 108 self.actionCut.triggered.connect(self.textEdit.cut) 109 self.actionCopy.triggered.connect(self.textEdit.copy) 110 self.actionPaste.triggered.connect(self.textEdit.paste) 111 self.textEdit.copyAvailable.connect(self.actionCut.setEnabled) 112 self.textEdit.copyAvailable.connect(self.actionCopy.setEnabled) 113 QApplication.clipboard().dataChanged.connect(self.clipboardDataChanged) 114 115 if fileName is None: 116 fileName = ':/example.html' 117 118 if not self.load(fileName): 119 self.fileNew() 120 121 def closeEvent(self, e): 122 if self.maybeSave(): 123 e.accept() 124 else: 125 e.ignore() 126 127 def setupFileActions(self): 128 tb = QToolBar(self) 129 tb.setWindowTitle("File Actions") 130 self.addToolBar(tb) 131 132 menu = QMenu("&File", self) 133 self.menuBar().addMenu(menu) 134 135 self.actionNew = QAction( 136 QIcon.fromTheme('document-new', 137 QIcon(rsrcPath + '/filenew.png')), 138 "&New", self, priority=QAction.LowPriority, 139 shortcut=QKeySequence.New, triggered=self.fileNew) 140 tb.addAction(self.actionNew) 141 menu.addAction(self.actionNew) 142 143 self.actionOpen = QAction( 144 QIcon.fromTheme('document-open', 145 QIcon(rsrcPath + '/fileopen.png')), 146 "&Open...", self, shortcut=QKeySequence.Open, 147 triggered=self.fileOpen) 148 tb.addAction(self.actionOpen) 149 menu.addAction(self.actionOpen) 150 menu.addSeparator() 151 152 self.actionSave = QAction( 153 QIcon.fromTheme('document-save', 154 QIcon(rsrcPath + '/filesave.png')), 155 "&Save", self, shortcut=QKeySequence.Save, 156 triggered=self.fileSave, enabled=False) 157 tb.addAction(self.actionSave) 158 menu.addAction(self.actionSave) 159 160 self.actionSaveAs = QAction("Save &As...", self, 161 priority=QAction.LowPriority, 162 shortcut=Qt.CTRL + Qt.SHIFT + Qt.Key_S, 163 triggered=self.fileSaveAs) 164 menu.addAction(self.actionSaveAs) 165 menu.addSeparator() 166 167 self.actionPrint = QAction( 168 QIcon.fromTheme('document-print', 169 QIcon(rsrcPath + '/fileprint.png')), 170 "&Print...", self, priority=QAction.LowPriority, 171 shortcut=QKeySequence.Print, triggered=self.filePrint) 172 tb.addAction(self.actionPrint) 173 menu.addAction(self.actionPrint) 174 175 self.actionPrintPreview = QAction( 176 QIcon.fromTheme('fileprint', 177 QIcon(rsrcPath + '/fileprint.png')), 178 "Print Preview...", self, 179 shortcut=Qt.CTRL + Qt.SHIFT + Qt.Key_P, 180 triggered=self.filePrintPreview) 181 menu.addAction(self.actionPrintPreview) 182 183 self.actionPrintPdf = QAction( 184 QIcon.fromTheme('exportpdf', 185 QIcon(rsrcPath + '/exportpdf.png')), 186 "&Export PDF...", self, priority=QAction.LowPriority, 187 shortcut=Qt.CTRL + Qt.Key_D, 188 triggered=self.filePrintPdf) 189 tb.addAction(self.actionPrintPdf) 190 menu.addAction(self.actionPrintPdf) 191 menu.addSeparator() 192 193 self.actionQuit = QAction("&Quit", self, shortcut=QKeySequence.Quit, 194 triggered=self.close) 195 menu.addAction(self.actionQuit) 196 197 def setupEditActions(self): 198 tb = QToolBar(self) 199 tb.setWindowTitle("Edit Actions") 200 self.addToolBar(tb) 201 202 menu = QMenu("&Edit", self) 203 self.menuBar().addMenu(menu) 204 205 self.actionUndo = QAction( 206 QIcon.fromTheme('edit-undo', 207 QIcon(rsrcPath + '/editundo.png')), 208 "&Undo", self, shortcut=QKeySequence.Undo) 209 tb.addAction(self.actionUndo) 210 menu.addAction(self.actionUndo) 211 212 self.actionRedo = QAction( 213 QIcon.fromTheme('edit-redo', 214 QIcon(rsrcPath + '/editredo.png')), 215 "&Redo", self, priority=QAction.LowPriority, 216 shortcut=QKeySequence.Redo) 217 tb.addAction(self.actionRedo) 218 menu.addAction(self.actionRedo) 219 menu.addSeparator() 220 221 self.actionCut = QAction( 222 QIcon.fromTheme('edit-cut', QIcon(rsrcPath + '/editcut.png')), 223 "Cu&t", self, priority=QAction.LowPriority, 224 shortcut=QKeySequence.Cut) 225 tb.addAction(self.actionCut) 226 menu.addAction(self.actionCut) 227 228 self.actionCopy = QAction( 229 QIcon.fromTheme('edit-copy', 230 QIcon(rsrcPath + '/editcopy.png')), 231 "&Copy", self, priority=QAction.LowPriority, 232 shortcut=QKeySequence.Copy) 233 tb.addAction(self.actionCopy) 234 menu.addAction(self.actionCopy) 235 236 self.actionPaste = QAction( 237 QIcon.fromTheme('edit-paste', 238 QIcon(rsrcPath + '/editpaste.png')), 239 "&Paste", self, priority=QAction.LowPriority, 240 shortcut=QKeySequence.Paste, 241 enabled=(len(QApplication.clipboard().text()) != 0)) 242 tb.addAction(self.actionPaste) 243 menu.addAction(self.actionPaste) 244 245 def setupTextActions(self): 246 tb = QToolBar(self) 247 tb.setWindowTitle("Format Actions") 248 self.addToolBar(tb) 249 250 menu = QMenu("F&ormat", self) 251 self.menuBar().addMenu(menu) 252 253 self.actionTextBold = QAction( 254 QIcon.fromTheme('format-text-bold', 255 QIcon(rsrcPath + '/textbold.png')), 256 "&Bold", self, priority=QAction.LowPriority, 257 shortcut=Qt.CTRL + Qt.Key_B, triggered=self.textBold, 258 checkable=True) 259 bold = QFont() 260 bold.setBold(True) 261 self.actionTextBold.setFont(bold) 262 tb.addAction(self.actionTextBold) 263 menu.addAction(self.actionTextBold) 264 265 self.actionTextItalic = QAction( 266 QIcon.fromTheme('format-text-italic', 267 QIcon(rsrcPath + '/textitalic.png')), 268 "&Italic", self, priority=QAction.LowPriority, 269 shortcut=Qt.CTRL + Qt.Key_I, triggered=self.textItalic, 270 checkable=True) 271 italic = QFont() 272 italic.setItalic(True) 273 self.actionTextItalic.setFont(italic) 274 tb.addAction(self.actionTextItalic) 275 menu.addAction(self.actionTextItalic) 276 277 self.actionTextUnderline = QAction( 278 QIcon.fromTheme('format-text-underline', 279 QIcon(rsrcPath + '/textunder.png')), 280 "&Underline", self, priority=QAction.LowPriority, 281 shortcut=Qt.CTRL + Qt.Key_U, triggered=self.textUnderline, 282 checkable=True) 283 underline = QFont() 284 underline.setUnderline(True) 285 self.actionTextUnderline.setFont(underline) 286 tb.addAction(self.actionTextUnderline) 287 menu.addAction(self.actionTextUnderline) 288 289 menu.addSeparator() 290 291 grp = QActionGroup(self, triggered=self.textAlign) 292 293 # Make sure the alignLeft is always left of the alignRight. 294 if QApplication.isLeftToRight(): 295 self.actionAlignLeft = QAction( 296 QIcon.fromTheme('format-justify-left', 297 QIcon(rsrcPath + '/textleft.png')), 298 "&Left", grp) 299 self.actionAlignCenter = QAction( 300 QIcon.fromTheme('format-justify-center', 301 QIcon(rsrcPath + '/textcenter.png')), 302 "C&enter", grp) 303 self.actionAlignRight = QAction( 304 QIcon.fromTheme('format-justify-right', 305 QIcon(rsrcPath + '/textright.png')), 306 "&Right", grp) 307 else: 308 self.actionAlignRight = QAction( 309 QIcon.fromTheme('format-justify-right', 310 QIcon(rsrcPath + '/textright.png')), 311 "&Right", grp) 312 self.actionAlignCenter = QAction( 313 QIcon.fromTheme('format-justify-center', 314 QIcon(rsrcPath + '/textcenter.png')), 315 "C&enter", grp) 316 self.actionAlignLeft = QAction( 317 QIcon.fromTheme('format-justify-left', 318 QIcon(rsrcPath + '/textleft.png')), 319 "&Left", grp) 320 321 self.actionAlignJustify = QAction( 322 QIcon.fromTheme('format-justify-fill', 323 QIcon(rsrcPath + '/textjustify.png')), 324 "&Justify", grp) 325 326 self.actionAlignLeft.setShortcut(Qt.CTRL + Qt.Key_L) 327 self.actionAlignLeft.setCheckable(True) 328 self.actionAlignLeft.setPriority(QAction.LowPriority) 329 330 self.actionAlignCenter.setShortcut(Qt.CTRL + Qt.Key_E) 331 self.actionAlignCenter.setCheckable(True) 332 self.actionAlignCenter.setPriority(QAction.LowPriority) 333 334 self.actionAlignRight.setShortcut(Qt.CTRL + Qt.Key_R) 335 self.actionAlignRight.setCheckable(True) 336 self.actionAlignRight.setPriority(QAction.LowPriority) 337 338 self.actionAlignJustify.setShortcut(Qt.CTRL + Qt.Key_J) 339 self.actionAlignJustify.setCheckable(True) 340 self.actionAlignJustify.setPriority(QAction.LowPriority) 341 342 tb.addActions(grp.actions()) 343 menu.addActions(grp.actions()) 344 menu.addSeparator() 345 346 pix = QPixmap(16, 16) 347 pix.fill(Qt.black) 348 self.actionTextColor = QAction(QIcon(pix), "&Color...", self, 349 triggered=self.textColor) 350 tb.addAction(self.actionTextColor) 351 menu.addAction(self.actionTextColor) 352 353 tb = QToolBar(self) 354 tb.setAllowedAreas(Qt.TopToolBarArea | Qt.BottomToolBarArea) 355 tb.setWindowTitle("Format Actions") 356 self.addToolBarBreak(Qt.TopToolBarArea) 357 self.addToolBar(tb) 358 359 comboStyle = QComboBox(tb) 360 tb.addWidget(comboStyle) 361 comboStyle.addItem("Standard") 362 comboStyle.addItem("Bullet List (Disc)") 363 comboStyle.addItem("Bullet List (Circle)") 364 comboStyle.addItem("Bullet List (Square)") 365 comboStyle.addItem("Ordered List (Decimal)") 366 comboStyle.addItem("Ordered List (Alpha lower)") 367 comboStyle.addItem("Ordered List (Alpha upper)") 368 comboStyle.addItem("Ordered List (Roman lower)") 369 comboStyle.addItem("Ordered List (Roman upper)") 370 comboStyle.activated.connect(self.textStyle) 371 372 self.comboFont = QFontComboBox(tb) 373 tb.addWidget(self.comboFont) 374 self.comboFont.activated[str].connect(self.textFamily) 375 376 self.comboSize = QComboBox(tb) 377 self.comboSize.setObjectName("comboSize") 378 tb.addWidget(self.comboSize) 379 self.comboSize.setEditable(True) 380 381 db = QFontDatabase() 382 for size in db.standardSizes(): 383 self.comboSize.addItem("%s" % (size)) 384 385 self.comboSize.activated[str].connect(self.textSize) 386 self.comboSize.setCurrentIndex( 387 self.comboSize.findText( 388 "%s" % (QApplication.font().pointSize()))) 389 390 def load(self, f): 391 if not QFile.exists(f): 392 return False 393 394 fh = QFile(f) 395 if not fh.open(QFile.ReadOnly): 396 return False 397 398 data = fh.readAll() 399 codec = QTextCodec.codecForHtml(data) 400 unistr = codec.toUnicode(data) 401 402 if Qt.mightBeRichText(unistr): 403 self.textEdit.setHtml(unistr) 404 else: 405 self.textEdit.setPlainText(unistr) 406 407 self.setCurrentFileName(f) 408 return True 409 410 def maybeSave(self): 411 if not self.textEdit.document().isModified(): 412 return True 413 414 if self.fileName.startswith(':/'): 415 return True 416 417 ret = QMessageBox.warning(self, "Application", 418 "The document has been modified.\n" 419 "Do you want to save your changes?", 420 QMessageBox.Save | QMessageBox.Discard | QMessageBox.Cancel) 421 422 if ret == QMessageBox.Save: 423 return self.fileSave() 424 425 if ret == QMessageBox.Cancel: 426 return False 427 428 return True 429 430 def setCurrentFileName(self, fileName=''): 431 self.fileName = fileName 432 self.textEdit.document().setModified(False) 433 434 if not fileName: 435 shownName = 'untitled.txt' 436 else: 437 shownName = QFileInfo(fileName).fileName() 438 439 self.setWindowTitle(self.tr("%s[*] - %s" % (shownName, "Rich Text"))) 440 self.setWindowModified(False) 441 442 def fileNew(self): 443 if self.maybeSave(): 444 self.textEdit.clear() 445 self.setCurrentFileName() 446 447 def fileOpen(self): 448 fn, _ = QFileDialog.getOpenFileName(self, "Open File...", None, 449 "HTML-Files (*.htm *.html);;All Files (*)") 450 451 if fn: 452 self.load(fn) 453 454 def fileSave(self): 455 if not self.fileName: 456 return self.fileSaveAs() 457 458 writer = QTextDocumentWriter(self.fileName) 459 success = writer.write(self.textEdit.document()) 460 if success: 461 self.textEdit.document().setModified(False) 462 463 return success 464 465 def fileSaveAs(self): 466 fn, _ = QFileDialog.getSaveFileName(self, "Save as...", None, 467 "ODF files (*.odt);;HTML-Files (*.htm *.html);;All Files (*)") 468 469 if not fn: 470 return False 471 472 lfn = fn.lower() 473 if not lfn.endswith(('.odt', '.htm', '.html')): 474 # The default. 475 fn += '.odt' 476 477 self.setCurrentFileName(fn) 478 return self.fileSave() 479 480 def filePrint(self): 481 printer = QPrinter(QPrinter.HighResolution) 482 dlg = QPrintDialog(printer, self) 483 484 if self.textEdit.textCursor().hasSelection(): 485 dlg.addEnabledOption(QPrintDialog.PrintSelection) 486 487 dlg.setWindowTitle("Print Document") 488 489 if dlg.exec_() == QPrintDialog.Accepted: 490 self.textEdit.print_(printer) 491 492 del dlg 493 494 def filePrintPreview(self): 495 printer = QPrinter(QPrinter.HighResolution) 496 preview = QPrintPreviewDialog(printer, self) 497 preview.paintRequested.connect(self.printPreview) 498 preview.exec_() 499 500 def printPreview(self, printer): 501 self.textEdit.print_(printer) 502 503 def filePrintPdf(self): 504 fn, _ = QFileDialog.getSaveFileName(self, "Export PDF", None, 505 "PDF files (*.pdf);;All Files (*)") 506 507 if fn: 508 if QFileInfo(fn).suffix().isEmpty(): 509 fn += '.pdf' 510 511 printer = QPrinter(QPrinter.HighResolution) 512 printer.setOutputFormat(QPrinter.PdfFormat) 513 printer.setOutputFileName(fn) 514 self.textEdit.document().print_(printer) 515 516 def textBold(self): 517 fmt = QTextCharFormat() 518 fmt.setFontWeight(self.actionTextBold.isChecked() and QFont.Bold or QFont.Normal) 519 self.mergeFormatOnWordOrSelection(fmt) 520 521 def textUnderline(self): 522 fmt = QTextCharFormat() 523 fmt.setFontUnderline(self.actionTextUnderline.isChecked()) 524 self.mergeFormatOnWordOrSelection(fmt) 525 526 def textItalic(self): 527 fmt = QTextCharFormat() 528 fmt.setFontItalic(self.actionTextItalic.isChecked()) 529 self.mergeFormatOnWordOrSelection(fmt) 530 531 def textFamily(self, family): 532 fmt = QTextCharFormat() 533 fmt.setFontFamily(family) 534 self.mergeFormatOnWordOrSelection(fmt) 535 536 def textSize(self, pointSize): 537 pointSize = float(pointSize) 538 if pointSize > 0: 539 fmt = QTextCharFormat() 540 fmt.setFontPointSize(pointSize) 541 self.mergeFormatOnWordOrSelection(fmt) 542 543 def textStyle(self, styleIndex): 544 cursor = self.textEdit.textCursor() 545 if styleIndex: 546 styleDict = { 547 1: QTextListFormat.ListDisc, 548 2: QTextListFormat.ListCircle, 549 3: QTextListFormat.ListSquare, 550 4: QTextListFormat.ListDecimal, 551 5: QTextListFormat.ListLowerAlpha, 552 6: QTextListFormat.ListUpperAlpha, 553 7: QTextListFormat.ListLowerRoman, 554 8: QTextListFormat.ListUpperRoman, 555 } 556 557 style = styleDict.get(styleIndex, QTextListFormat.ListDisc) 558 cursor.beginEditBlock() 559 blockFmt = cursor.blockFormat() 560 listFmt = QTextListFormat() 561 562 if cursor.currentList(): 563 listFmt = cursor.currentList().format() 564 else: 565 listFmt.setIndent(blockFmt.indent() + 1) 566 blockFmt.setIndent(0) 567 cursor.setBlockFormat(blockFmt) 568 569 listFmt.setStyle(style) 570 cursor.createList(listFmt) 571 cursor.endEditBlock() 572 else: 573 bfmt = QTextBlockFormat() 574 bfmt.setObjectIndex(-1) 575 cursor.mergeBlockFormat(bfmt) 576 577 def textColor(self): 578 col = QColorDialog.getColor(self.textEdit.textColor(), self) 579 if not col.isValid(): 580 return 581 582 fmt = QTextCharFormat() 583 fmt.setForeground(col) 584 self.mergeFormatOnWordOrSelection(fmt) 585 self.colorChanged(col) 586 587 def textAlign(self, action): 588 if action == self.actionAlignLeft: 589 self.textEdit.setAlignment(Qt.AlignLeft | Qt.AlignAbsolute) 590 elif action == self.actionAlignCenter: 591 self.textEdit.setAlignment(Qt.AlignHCenter) 592 elif action == self.actionAlignRight: 593 self.textEdit.setAlignment(Qt.AlignRight | Qt.AlignAbsolute) 594 elif action == self.actionAlignJustify: 595 self.textEdit.setAlignment(Qt.AlignJustify) 596 597 def currentCharFormatChanged(self, format): 598 self.fontChanged(format.font()) 599 self.colorChanged(format.foreground().color()) 600 601 def cursorPositionChanged(self): 602 self.alignmentChanged(self.textEdit.alignment()) 603 604 def clipboardDataChanged(self): 605 self.actionPaste.setEnabled(len(QApplication.clipboard().text()) != 0) 606 607 def about(self): 608 QMessageBox.about(self, "About", 609 "This example demonstrates Qt's rich text editing facilities " 610 "in action, providing an example document for you to " 611 "experiment with.") 612 613 def mergeFormatOnWordOrSelection(self, format): 614 cursor = self.textEdit.textCursor() 615 if not cursor.hasSelection(): 616 cursor.select(QTextCursor.WordUnderCursor) 617 618 cursor.mergeCharFormat(format) 619 self.textEdit.mergeCurrentCharFormat(format) 620 621 def fontChanged(self, font): 622 self.comboFont.setCurrentIndex( 623 self.comboFont.findText(QFontInfo(font).family())) 624 self.comboSize.setCurrentIndex( 625 self.comboSize.findText("%s" % font.pointSize())) 626 self.actionTextBold.setChecked(font.bold()) 627 self.actionTextItalic.setChecked(font.italic()) 628 self.actionTextUnderline.setChecked(font.underline()) 629 630 def colorChanged(self, color): 631 pix = QPixmap(16, 16) 632 pix.fill(color) 633 self.actionTextColor.setIcon(QIcon(pix)) 634 635 def alignmentChanged(self, alignment): 636 if alignment & Qt.AlignLeft: 637 self.actionAlignLeft.setChecked(True) 638 elif alignment & Qt.AlignHCenter: 639 self.actionAlignCenter.setChecked(True) 640 elif alignment & Qt.AlignRight: 641 self.actionAlignRight.setChecked(True) 642 elif alignment & Qt.AlignJustify: 643 self.actionAlignJustify.setChecked(True) 644 645 646if __name__ == '__main__': 647 app = QApplication(sys.argv) 648 649 mainWindows = [] 650 for fn in sys.argv[1:] or [None]: 651 textEdit = TextEdit(fn) 652 textEdit.resize(700, 800) 653 textEdit.show() 654 mainWindows.append(textEdit) 655 656 sys.exit(app.exec_()) 657