demos/textedit/textedit.cpp
changeset 0 1918ee327afb
child 3 41300fa6a67c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/demos/textedit/textedit.cpp	Mon Jan 11 14:00:40 2010 +0000
@@ -0,0 +1,732 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the demonstration applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights.  These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "textedit.h"
+
+#include <QAction>
+#include <QApplication>
+#include <QClipboard>
+#include <QColorDialog>
+#include <QComboBox>
+#include <QFontComboBox>
+#include <QFile>
+#include <QFileDialog>
+#include <QFileInfo>
+#include <QFontDatabase>
+#include <QMenu>
+#include <QMenuBar>
+#include <QPrintDialog>
+#include <QPrinter>
+#include <QTextCodec>
+#include <QTextEdit>
+#include <QToolBar>
+#include <QTextCursor>
+#include <QTextDocumentWriter>
+#include <QTextList>
+#include <QtDebug>
+#include <QCloseEvent>
+#include <QMessageBox>
+#include <QPrintPreviewDialog>
+
+#ifdef Q_WS_MAC
+const QString rsrcPath = ":/images/mac";
+#else
+const QString rsrcPath = ":/images/win";
+#endif
+
+TextEdit::TextEdit(QWidget *parent)
+    : QMainWindow(parent)
+{
+    setToolButtonStyle(Qt::ToolButtonFollowStyle);
+    setupFileActions();
+    setupEditActions();
+    setupTextActions();
+
+    {
+        QMenu *helpMenu = new QMenu(tr("Help"), this);
+        menuBar()->addMenu(helpMenu);
+        helpMenu->addAction(tr("About"), this, SLOT(about()));
+        helpMenu->addAction(tr("About &Qt"), qApp, SLOT(aboutQt()));
+    }
+
+    textEdit = new QTextEdit(this);
+    connect(textEdit, SIGNAL(currentCharFormatChanged(const QTextCharFormat &)),
+            this, SLOT(currentCharFormatChanged(const QTextCharFormat &)));
+    connect(textEdit, SIGNAL(cursorPositionChanged()),
+            this, SLOT(cursorPositionChanged()));
+
+    setCentralWidget(textEdit);
+    textEdit->setFocus();
+    setCurrentFileName(QString());
+
+    fontChanged(textEdit->font());
+    colorChanged(textEdit->textColor());
+    alignmentChanged(textEdit->alignment());
+
+    connect(textEdit->document(), SIGNAL(modificationChanged(bool)),
+            actionSave, SLOT(setEnabled(bool)));
+    connect(textEdit->document(), SIGNAL(modificationChanged(bool)),
+            this, SLOT(setWindowModified(bool)));
+    connect(textEdit->document(), SIGNAL(undoAvailable(bool)),
+            actionUndo, SLOT(setEnabled(bool)));
+    connect(textEdit->document(), SIGNAL(redoAvailable(bool)),
+            actionRedo, SLOT(setEnabled(bool)));
+
+    setWindowModified(textEdit->document()->isModified());
+    actionSave->setEnabled(textEdit->document()->isModified());
+    actionUndo->setEnabled(textEdit->document()->isUndoAvailable());
+    actionRedo->setEnabled(textEdit->document()->isRedoAvailable());
+
+    connect(actionUndo, SIGNAL(triggered()), textEdit, SLOT(undo()));
+    connect(actionRedo, SIGNAL(triggered()), textEdit, SLOT(redo()));
+
+    actionCut->setEnabled(false);
+    actionCopy->setEnabled(false);
+
+    connect(actionCut, SIGNAL(triggered()), textEdit, SLOT(cut()));
+    connect(actionCopy, SIGNAL(triggered()), textEdit, SLOT(copy()));
+    connect(actionPaste, SIGNAL(triggered()), textEdit, SLOT(paste()));
+
+    connect(textEdit, SIGNAL(copyAvailable(bool)), actionCut, SLOT(setEnabled(bool)));
+    connect(textEdit, SIGNAL(copyAvailable(bool)), actionCopy, SLOT(setEnabled(bool)));
+
+#ifndef QT_NO_CLIPBOARD
+    connect(QApplication::clipboard(), SIGNAL(dataChanged()), this, SLOT(clipboardDataChanged()));
+#endif
+
+    QString initialFile = ":/example.html";
+    const QStringList args = QCoreApplication::arguments();
+    if (args.count() == 2)
+        initialFile = args.at(1);
+
+    if (!load(initialFile))
+        fileNew();
+}
+
+void TextEdit::closeEvent(QCloseEvent *e)
+{
+    if (maybeSave())
+        e->accept();
+    else
+        e->ignore();
+}
+
+void TextEdit::setupFileActions()
+{
+    QToolBar *tb = new QToolBar(this);
+    tb->setWindowTitle(tr("File Actions"));
+    addToolBar(tb);
+
+    QMenu *menu = new QMenu(tr("&File"), this);
+    menuBar()->addMenu(menu);
+
+    QAction *a;
+
+    QIcon newIcon = QIcon::fromTheme("document-new", QIcon(rsrcPath + "/filenew.png"));
+    a = new QAction( newIcon, tr("&New"), this);
+    a->setPriority(QAction::LowPriority);
+    a->setShortcut(QKeySequence::New);
+    connect(a, SIGNAL(triggered()), this, SLOT(fileNew()));
+    tb->addAction(a);
+    menu->addAction(a);
+
+    a = new QAction(QIcon::fromTheme("document-open", QIcon(rsrcPath + "/fileopen.png")),
+                    tr("&Open..."), this);
+    a->setShortcut(QKeySequence::Open);
+    connect(a, SIGNAL(triggered()), this, SLOT(fileOpen()));
+    tb->addAction(a);
+    menu->addAction(a);
+
+    menu->addSeparator();
+
+    actionSave = a = new QAction(QIcon::fromTheme("document-save", QIcon(rsrcPath + "/filesave.png")),
+                                 tr("&Save"), this);
+    a->setShortcut(QKeySequence::Save);
+    connect(a, SIGNAL(triggered()), this, SLOT(fileSave()));
+    a->setEnabled(false);
+    tb->addAction(a);
+    menu->addAction(a);
+
+    a = new QAction(tr("Save &As..."), this);
+    a->setPriority(QAction::LowPriority);
+    connect(a, SIGNAL(triggered()), this, SLOT(fileSaveAs()));
+    menu->addAction(a);
+    menu->addSeparator();
+
+#ifndef QT_NO_PRINTER
+    a = new QAction(QIcon::fromTheme("document-print", QIcon(rsrcPath + "/fileprint.png")),
+                    tr("&Print..."), this);
+    a->setPriority(QAction::LowPriority);    
+    a->setShortcut(QKeySequence::Print);
+    connect(a, SIGNAL(triggered()), this, SLOT(filePrint()));
+    tb->addAction(a);
+    menu->addAction(a);
+
+    a = new QAction(QIcon::fromTheme("fileprint", QIcon(rsrcPath + "/fileprint.png")),
+                    tr("Print Preview..."), this);
+    connect(a, SIGNAL(triggered()), this, SLOT(filePrintPreview()));
+    menu->addAction(a);
+
+    a = new QAction(QIcon::fromTheme("exportpdf", QIcon(rsrcPath + "/exportpdf.png")),
+    tr("&Export PDF..."), this);
+    a->setPriority(QAction::LowPriority);
+    a->setShortcut(Qt::CTRL + Qt::Key_D);
+    connect(a, SIGNAL(triggered()), this, SLOT(filePrintPdf()));
+    tb->addAction(a);
+    menu->addAction(a);
+
+    menu->addSeparator();
+#endif
+
+    a = new QAction(tr("&Quit"), this);
+    a->setShortcut(Qt::CTRL + Qt::Key_Q);
+    connect(a, SIGNAL(triggered()), this, SLOT(close()));
+    menu->addAction(a);
+}
+
+void TextEdit::setupEditActions()
+{
+    QToolBar *tb = new QToolBar(this);
+    tb->setWindowTitle(tr("Edit Actions"));
+    addToolBar(tb);
+    QMenu *menu = new QMenu(tr("&Edit"), this);
+    menuBar()->addMenu(menu);
+
+    QAction *a;
+    a = actionUndo = new QAction(QIcon::fromTheme("edit-undo", QIcon(rsrcPath + "/editundo.png")),
+                                              tr("&Undo"), this);
+    a->setShortcut(QKeySequence::Undo);
+    tb->addAction(a);
+    menu->addAction(a);
+    a = actionRedo = new QAction(QIcon::fromTheme("edit-redo", QIcon(rsrcPath + "/editredo.png")),
+                                              tr("&Redo"), this);
+    a->setPriority(QAction::LowPriority);
+    a->setShortcut(QKeySequence::Redo);
+    tb->addAction(a);
+    menu->addAction(a);
+    menu->addSeparator();
+    a = actionCut = new QAction(QIcon::fromTheme("edit-cut", QIcon(rsrcPath + "/editcut.png")),
+                                             tr("Cu&t"), this);
+    a->setPriority(QAction::LowPriority);
+    a->setShortcut(QKeySequence::Cut);
+    tb->addAction(a);
+    menu->addAction(a);
+    a = actionCopy = new QAction(QIcon::fromTheme("edit-copy", QIcon(rsrcPath + "/editcopy.png")),
+                                 tr("&Copy"), this);
+    a->setPriority(QAction::LowPriority);
+    a->setShortcut(QKeySequence::Copy);
+    tb->addAction(a);
+    menu->addAction(a);
+    a = actionPaste = new QAction(QIcon::fromTheme("edit-paste", QIcon(rsrcPath + "/editpaste.png")),
+                                  tr("&Paste"), this);
+    a->setPriority(QAction::LowPriority);
+    a->setShortcut(QKeySequence::Paste);
+    tb->addAction(a);
+    menu->addAction(a);
+#ifndef QT_NO_CLIPBOARD
+    actionPaste->setEnabled(!QApplication::clipboard()->text().isEmpty());
+#endif
+}
+
+void TextEdit::setupTextActions()
+{
+    QToolBar *tb = new QToolBar(this);
+    tb->setWindowTitle(tr("Format Actions"));
+    addToolBar(tb);
+
+    QMenu *menu = new QMenu(tr("F&ormat"), this);
+    menuBar()->addMenu(menu);
+
+    actionTextBold = new QAction(QIcon::fromTheme("format-text-bold", QIcon(rsrcPath + "/textbold.png")),
+                                 tr("&Bold"), this);
+    actionTextBold->setShortcut(Qt::CTRL + Qt::Key_B);
+    actionTextBold->setPriority(QAction::LowPriority);
+	QFont bold;
+    bold.setBold(true);
+    actionTextBold->setFont(bold);
+    connect(actionTextBold, SIGNAL(triggered()), this, SLOT(textBold()));
+    tb->addAction(actionTextBold);
+    menu->addAction(actionTextBold);
+    actionTextBold->setCheckable(true);
+
+    actionTextItalic = new QAction(QIcon::fromTheme("format-text-italic", QIcon(rsrcPath + "/textitalic.png")),
+                                   tr("&Italic"), this);
+    actionTextItalic->setPriority(QAction::LowPriority);
+    actionTextItalic->setShortcut(Qt::CTRL + Qt::Key_I);
+    QFont italic;
+    italic.setItalic(true);
+    actionTextItalic->setFont(italic);
+    connect(actionTextItalic, SIGNAL(triggered()), this, SLOT(textItalic()));
+    tb->addAction(actionTextItalic);
+    menu->addAction(actionTextItalic);
+    actionTextItalic->setCheckable(true);
+
+    actionTextUnderline = new QAction(QIcon::fromTheme("format-text-underline", QIcon(rsrcPath + "/textunder.png")),
+                                      tr("&Underline"), this);
+    actionTextUnderline->setShortcut(Qt::CTRL + Qt::Key_U);
+    actionTextUnderline->setPriority(QAction::LowPriority);
+    QFont underline;
+    underline.setUnderline(true);
+    actionTextUnderline->setFont(underline);
+    connect(actionTextUnderline, SIGNAL(triggered()), this, SLOT(textUnderline()));
+    tb->addAction(actionTextUnderline);
+    menu->addAction(actionTextUnderline);
+    actionTextUnderline->setCheckable(true);
+
+    menu->addSeparator();
+
+    QActionGroup *grp = new QActionGroup(this);
+    connect(grp, SIGNAL(triggered(QAction *)), this, SLOT(textAlign(QAction *)));
+
+    // Make sure the alignLeft  is always left of the alignRight
+    if (QApplication::isLeftToRight()) {
+        actionAlignLeft = new QAction(QIcon::fromTheme("format-justify-left", QIcon(rsrcPath + "/textleft.png")),
+                                      tr("&Left"), grp);
+        actionAlignCenter = new QAction(QIcon::fromTheme("format-justify-center", QIcon(rsrcPath + "/textcenter.png")), tr("C&enter"), grp);
+        actionAlignRight = new QAction(QIcon::fromTheme("format-justify-right", QIcon(rsrcPath + "/textright.png")), tr("&Right"), grp);
+    } else {
+        actionAlignRight = new QAction(QIcon::fromTheme("format-justify-right", QIcon(rsrcPath + "/textright.png")), tr("&Right"), grp);
+        actionAlignCenter = new QAction(QIcon::fromTheme("format-justify-center", QIcon(rsrcPath + "/textcenter.png")), tr("C&enter"), grp);
+        actionAlignLeft = new QAction(QIcon::fromTheme("format-justify-left", QIcon(rsrcPath + "/textleft.png")), tr("&Left"), grp);
+    }
+    actionAlignJustify = new QAction(QIcon::fromTheme("format-justify-fill", QIcon(rsrcPath + "/textjustify.png")), tr("&Justify"), grp);
+
+    actionAlignLeft->setShortcut(Qt::CTRL + Qt::Key_L);
+    actionAlignLeft->setCheckable(true);
+    actionAlignLeft->setPriority(QAction::LowPriority);
+    actionAlignCenter->setShortcut(Qt::CTRL + Qt::Key_E);
+    actionAlignCenter->setCheckable(true);
+    actionAlignCenter->setPriority(QAction::LowPriority);
+    actionAlignRight->setShortcut(Qt::CTRL + Qt::Key_R);
+    actionAlignRight->setCheckable(true);
+    actionAlignRight->setPriority(QAction::LowPriority);
+    actionAlignJustify->setShortcut(Qt::CTRL + Qt::Key_J);
+    actionAlignJustify->setCheckable(true);
+    actionAlignJustify->setPriority(QAction::LowPriority);
+
+    tb->addActions(grp->actions());
+    menu->addActions(grp->actions());
+
+    menu->addSeparator();
+
+    QPixmap pix(16, 16);
+    pix.fill(Qt::black);
+    actionTextColor = new QAction(pix, tr("&Color..."), this);
+    connect(actionTextColor, SIGNAL(triggered()), this, SLOT(textColor()));
+    tb->addAction(actionTextColor);
+    menu->addAction(actionTextColor);
+
+
+    tb = new QToolBar(this);
+    tb->setAllowedAreas(Qt::TopToolBarArea | Qt::BottomToolBarArea);
+    tb->setWindowTitle(tr("Format Actions"));
+    addToolBarBreak(Qt::TopToolBarArea);
+    addToolBar(tb);
+
+    comboStyle = new QComboBox(tb);
+    tb->addWidget(comboStyle);
+    comboStyle->addItem("Standard");
+    comboStyle->addItem("Bullet List (Disc)");
+    comboStyle->addItem("Bullet List (Circle)");
+    comboStyle->addItem("Bullet List (Square)");
+    comboStyle->addItem("Ordered List (Decimal)");
+    comboStyle->addItem("Ordered List (Alpha lower)");
+    comboStyle->addItem("Ordered List (Alpha upper)");
+    comboStyle->addItem("Ordered List (Roman lower)");
+    comboStyle->addItem("Ordered List (Roman upper)");
+    connect(comboStyle, SIGNAL(activated(int)),
+            this, SLOT(textStyle(int)));
+
+    comboFont = new QFontComboBox(tb);
+    tb->addWidget(comboFont);
+    connect(comboFont, SIGNAL(activated(const QString &)),
+            this, SLOT(textFamily(const QString &)));
+
+    comboSize = new QComboBox(tb);
+    comboSize->setObjectName("comboSize");
+    tb->addWidget(comboSize);
+    comboSize->setEditable(true);
+
+    QFontDatabase db;
+    foreach(int size, db.standardSizes())
+        comboSize->addItem(QString::number(size));
+
+    connect(comboSize, SIGNAL(activated(const QString &)),
+            this, SLOT(textSize(const QString &)));
+    comboSize->setCurrentIndex(comboSize->findText(QString::number(QApplication::font()
+                                                                   .pointSize())));
+}
+
+bool TextEdit::load(const QString &f)
+{
+    if (!QFile::exists(f))
+        return false;
+    QFile file(f);
+    if (!file.open(QFile::ReadOnly))
+        return false;
+
+    QByteArray data = file.readAll();
+    QTextCodec *codec = Qt::codecForHtml(data);
+    QString str = codec->toUnicode(data);
+    if (Qt::mightBeRichText(str)) {
+        textEdit->setHtml(str);
+    } else {
+        str = QString::fromLocal8Bit(data);
+        textEdit->setPlainText(str);
+    }
+
+    setCurrentFileName(f);
+    return true;
+}
+
+bool TextEdit::maybeSave()
+{
+    if (!textEdit->document()->isModified())
+        return true;
+    if (fileName.startsWith(QLatin1String(":/")))
+        return true;
+    QMessageBox::StandardButton ret;
+    ret = QMessageBox::warning(this, tr("Application"),
+                               tr("The document has been modified.\n"
+                                  "Do you want to save your changes?"),
+                               QMessageBox::Save | QMessageBox::Discard
+                               | QMessageBox::Cancel);
+    if (ret == QMessageBox::Save)
+        return fileSave();
+    else if (ret == QMessageBox::Cancel)
+        return false;
+    return true;
+}
+
+void TextEdit::setCurrentFileName(const QString &fileName)
+{
+    this->fileName = fileName;
+    textEdit->document()->setModified(false);
+
+    QString shownName;
+    if (fileName.isEmpty())
+        shownName = "untitled.txt";
+    else
+        shownName = QFileInfo(fileName).fileName();
+
+    setWindowTitle(tr("%1[*] - %2").arg(shownName).arg(tr("Rich Text")));
+    setWindowModified(false);
+}
+
+void TextEdit::fileNew()
+{
+    if (maybeSave()) {
+        textEdit->clear();
+        setCurrentFileName(QString());
+    }
+}
+
+void TextEdit::fileOpen()
+{
+    QString fn = QFileDialog::getOpenFileName(this, tr("Open File..."),
+                                              QString(), tr("HTML-Files (*.htm *.html);;All Files (*)"));
+    if (!fn.isEmpty())
+        load(fn);
+}
+
+bool TextEdit::fileSave()
+{
+    if (fileName.isEmpty())
+        return fileSaveAs();
+
+    QTextDocumentWriter writer(fileName);
+    bool success = writer.write(textEdit->document());
+    if (success)
+        textEdit->document()->setModified(false);
+    return success;
+}
+
+bool TextEdit::fileSaveAs()
+{
+    QString fn = QFileDialog::getSaveFileName(this, tr("Save as..."),
+                                              QString(), tr("ODF files (*.odt);;HTML-Files (*.htm *.html);;All Files (*)"));
+    if (fn.isEmpty())
+        return false;
+    if (! (fn.endsWith(".odt", Qt::CaseInsensitive) || fn.endsWith(".htm", Qt::CaseInsensitive) || fn.endsWith(".html", Qt::CaseInsensitive)) )
+        fn += ".odt"; // default
+    setCurrentFileName(fn);
+    return fileSave();
+}
+
+void TextEdit::filePrint()
+{
+#ifndef QT_NO_PRINTER
+    QPrinter printer(QPrinter::HighResolution);
+    QPrintDialog *dlg = new QPrintDialog(&printer, this);
+    if (textEdit->textCursor().hasSelection())
+        dlg->addEnabledOption(QAbstractPrintDialog::PrintSelection);
+    dlg->setWindowTitle(tr("Print Document"));
+    if (dlg->exec() == QDialog::Accepted) {
+        textEdit->print(&printer);
+    }
+    delete dlg;
+#endif
+}
+
+void TextEdit::filePrintPreview()
+{
+#ifndef QT_NO_PRINTER
+    QPrinter printer(QPrinter::HighResolution);
+    QPrintPreviewDialog preview(&printer, this);
+    connect(&preview, SIGNAL(paintRequested(QPrinter *)), SLOT(printPreview(QPrinter *)));
+    preview.exec();
+#endif
+}
+
+void TextEdit::printPreview(QPrinter *printer)
+{
+#ifdef QT_NO_PRINTER
+    Q_UNUSED(printer);
+#else
+    textEdit->print(printer);
+#endif
+}
+
+
+void TextEdit::filePrintPdf()
+{
+#ifndef QT_NO_PRINTER
+//! [0]
+    QString fileName = QFileDialog::getSaveFileName(this, "Export PDF",
+                                                    QString(), "*.pdf");
+    if (!fileName.isEmpty()) {
+        if (QFileInfo(fileName).suffix().isEmpty())
+            fileName.append(".pdf");
+        QPrinter printer(QPrinter::HighResolution);
+        printer.setOutputFormat(QPrinter::PdfFormat);
+        printer.setOutputFileName(fileName);
+        textEdit->document()->print(&printer);
+    }
+//! [0]
+#endif
+}
+
+void TextEdit::textBold()
+{
+    QTextCharFormat fmt;
+    fmt.setFontWeight(actionTextBold->isChecked() ? QFont::Bold : QFont::Normal);
+    mergeFormatOnWordOrSelection(fmt);
+}
+
+void TextEdit::textUnderline()
+{
+    QTextCharFormat fmt;
+    fmt.setFontUnderline(actionTextUnderline->isChecked());
+    mergeFormatOnWordOrSelection(fmt);
+}
+
+void TextEdit::textItalic()
+{
+    QTextCharFormat fmt;
+    fmt.setFontItalic(actionTextItalic->isChecked());
+    mergeFormatOnWordOrSelection(fmt);
+}
+
+void TextEdit::textFamily(const QString &f)
+{
+    QTextCharFormat fmt;
+    fmt.setFontFamily(f);
+    mergeFormatOnWordOrSelection(fmt);
+}
+
+void TextEdit::textSize(const QString &p)
+{
+    qreal pointSize = p.toFloat();
+    if (p.toFloat() > 0) {
+        QTextCharFormat fmt;
+        fmt.setFontPointSize(pointSize);
+        mergeFormatOnWordOrSelection(fmt);
+    }
+}
+
+void TextEdit::textStyle(int styleIndex)
+{
+    QTextCursor cursor = textEdit->textCursor();
+
+    if (styleIndex != 0) {
+        QTextListFormat::Style style = QTextListFormat::ListDisc;
+
+        switch (styleIndex) {
+            default:
+            case 1:
+                style = QTextListFormat::ListDisc;
+                break;
+            case 2:
+                style = QTextListFormat::ListCircle;
+                break;
+            case 3:
+                style = QTextListFormat::ListSquare;
+                break;
+            case 4:
+                style = QTextListFormat::ListDecimal;
+                break;
+            case 5:
+                style = QTextListFormat::ListLowerAlpha;
+                break;
+            case 6:
+                style = QTextListFormat::ListUpperAlpha;
+                break;
+            case 7:
+                style = QTextListFormat::ListLowerRoman;
+                break;
+            case 8:
+                style = QTextListFormat::ListUpperRoman;
+                break;
+        }
+
+        cursor.beginEditBlock();
+
+        QTextBlockFormat blockFmt = cursor.blockFormat();
+
+        QTextListFormat listFmt;
+
+        if (cursor.currentList()) {
+            listFmt = cursor.currentList()->format();
+        } else {
+            listFmt.setIndent(blockFmt.indent() + 1);
+            blockFmt.setIndent(0);
+            cursor.setBlockFormat(blockFmt);
+        }
+
+        listFmt.setStyle(style);
+
+        cursor.createList(listFmt);
+
+        cursor.endEditBlock();
+    } else {
+        // ####
+        QTextBlockFormat bfmt;
+        bfmt.setObjectIndex(-1);
+        cursor.mergeBlockFormat(bfmt);
+    }
+}
+
+void TextEdit::textColor()
+{
+    QColor col = QColorDialog::getColor(textEdit->textColor(), this);
+    if (!col.isValid())
+        return;
+    QTextCharFormat fmt;
+    fmt.setForeground(col);
+    mergeFormatOnWordOrSelection(fmt);
+    colorChanged(col);
+}
+
+void TextEdit::textAlign(QAction *a)
+{
+    if (a == actionAlignLeft)
+        textEdit->setAlignment(Qt::AlignLeft | Qt::AlignAbsolute);
+    else if (a == actionAlignCenter)
+        textEdit->setAlignment(Qt::AlignHCenter);
+    else if (a == actionAlignRight)
+        textEdit->setAlignment(Qt::AlignRight | Qt::AlignAbsolute);
+    else if (a == actionAlignJustify)
+        textEdit->setAlignment(Qt::AlignJustify);
+}
+
+void TextEdit::currentCharFormatChanged(const QTextCharFormat &format)
+{
+    fontChanged(format.font());
+    colorChanged(format.foreground().color());
+}
+
+void TextEdit::cursorPositionChanged()
+{
+    alignmentChanged(textEdit->alignment());
+}
+
+void TextEdit::clipboardDataChanged()
+{
+#ifndef QT_NO_CLIPBOARD
+    actionPaste->setEnabled(!QApplication::clipboard()->text().isEmpty());
+#endif
+}
+
+void TextEdit::about()
+{
+    QMessageBox::about(this, tr("About"), tr("This example demonstrates Qt's "
+        "rich text editing facilities in action, providing an example "
+        "document for you to experiment with."));
+}
+
+void TextEdit::mergeFormatOnWordOrSelection(const QTextCharFormat &format)
+{
+    QTextCursor cursor = textEdit->textCursor();
+    if (!cursor.hasSelection())
+        cursor.select(QTextCursor::WordUnderCursor);
+    cursor.mergeCharFormat(format);
+    textEdit->mergeCurrentCharFormat(format);
+}
+
+void TextEdit::fontChanged(const QFont &f)
+{
+    comboFont->setCurrentIndex(comboFont->findText(QFontInfo(f).family()));
+    comboSize->setCurrentIndex(comboSize->findText(QString::number(f.pointSize())));
+    actionTextBold->setChecked(f.bold());
+    actionTextItalic->setChecked(f.italic());
+    actionTextUnderline->setChecked(f.underline());
+}
+
+void TextEdit::colorChanged(const QColor &c)
+{
+    QPixmap pix(16, 16);
+    pix.fill(c);
+    actionTextColor->setIcon(pix);
+}
+
+void TextEdit::alignmentChanged(Qt::Alignment a)
+{
+    if (a & Qt::AlignLeft) {
+        actionAlignLeft->setChecked(true);
+    } else if (a & Qt::AlignHCenter) {
+        actionAlignCenter->setChecked(true);
+    } else if (a & Qt::AlignRight) {
+        actionAlignRight->setChecked(true);
+    } else if (a & Qt::AlignJustify) {
+        actionAlignJustify->setChecked(true);
+    }
+}
+