#include "lts_text_editor2.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #if defined(QT_PRINTSUPPORT_LIB) #include #if QT_CONFIG(printer) #if QT_CONFIG(printdialog) #include #endif #include #if QT_CONFIG(printpreviewdialog) #include #endif #endif #endif #include #ifdef Q_OS_MAC inline QString rsrcPath(){ QStringLiteral(":/images/mac");} #else inline QString rsrcPath(){return QStringLiteral(":/images/win");} #endif namespace LtsWidgets { LtsTextEditor2::LtsTextEditor2(QWidget *parent) : QMainWindow(parent) { setWindowFlags(Qt::CustomizeWindowHint ); setWindowTitle(QCoreApplication::applicationName()); m_textEdit = new QTextEdit(this); connect(m_textEdit, &QTextEdit::currentCharFormatChanged, this, &LtsTextEditor2::currentCharFormatChanged); connect(m_textEdit, &QTextEdit::cursorPositionChanged, this, &LtsTextEditor2::cursorPositionChanged); setCentralWidget(m_textEdit); setToolButtonStyle(Qt::ToolButtonFollowStyle); setupFileActions(); setupEditActions(); setupTextActions(); { QMenu *helpMenu = menuBar()->addMenu(tr("Help")); helpMenu->addAction(tr("About"), this, &LtsTextEditor2::about); helpMenu->addAction(tr("About &Qt"), qApp, &QApplication::aboutQt); } QFont textFont(QStringLiteral("Helvetica")); textFont.setStyleHint(QFont::SansSerif); m_textEdit->setFont(textFont); fontChanged(m_textEdit->font()); colorChanged(m_textEdit->textColor()); alignmentChanged(m_textEdit->alignment()); connect(m_textEdit->document(), &QTextDocument::modificationChanged, m_actionSave, &QAction::setEnabled); connect(m_textEdit->document(), &QTextDocument::modificationChanged, this, &QWidget::setWindowModified); connect(m_textEdit->document(), &QTextDocument::undoAvailable, m_actionUndo, &QAction::setEnabled); connect(m_textEdit->document(), &QTextDocument::redoAvailable, m_actionRedo, &QAction::setEnabled); setWindowModified(m_textEdit->document()->isModified()); m_actionSave->setEnabled(m_textEdit->document()->isModified()); m_actionUndo->setEnabled(m_textEdit->document()->isUndoAvailable()); m_actionRedo->setEnabled(m_textEdit->document()->isRedoAvailable()); #ifndef QT_NO_CLIPBOARD m_actionCut->setEnabled(false); connect(m_textEdit, &QTextEdit::copyAvailable, m_actionCut, &QAction::setEnabled); m_actionCopy->setEnabled(false); connect(m_textEdit, &QTextEdit::copyAvailable, m_actionCopy, &QAction::setEnabled); connect(QApplication::clipboard(), &QClipboard::dataChanged, this, &LtsTextEditor2::clipboardDataChanged); #endif m_textEdit->setFocus(); setCurrentFileName(QString()); this->menuBar()->hide(); m_actionSave->setVisible(false); m_actionOpen->setVisible(false); m_actionQuit->setVisible(false); m_actionSaveAs->setVisible(false); m_actionNew->setVisible(false); #if defined(QT_PRINTSUPPORT_LIB) && QT_CONFIG(printer) actionPrint->setVisible(false); actionPreview->setVisible(false); actionExport->setVisible(false); #endif m_actionToggleCheckState->setVisible(false); m_actionToggleCheckState->setVisible(false); m_actionIndentLess->setVisible(false); m_actionIndentMore->setVisible(false); m_comboStyleAction->setVisible(false); m_actionToggleCheckState->setVisible(false); } LtsTextEditor2::~LtsTextEditor2() { } QTextEdit *LtsTextEditor2::textEdit() { return m_textEdit; } QColor LtsTextEditor2::backgroundColor() const { return m_backgroundColor; } void LtsTextEditor2::setInitialBackgroundColor(const QColor &bgColor) { if (bgColor.isValid()) m_backgroundColor = bgColor; slotBackgroundColorChanged(m_backgroundColor); } void LtsTextEditor2::enableBackgroundColor(bool onOff) { m_actionBackgroundColor->setVisible(onOff); } void LtsTextEditor2::slotBackgroundColorChanged(const QColor &bgColor) { QPixmap pix(16, 16); pix.fill(bgColor); m_actionBackgroundColor->setIcon(pix); } void LtsTextEditor2::slotBackgroundColor() { QColor col = QColorDialog::getColor(m_backgroundColor.isValid() ? m_backgroundColor : Qt::white, this); if (!col.isValid()) return; m_backgroundColor = col; slotBackgroundColorChanged(m_backgroundColor); emit backgroundColorChanged(m_backgroundColor); } void LtsTextEditor2::setupFileActions() { QToolBar *tb = addToolBar(tr("File Actions")); QMenu *menu = menuBar()->addMenu(tr("&File")); const QIcon newIcon = QIcon::fromTheme(QStringLiteral("document-new"), QIcon(rsrcPath() + QStringLiteral("/filenew.png"))); m_actionNew = menu->addAction(newIcon, tr("&New"), this, &LtsTextEditor2::onFileNew); tb->addAction(m_actionNew); m_actionNew->setPriority(QAction::LowPriority); m_actionNew->setShortcut(QKeySequence::New); const QIcon openIcon = QIcon::fromTheme(QStringLiteral("document-open"), QIcon(rsrcPath() + QStringLiteral("/fileopen.png"))); m_actionOpen = menu->addAction(openIcon, tr("&Open..."), this, &LtsTextEditor2::onFileOpen); m_actionOpen->setShortcut(QKeySequence::Open); tb->addAction(m_actionOpen); menu->addSeparator(); const QIcon saveIcon = QIcon::fromTheme(QStringLiteral("document-save"), QIcon(rsrcPath()+ QStringLiteral("/filesave.png"))); m_actionSave = menu->addAction(saveIcon, tr("&Save"), this, &LtsTextEditor2::onFileSave); m_actionSave->setShortcut(QKeySequence::Save); m_actionSave->setEnabled(false); tb->addAction(m_actionSave); m_actionSaveAs = menu->addAction(tr("Save &As..."), this, &LtsTextEditor2::onFileSaveAs); m_actionSaveAs->setPriority(QAction::LowPriority); menu->addSeparator(); #if defined(QT_PRINTSUPPORT_LIB) && QT_CONFIG(printer) const QIcon printIcon = QIcon::fromTheme(QStringLiteral("document-print"), QIcon(rsrcPath()+ QStringLiteral("/fileprint.png"))); actionPrint = menu->addAction(printIcon, tr("&Print..."), this, &LtsTextEditor2::filePrint); actionPrint->setPriority(QAction::LowPriority); actionPrint->setShortcut(QKeySequence::Print); tb->addAction(actionPrint); const QIcon filePrintIcon = QIcon::fromTheme(QStringLiteral("fileprint"), QIcon(rsrcPath()+ QStringLiteral("/fileprint.png"))); actionPreview = menu->addAction(filePrintIcon, tr("Print Preview..."), this, &LtsTextEditor2::filePrintPreview); const QIcon exportPdfIcon = QIcon::fromTheme(QStringLiteral("exportpdf"), QIcon(rsrcPath()+ QStringLiteral("/exportpdf.png"))); actionExport = menu->addAction(exportPdfIcon, tr("&Export PDF..."), this, &LtsTextEditor2::filePrintPdf); actionExport->setPriority(QAction::LowPriority); actionExport->setShortcut(Qt::CTRL + Qt::Key_D); tb->addAction(actionExport); menu->addSeparator(); #endif m_actionQuit = menu->addAction(tr("&Quit"), this, &QWidget::close); m_actionQuit->setShortcut(Qt::CTRL + Qt::Key_Q); } void LtsTextEditor2::setupEditActions() { QToolBar *tb = addToolBar(tr("Edit Actions")); QMenu *menu = menuBar()->addMenu(tr("&Edit")); const QIcon undoIcon = QIcon::fromTheme(QStringLiteral("icon:undo.svg")); m_actionUndo = menu->addAction(undoIcon, {}, m_textEdit, &QTextEdit::undo); m_actionUndo->setToolTip(tr("&Undo")); m_actionUndo->setShortcut(QKeySequence::Undo); tb->addAction(m_actionUndo); const QIcon redoIcon = QIcon::fromTheme(QStringLiteral("icon:redo.svg")); m_actionRedo = menu->addAction(redoIcon, tr("&Redo"), m_textEdit, &QTextEdit::redo); m_actionRedo->setPriority(QAction::LowPriority); m_actionRedo->setShortcut(QKeySequence::Redo); tb->addAction(m_actionRedo); menu->addSeparator(); #ifndef QT_NO_CLIPBOARD const QIcon cutIcon = QIcon::fromTheme(QStringLiteral("icon:edit-cut.svg")); m_actionCut = menu->addAction(cutIcon, tr("Cu&t"), m_textEdit, &QTextEdit::cut); m_actionCut->setPriority(QAction::LowPriority); m_actionCut->setShortcut(QKeySequence::Cut); tb->addAction(m_actionCut); const QIcon copyIcon = QIcon::fromTheme(QStringLiteral("icon:edit-copy.svg")); m_actionCopy = menu->addAction(copyIcon, tr("&Copy"), m_textEdit, &QTextEdit::copy); m_actionCopy->setPriority(QAction::LowPriority); m_actionCopy->setShortcut(QKeySequence::Copy); tb->addAction(m_actionCopy); const QIcon pasteIcon = QIcon::fromTheme(QStringLiteral("icon:edit-paste.svg")); m_actionPaste = menu->addAction(pasteIcon, tr("&Paste"), m_textEdit, &QTextEdit::paste); m_actionPaste->setPriority(QAction::LowPriority); m_actionPaste->setShortcut(QKeySequence::Paste); tb->addAction(m_actionPaste); if (const QMimeData *md = QApplication::clipboard()->mimeData()) m_actionPaste->setEnabled(md->hasText()); #endif } void LtsTextEditor2::setupTextActions() { QToolBar *tb = addToolBar(tr("Format Actions")); QMenu *menu = menuBar()->addMenu(tr("F&ormat")); const QIcon boldIcon = QIcon::fromTheme(QStringLiteral(":icons/22x22/format-text-bold.png")); m_actionTextBold = menu->addAction(boldIcon, tr("&Bold"), this, &LtsTextEditor2::onTextBold); m_actionTextBold->setShortcut(Qt::CTRL + Qt::Key_B); m_actionTextBold->setPriority(QAction::LowPriority); QFont bold; bold.setBold(true); m_actionTextBold->setFont(bold); tb->addAction(m_actionTextBold); m_actionTextBold->setCheckable(true); const QIcon italicIcon = QIcon::fromTheme(QStringLiteral(":icons/22x22/format-text-italic.png")); m_actionTextItalic = menu->addAction(italicIcon, tr("&Italic"), this, &LtsTextEditor2::onTextItalic); m_actionTextItalic->setPriority(QAction::LowPriority); m_actionTextItalic->setShortcut(Qt::CTRL + Qt::Key_I); QFont italic; italic.setItalic(true); m_actionTextItalic->setFont(italic); tb->addAction(m_actionTextItalic); m_actionTextItalic->setCheckable(true); const QIcon underlineIcon = QIcon::fromTheme(QStringLiteral(":icons/22x22/format-text-underline.png")); m_actionTextUnderline = menu->addAction(underlineIcon, tr("&Underline"), this, &LtsTextEditor2::onTextUnderline); m_actionTextUnderline->setShortcut(Qt::CTRL + Qt::Key_U); m_actionTextUnderline->setPriority(QAction::LowPriority); QFont underline; underline.setUnderline(true); m_actionTextUnderline->setFont(underline); tb->addAction(m_actionTextUnderline); m_actionTextUnderline->setCheckable(true); menu->addSeparator(); const QIcon leftIcon = QIcon::fromTheme(QStringLiteral(":icons/22x22/format-justify-left.png")); m_actionAlignLeft = new QAction(leftIcon, tr("&Left"), this); m_actionAlignLeft->setShortcut(Qt::CTRL + Qt::Key_L); m_actionAlignLeft->setCheckable(true); m_actionAlignLeft->setPriority(QAction::LowPriority); const QIcon centerIcon = QIcon::fromTheme(QStringLiteral(":icons/22x22/format-justify-center.png")); m_actionAlignCenter = new QAction(centerIcon, tr("C&enter"), this); m_actionAlignCenter->setShortcut(Qt::CTRL + Qt::Key_E); m_actionAlignCenter->setCheckable(true); m_actionAlignCenter->setPriority(QAction::LowPriority); const QIcon rightIcon = QIcon::fromTheme(QStringLiteral(":icons/22x22/format-justify-right.png")); m_actionAlignRight = new QAction(rightIcon, tr("&Right"), this); m_actionAlignRight->setShortcut(Qt::CTRL + Qt::Key_R); m_actionAlignRight->setCheckable(true); m_actionAlignRight->setPriority(QAction::LowPriority); const QIcon fillIcon = QIcon::fromTheme(QStringLiteral(":icons/22x22/format-justify-fill.png")); m_actionAlignJustify = new QAction(fillIcon, tr("&Justify"), this); m_actionAlignJustify->setShortcut(Qt::CTRL + Qt::Key_J); m_actionAlignJustify->setCheckable(true); m_actionAlignJustify->setPriority(QAction::LowPriority); const QIcon indentMoreIcon = QIcon::fromTheme(QStringLiteral("format-indent-more"), QIcon(rsrcPath()+ QStringLiteral("/format-indent-more.png"))); m_actionIndentMore = menu->addAction(indentMoreIcon, tr("&Indent"), this, &LtsTextEditor2::indent); m_actionIndentMore->setShortcut(Qt::CTRL + Qt::Key_BracketRight); m_actionIndentMore->setPriority(QAction::LowPriority); const QIcon indentLessIcon = QIcon::fromTheme(QStringLiteral("format-indent-less"), QIcon(rsrcPath()+ QStringLiteral("/format-indent-less.png"))); m_actionIndentLess = menu->addAction(indentLessIcon, tr("&Unindent"), this, &LtsTextEditor2::unindent); m_actionIndentLess->setShortcut(Qt::CTRL + Qt::Key_BracketLeft); m_actionIndentLess->setPriority(QAction::LowPriority); QActionGroup *alignGroup = new QActionGroup(this); connect(alignGroup, &QActionGroup::triggered, this, &LtsTextEditor2::onTextAlign); if (QApplication::isLeftToRight()) { alignGroup->addAction(m_actionAlignLeft); alignGroup->addAction(m_actionAlignCenter); alignGroup->addAction(m_actionAlignRight); } else { alignGroup->addAction(m_actionAlignRight); alignGroup->addAction(m_actionAlignCenter); alignGroup->addAction(m_actionAlignLeft); } alignGroup->addAction(m_actionAlignJustify); tb->addActions(alignGroup->actions()); menu->addActions(alignGroup->actions()); tb->addAction(m_actionIndentMore); tb->addAction(m_actionIndentLess); menu->addAction(m_actionIndentMore); menu->addAction(m_actionIndentLess); menu->addSeparator(); QPixmap pix(16, 16); pix.fill(Qt::black); m_actionTextColor = menu->addAction(pix, tr("&Color..."), this, &LtsTextEditor2::onTextColor); m_actionTextColor->setPriority(QAction::LowPriority); tb->addAction(m_actionTextColor); QPixmap pix2(16, 16); pix2.fill(Qt::white); m_actionBackgroundColor = new QAction(pix2, tr("&Background Color"), this); m_actionBackgroundColor->setIcon(pix2); m_actionBackgroundColor->setPriority(QAction::LowPriority); connect(m_actionBackgroundColor, &QAction::triggered, this, &LtsTextEditor2::slotBackgroundColor); tb->addAction(m_actionBackgroundColor); menu->addSeparator(); const QIcon checkboxIcon = QIcon::fromTheme(QStringLiteral("status-checkbox-checked"), QIcon(rsrcPath()+ QStringLiteral("/checkbox-checked.png"))); m_actionToggleCheckState = menu->addAction(checkboxIcon, tr("Chec&ked"), this, &LtsTextEditor2::setChecked); m_actionToggleCheckState->setShortcut(Qt::CTRL + Qt::Key_K); m_actionToggleCheckState->setCheckable(true); m_actionToggleCheckState->setPriority(QAction::LowPriority); tb->addAction(m_actionToggleCheckState); m_comboStyle = new QComboBox(tb); m_comboStyleAction = tb->addWidget(m_comboStyle); m_comboStyle->addItem(QStringLiteral("Standard")); m_comboStyle->addItem(QStringLiteral("Bullet List (Disc)")); m_comboStyle->addItem(QStringLiteral("Bullet List (Circle)")); m_comboStyle->addItem(QStringLiteral("Bullet List (Square)")); m_comboStyle->addItem(QStringLiteral("Task List (Unchecked)")); m_comboStyle->addItem(QStringLiteral("Task List (Checked)")); m_comboStyle->addItem(QStringLiteral("Ordered List (Decimal)")); m_comboStyle->addItem(QStringLiteral("Ordered List (Alpha lower)")); m_comboStyle->addItem(QStringLiteral("Ordered List (Alpha upper)")); m_comboStyle->addItem(QStringLiteral("Ordered List (Roman lower)")); m_comboStyle->addItem(QStringLiteral("Ordered List (Roman upper)")); m_comboStyle->addItem(QStringLiteral("Heading 1")); m_comboStyle->addItem(QStringLiteral("Heading 2")); m_comboStyle->addItem(QStringLiteral("Heading 3")); m_comboStyle->addItem(QStringLiteral("Heading 4")); m_comboStyle->addItem(QStringLiteral("Heading 5")); m_comboStyle->addItem(QStringLiteral("Heading 6")); connect(m_comboStyle, QOverload::of(&QComboBox::activated), this, &LtsTextEditor2::onTextStyle); m_comboFont = new QFontComboBox(tb); tb->addWidget(m_comboFont); connect(m_comboFont, &QComboBox::textActivated, this, &LtsTextEditor2::onTextFamily); m_comboSize = new QComboBox(tb); m_comboSize->setObjectName(QStringLiteral("comboSize")); tb->addWidget(m_comboSize); m_comboSize->setEditable(true); const QList standardSizes = QFontDatabase::standardSizes(); for (int size : standardSizes) m_comboSize->addItem(QString::number(size)); m_comboSize->setCurrentIndex(standardSizes.indexOf(QApplication::font().pointSize())); connect(m_comboSize, &QComboBox::textActivated, this, &LtsTextEditor2::onTextSize); } bool LtsTextEditor2::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)) { QUrl baseUrl = (f.front() == QLatin1Char(':') ? QUrl(f) : QUrl::fromLocalFile(f)).adjusted(QUrl::RemoveFilename); m_textEdit->document()->setBaseUrl(baseUrl); m_textEdit->setHtml(str); } else { #if QT_CONFIG(textmarkdownreader) QMimeDatabase db; if (db.mimeTypeForFileNameAndData(f, data).name() == QStringLiteral("text/markdown")) m_textEdit->setMarkdown(QString::fromUtf8(data)); else #endif m_textEdit->setPlainText(QString::fromUtf8(data)); } setCurrentFileName(f); return true; } bool LtsTextEditor2::maybeSave() { if (!m_textEdit->document()->isModified()) return true; const QMessageBox::StandardButton ret = QMessageBox::warning(this, QCoreApplication::applicationName(), 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 onFileSave(); else if (ret == QMessageBox::Cancel) return false; return true; } void LtsTextEditor2::setCurrentFileName(const QString &fileName) { this->m_fileName = fileName; m_textEdit->document()->setModified(false); QString shownName; if (fileName.isEmpty()) shownName = QStringLiteral("untitled.txt"); else shownName = QFileInfo(fileName).fileName(); setWindowTitle(tr("%1[*] - %2").arg(shownName, QCoreApplication::applicationName())); setWindowModified(false); } void LtsTextEditor2::onFileNew() { if (maybeSave()) { m_textEdit->clear(); setCurrentFileName(QString()); } } void LtsTextEditor2::onFileOpen() { QFileDialog fileDialog(this, tr("Open File...")); fileDialog.setAcceptMode(QFileDialog::AcceptOpen); fileDialog.setFileMode(QFileDialog::ExistingFile); fileDialog.setMimeTypeFilters(QStringList() #if QT_CONFIG(texthtmlparser) << QStringLiteral("text/html") #endif #if QT_CONFIG(textmarkdownreader) << QStringLiteral("text/markdown") #endif << QStringLiteral("text/plain")); if (fileDialog.exec() != QDialog::Accepted) return; const QStringList &fileNameList = fileDialog.selectedFiles(); if (fileNameList.isEmpty()) return; QString fn = fileNameList.constFirst(); if (load(fn)) statusBar()->showMessage(tr("Opened \"%1\"").arg(QDir::toNativeSeparators(fn))); else statusBar()->showMessage(tr("Could not open \"%1\"").arg(QDir::toNativeSeparators(fn))); } bool LtsTextEditor2::onFileSave() { if (m_fileName.isEmpty()) return onFileSaveAs(); if (m_fileName.startsWith(QStringLiteral(":/"))) return onFileSaveAs(); QTextDocumentWriter writer(m_fileName); bool success = writer.write(m_textEdit->document()); if (success) { m_textEdit->document()->setModified(false); statusBar()->showMessage(tr("Wrote \"%1\"").arg(QDir::toNativeSeparators(m_fileName))); } else { statusBar()->showMessage(tr("Could not write to file \"%1\"") .arg(QDir::toNativeSeparators(m_fileName))); } return success; } bool LtsTextEditor2::onFileSaveAs() { QFileDialog fileDialog(this, tr("Save as...")); fileDialog.setAcceptMode(QFileDialog::AcceptSave); QStringList mimeTypes; mimeTypes << QStringLiteral("text/plain") #if QT_CONFIG(textodfwriter) << QStringLiteral("application/vnd.oasis.opendocument.text") #endif #if QT_CONFIG(textmarkdownwriter) << QStringLiteral("text/markdown") #endif << QStringLiteral("text/html"); fileDialog.setMimeTypeFilters(mimeTypes); #if QT_CONFIG(textodfwriter) fileDialog.setDefaultSuffix(QStringLiteral("odt")); #endif if (fileDialog.exec() != QDialog::Accepted) return false; const QStringList &fileNameList = fileDialog.selectedFiles(); if (fileNameList.isEmpty()) return false; QString fn = fileNameList.constFirst(); setCurrentFileName(fn); return onFileSave(); } void LtsTextEditor2::onFilePrint() { #if defined(QT_PRINTSUPPORT_LIB) && QT_CONFIG(printdialog) 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 LtsTextEditor2::onFilePrintPreview() { #if defined(QT_PRINTSUPPORT_LIB) && QT_CONFIG(printpreviewdialog) QPrinter printer(QPrinter::HighResolution); QPrintPreviewDialog preview(&printer, this); connect(&preview, &QPrintPreviewDialog::paintRequested, this, &LtsTextEditor2::printPreview); preview.exec(); #endif } void LtsTextEditor2::printPreview(QPrinter *printer) { #if defined(QT_PRINTSUPPORT_LIB) && QT_CONFIG(printer) textEdit->print(printer); #else Q_UNUSED(printer) #endif } void LtsTextEditor2::onFilePrintPdf() { #if defined(QT_PRINTSUPPORT_LIB) && QT_CONFIG(printer) QFileDialog fileDialog(this, tr("Export PDF")); fileDialog.setAcceptMode(QFileDialog::AcceptSave); fileDialog.setMimeTypeFilters(QStringList(QStringLiteral("application/pdf"))); fileDialog.setDefaultSuffix(QStringLiteral("pdf")); if (fileDialog.exec() != QDialog::Accepted) return; const QStringList &fileNameList = fileDialog.selectedFiles(); if (fileNameList.isEmpty()) return; QString fileName = fileNameList.constFirst(); QPrinter printer(QPrinter::HighResolution); printer.setOutputFormat(QPrinter::PdfFormat); printer.setOutputFileName(fileName); textEdit->document()->print(&printer); statusBar()->showMessage(tr("Exported \"%1\"") .arg(QDir::toNativeSeparators(fileName))); #endif } void LtsTextEditor2::onTextBold() { QTextCharFormat fmt; fmt.setFontWeight(m_actionTextBold->isChecked() ? QFont::Bold : QFont::Normal); mergeFormatOnWordOrSelection(fmt); } void LtsTextEditor2::onTextUnderline() { QTextCharFormat fmt; fmt.setFontUnderline(m_actionTextUnderline->isChecked()); mergeFormatOnWordOrSelection(fmt); } void LtsTextEditor2::onTextItalic() { QTextCharFormat fmt; fmt.setFontItalic(m_actionTextItalic->isChecked()); mergeFormatOnWordOrSelection(fmt); } void LtsTextEditor2::onTextFamily(const QString &f) { QTextCharFormat fmt; fmt.setFontFamily(f); mergeFormatOnWordOrSelection(fmt); } void LtsTextEditor2::onTextSize(const QString &p) { qreal pointSize = p.toFloat(); if (p.toFloat() > 0) { QTextCharFormat fmt; fmt.setFontPointSize(pointSize); mergeFormatOnWordOrSelection(fmt); } } void LtsTextEditor2::onTextStyle(int styleIndex) { QTextCursor cursor = m_textEdit->textCursor(); QTextListFormat::Style style = QTextListFormat::ListStyleUndefined; QTextBlockFormat::MarkerType marker = QTextBlockFormat::MarkerType::NoMarker; switch (styleIndex) { case 1: style = QTextListFormat::ListDisc; break; case 2: style = QTextListFormat::ListCircle; break; case 3: style = QTextListFormat::ListSquare; break; case 4: if (cursor.currentList()) style = cursor.currentList()->format().style(); else style = QTextListFormat::ListDisc; marker = QTextBlockFormat::MarkerType::Unchecked; break; case 5: if (cursor.currentList()) style = cursor.currentList()->format().style(); else style = QTextListFormat::ListDisc; marker = QTextBlockFormat::MarkerType::Checked; break; case 6: style = QTextListFormat::ListDecimal; break; case 7: style = QTextListFormat::ListLowerAlpha; break; case 8: style = QTextListFormat::ListUpperAlpha; break; case 9: style = QTextListFormat::ListLowerRoman; break; case 10: style = QTextListFormat::ListUpperRoman; break; default: break; } cursor.beginEditBlock(); QTextBlockFormat blockFmt = cursor.blockFormat(); if (style == QTextListFormat::ListStyleUndefined) { blockFmt.setObjectIndex(-1); int headingLevel = styleIndex >= 11 ? styleIndex - 11 + 1 : 0; blockFmt.setHeadingLevel(headingLevel); cursor.setBlockFormat(blockFmt); int sizeAdjustment = headingLevel ? 4 - headingLevel : 0; QTextCharFormat fmt; fmt.setFontWeight(headingLevel ? QFont::Bold : QFont::Normal); fmt.setProperty(QTextFormat::FontSizeAdjustment, sizeAdjustment); cursor.select(QTextCursor::LineUnderCursor); cursor.mergeCharFormat(fmt); m_textEdit->mergeCurrentCharFormat(fmt); } else { blockFmt.setMarker(marker); cursor.setBlockFormat(blockFmt); 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(); } void LtsTextEditor2::onTextColor() { QColor col = QColorDialog::getColor(m_textEdit->textColor(), this); if (!col.isValid()) return; QTextCharFormat fmt; fmt.setForeground(col); mergeFormatOnWordOrSelection(fmt); colorChanged(col); } void LtsTextEditor2::onTextAlign(QAction *a) { if (a == m_actionAlignLeft) m_textEdit->setAlignment(Qt::AlignLeft | Qt::AlignAbsolute); else if (a == m_actionAlignCenter) m_textEdit->setAlignment(Qt::AlignHCenter); else if (a == m_actionAlignRight) m_textEdit->setAlignment(Qt::AlignRight | Qt::AlignAbsolute); else if (a == m_actionAlignJustify) m_textEdit->setAlignment(Qt::AlignJustify); } void LtsTextEditor2::setChecked(bool checked) { onTextStyle(checked ? 5 : 4); } void LtsTextEditor2::indent() { modifyIndentation(1); } void LtsTextEditor2::unindent() { modifyIndentation(-1); } void LtsTextEditor2::modifyIndentation(int amount) { QTextCursor cursor = m_textEdit->textCursor(); cursor.beginEditBlock(); if (cursor.currentList()) { QTextListFormat listFmt = cursor.currentList()->format(); QTextCursor above(cursor); above.movePosition(QTextCursor::Up); if (above.currentList() && listFmt.indent() + amount == above.currentList()->format().indent()) { above.currentList()->add(cursor.block()); } else { listFmt.setIndent(listFmt.indent() + amount); cursor.createList(listFmt); } } else { QTextBlockFormat blockFmt = cursor.blockFormat(); blockFmt.setIndent(blockFmt.indent() + amount); cursor.setBlockFormat(blockFmt); } cursor.endEditBlock(); } void LtsTextEditor2::currentCharFormatChanged(const QTextCharFormat &format) { fontChanged(format.font()); colorChanged(format.foreground().color()); } void LtsTextEditor2::cursorPositionChanged() { alignmentChanged(m_textEdit->alignment()); QTextList *list = m_textEdit->textCursor().currentList(); if (list) { switch (list->format().style()) { case QTextListFormat::ListDisc: m_comboStyle->setCurrentIndex(1); break; case QTextListFormat::ListCircle: m_comboStyle->setCurrentIndex(2); break; case QTextListFormat::ListSquare: m_comboStyle->setCurrentIndex(3); break; case QTextListFormat::ListDecimal: m_comboStyle->setCurrentIndex(6); break; case QTextListFormat::ListLowerAlpha: m_comboStyle->setCurrentIndex(7); break; case QTextListFormat::ListUpperAlpha: m_comboStyle->setCurrentIndex(8); break; case QTextListFormat::ListLowerRoman: m_comboStyle->setCurrentIndex(9); break; case QTextListFormat::ListUpperRoman: m_comboStyle->setCurrentIndex(10); break; default: m_comboStyle->setCurrentIndex(-1); break; } switch (m_textEdit->textCursor().block().blockFormat().marker()) { case QTextBlockFormat::MarkerType::NoMarker: m_actionToggleCheckState->setChecked(false); break; case QTextBlockFormat::MarkerType::Unchecked: m_comboStyle->setCurrentIndex(4); m_actionToggleCheckState->setChecked(false); break; case QTextBlockFormat::MarkerType::Checked: m_comboStyle->setCurrentIndex(5); m_actionToggleCheckState->setChecked(true); break; } } else { int headingLevel = m_textEdit->textCursor().blockFormat().headingLevel(); m_comboStyle->setCurrentIndex(headingLevel ? headingLevel + 10 : 0); } } void LtsTextEditor2::clipboardDataChanged() { #ifndef QT_NO_CLIPBOARD if (const QMimeData *md = QApplication::clipboard()->mimeData()) m_actionPaste->setEnabled(md->hasText()); #endif } void LtsTextEditor2::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 LtsTextEditor2::mergeFormatOnWordOrSelection(const QTextCharFormat &format) { QTextCursor cursor = m_textEdit->textCursor(); if (!cursor.hasSelection()) cursor.select(QTextCursor::WordUnderCursor); cursor.mergeCharFormat(format); m_textEdit->mergeCurrentCharFormat(format); } void LtsTextEditor2::fontChanged(const QFont &f) { m_comboFont->setCurrentIndex(m_comboFont->findText(QFontInfo(f).family())); m_comboSize->setCurrentIndex(m_comboSize->findText(QString::number(f.pointSize()))); m_actionTextBold->setChecked(f.bold()); m_actionTextItalic->setChecked(f.italic()); m_actionTextUnderline->setChecked(f.underline()); } void LtsTextEditor2::colorChanged(const QColor &c) { QPixmap pix(16, 16); pix.fill(c); m_actionTextColor->setIcon(pix); } void LtsTextEditor2::alignmentChanged(Qt::Alignment a) { if (a & Qt::AlignLeft) m_actionAlignLeft->setChecked(true); else if (a & Qt::AlignHCenter) m_actionAlignCenter->setChecked(true); else if (a & Qt::AlignRight) m_actionAlignRight->setChecked(true); else if (a & Qt::AlignJustify) m_actionAlignJustify->setChecked(true); } }