928 lines
31 KiB
C++
Executable File
928 lines
31 KiB
C++
Executable File
/**
|
|
* @RDE_HEADER@
|
|
* Widget to create Text Editor
|
|
* $Id$
|
|
* $HeadURL$
|
|
* $Author$
|
|
*/
|
|
|
|
|
|
#include "lts_text_editor2.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 <QTextCodec>
|
|
#include <QTextEdit>
|
|
#include <QStatusBar>
|
|
#include <QToolBar>
|
|
#include <QTextCursor>
|
|
#include <QTextDocumentWriter>
|
|
#include <QTextList>
|
|
#include <QtDebug>
|
|
#include <QCloseEvent>
|
|
#include <QMessageBox>
|
|
#include <QMimeData>
|
|
#include <QMimeDatabase>
|
|
#if defined(QT_PRINTSUPPORT_LIB)
|
|
#include <QtPrintSupport/qtprintsupportglobal.h>
|
|
#if QT_CONFIG(printer)
|
|
#if QT_CONFIG(printdialog)
|
|
#include <QPrintDialog>
|
|
#endif
|
|
#include <QPrinter>
|
|
#if QT_CONFIG(printpreviewdialog)
|
|
#include <QPrintPreviewDialog>
|
|
#endif
|
|
#endif
|
|
#endif
|
|
|
|
|
|
#include <LtsUtilsSettings/settings.h>
|
|
#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 /*Qt::WindowStaysOnTopHint */);
|
|
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()
|
|
{
|
|
//delete m_ui;
|
|
}
|
|
|
|
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);
|
|
}
|
|
|
|
/*!
|
|
* \brief LtsTextEditor2::slotBackgroundColorChanged
|
|
* \param bgColor
|
|
*/
|
|
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);
|
|
|
|
// Make sure the alignLeft is always left of the alignRight
|
|
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);
|
|
|
|
// tb = addToolBar(tr("Format Actions"));
|
|
// tb->setAllowedAreas(Qt::TopToolBarArea | Qt::BottomToolBarArea);
|
|
// addToolBarBreak(Qt::TopToolBarArea);
|
|
// addToolBar(tb);
|
|
|
|
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<int>::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<int> 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)
|
|
//! [0]
|
|
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)));
|
|
//! [0]
|
|
#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; // H1 to H6, or Standard
|
|
blockFmt.setHeadingLevel(headingLevel);
|
|
cursor.setBlockFormat(blockFmt);
|
|
|
|
int sizeAdjustment = headingLevel ? 4 - headingLevel : 0; // H1 to H6: +3 to -2
|
|
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();
|
|
// See whether the line above is the list we want to move this item into,
|
|
// or whether we need a new list.
|
|
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);
|
|
}
|
|
|
|
} // namespace LtsWidgets
|