Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include "mtextedit.h"
- #include <QTextDocument>
- #include <QTextCursor>
- #include <QImage>
- #include <QByteArray>
- #include <QBuffer>
- #include <QApplication>
- #include <QClipboard>
- #include <QMimeData>
- #include <QFontDatabase>
- #include <QTextList>
- #include <QFileDialog>
- #include <QImageReader>
- #include <QUrl>
- #include <QRegularExpression>
- #include <QStandardItemModel>
- #include <QAction>
- #include <QInputDialog>
- #include <QSettings>
- #include "Globals.h"
- #include <QDesktopServices>
- #include <QMessageBox>
- MTextEdit::MTextEdit(QWidget *parent)
- : QTextBrowser(parent)
- , m_lastBlockList(nullptr)
- , m_fontSize(9)
- , m_imageCounter(1U)
- {
- setOpenLinks(false);
- setOpenExternalLinks(false);
- setReadOnly(false);
- setTabStopWidth(40);
- connect(this, &MTextEdit::anchorClicked, this, &MTextEdit::urlActivated);
- connect(this, &MTextEdit::currentCharFormatChanged, this, &MTextEdit::slotCurrentCharFormatChanged);
- connect(this, &MTextEdit::cursorPositionChanged, this, &MTextEdit::slotCursorPositionChanged);
- #ifndef QT_NO_CLIPBOARD
- connect(QApplication::clipboard(), &QClipboard::dataChanged, this, &MTextEdit::slotClipboardDataChanged);
- #endif
- m_fontsModel = new QStandardItemModel(this);
- m_fontsModel->insertColumn(0);
- const QList<int> fontSizes = QFontDatabase::standardSizes();
- m_fontsModel->insertRows(0, fontSizes.size());
- for (int i = 0; i < fontSizes.size(); ++i)
- m_fontsModel->setData(m_fontsModel->index(i, 0), fontSizes.at(i));
- m_fontsModel->sort(0);
- connect(this, &MTextEdit::fontSizeChanged, this, &MTextEdit::textSize);
- connect(this, &MTextEdit::fgColorChanged, this, &MTextEdit::textFgColor);
- connect(this, &MTextEdit::bgColorChanged, this, &MTextEdit::textBgColor);
- createActions();
- fontChanged(font());
- bgColorChanged(textColor());
- setFontSize(QApplication::font().pointSize());
- setFgColor(QApplication::palette().foreground().color());
- setBgColor(QApplication::palette().background().color());
- }
- bool MTextEdit::canInsertFromMimeData(const QMimeData *source) const {
- return
- source->hasImage()
- || source->hasUrls()
- || QTextBrowser::canInsertFromMimeData(source);
- }
- void MTextEdit::insertFromMimeData(const QMimeData *source) {
- if (source->hasImage()) {
- dropImage(source->imageData().value<QImage>());
- }
- else if (source->hasUrls()) {
- const auto allUrls = source->urls();
- for (const QUrl& singleUrl : allUrls)
- dropDocument(singleUrl);
- }
- else
- QTextBrowser::insertFromMimeData(source);
- }
- QMimeData *MTextEdit::createMimeDataFromSelection() const {
- return QTextBrowser::createMimeDataFromSelection();
- }
- void MTextEdit::focusInEvent(QFocusEvent *e)
- {
- QTextBrowser::focusInEvent(e);
- setFocus(Qt::TabFocusReason);
- }
- void MTextEdit::createActions()
- {
- m_undoAction = new QAction(QIcon::fromTheme("edit-undo"), tr("Undo"), this);
- m_undoAction->setShortcut(QKeySequence::Undo);
- connect(this->document(), &QTextDocument::undoAvailable, m_undoAction, &QAction::setEnabled);
- connect(m_undoAction, &QAction::triggered, this, &MTextEdit::undo);
- m_undoAction->setEnabled(this->document()->isUndoAvailable());
- m_redoAction = new QAction(QIcon::fromTheme("edit-redo"), tr("Redo"), this);
- m_redoAction->setShortcut(QKeySequence::Redo);
- m_redoAction->setEnabled(this->document()->isRedoAvailable());
- connect(this->document(), &QTextDocument::redoAvailable, m_redoAction, &QAction::setEnabled);
- connect(m_redoAction, &QAction::triggered, this, &MTextEdit::redo);
- m_cutAction = new QAction(QIcon::fromTheme("edit-cut"), tr("Cut"), this);
- m_cutAction->setEnabled(false);
- m_cutAction->setShortcut(QKeySequence::Cut);
- connect(m_cutAction, &QAction::triggered, this, &MTextEdit::cut);
- connect(this, &MTextEdit::copyAvailable, m_cutAction, &QAction::setEnabled);
- m_copyAction = new QAction(QIcon::fromTheme("edit-copy"), tr("Copy"), this);
- m_copyAction->setEnabled(false);
- m_copyAction->setShortcut(QKeySequence::Copy);
- connect(m_copyAction, &QAction::triggered, this, &MTextEdit::copy);
- connect(this, &MTextEdit::copyAvailable, m_copyAction, &QAction::setEnabled);
- m_pasteAction = new QAction(QIcon::fromTheme("edit-paste"), tr("Paste"), this);
- m_pasteAction->setShortcut(QKeySequence::Paste);
- connect(m_copyAction, &QAction::triggered, this, &MTextEdit::paste);
- m_boldAction = new QAction(QIcon::fromTheme("format-text-bold"), tr("Bold"), this);
- m_boldAction->setShortcut(Qt::CTRL + Qt::Key_B);
- m_boldAction->setCheckable(true);
- connect(m_boldAction, &QAction::triggered, this, &MTextEdit::textBold);
- m_italicAction = new QAction(QIcon::fromTheme("format-text-italic"), tr("Italic"), this);
- m_italicAction->setShortcut(Qt::CTRL + Qt::Key_I);
- m_italicAction->setCheckable(true);
- connect(m_italicAction, &QAction::triggered, this, &MTextEdit::textItalic);
- m_underlineAction = new QAction(QIcon::fromTheme("format-text-underline"), tr("Underline"), this);
- m_underlineAction->setShortcut(Qt::CTRL + Qt::Key_U);
- m_underlineAction->setCheckable(true);
- connect(m_underlineAction, &QAction::triggered, this, &MTextEdit::textUnderline);
- m_strikeoutAction = new QAction(QIcon::fromTheme("format-text-strikethrough"), tr("Strike out"), this);
- m_strikeoutAction->setCheckable(true);
- connect(m_strikeoutAction, &QAction::triggered, this, &MTextEdit::textStrikeout);
- m_orderedListAction = new QAction(QIcon::fromTheme("format-list-ordered"), tr("Ordered list"), this);
- m_orderedListAction->setCheckable(true);
- m_orderedListAction->setShortcut(Qt::CTRL + Qt::Key_Equal);
- connect(m_orderedListAction, &QAction::triggered, this, &MTextEdit::listOrdered);
- m_unorderedListAction = new QAction(QIcon::fromTheme("format-list-unordered"), tr("Unordered list"), this);
- m_unorderedListAction->setCheckable(true);
- m_unorderedListAction->setShortcut(Qt::CTRL + Qt::Key_Minus);
- connect(m_unorderedListAction, &QAction::triggered, this, &MTextEdit::listBullet);
- m_increaseIndentAction = new QAction(QIcon::fromTheme("format-indent-more"), tr("Increase indentation"), this);
- m_increaseIndentAction->setShortcut(Qt::CTRL + Qt::Key_Period);
- connect(m_increaseIndentAction, &QAction::triggered, this, &MTextEdit::increaseIndentation);
- m_decreaseIndentAction = new QAction(QIcon::fromTheme("format-indent-less"), tr("Decrease indentation"), this);
- m_decreaseIndentAction->setShortcut(Qt::CTRL + Qt::Key_Comma);
- connect(m_decreaseIndentAction, &QAction::triggered, this, &MTextEdit::decreaseIndentation);
- m_imageAction = new QAction(QIcon::fromTheme("insert-image"), tr("Image"), this);
- connect(m_imageAction, &QAction::triggered, this, &MTextEdit::insertImage);
- addAction(m_undoAction);
- addAction(m_redoAction);
- addAction(m_cutAction);
- addAction(m_copyAction);
- addAction(m_pasteAction);
- addAction(m_pasteAction);
- addAction(m_boldAction);
- addAction(m_italicAction);
- addAction(m_underlineAction);
- addAction(m_strikeoutAction);
- addAction(m_orderedListAction);
- addAction(m_unorderedListAction);
- addAction(m_increaseIndentAction);
- addAction(m_decreaseIndentAction);
- addAction(m_imageAction);
- }
- void MTextEdit::textBold()
- {
- QTextCharFormat fmt;
- fmt.setFontWeight(m_boldAction->isChecked() ? QFont::Bold : QFont::Normal);
- mergeFormatOnWordOrSelection(fmt);
- }
- void MTextEdit::textUnderline()
- {
- QTextCharFormat fmt;
- fmt.setFontUnderline(m_underlineAction->isChecked());
- mergeFormatOnWordOrSelection(fmt);
- }
- void MTextEdit::textItalic()
- {
- QTextCharFormat fmt;
- fmt.setFontItalic(m_italicAction->isChecked());
- mergeFormatOnWordOrSelection(fmt);
- }
- void MTextEdit::textStrikeout()
- {
- QTextCharFormat fmt;
- fmt.setFontStrikeOut(m_strikeoutAction->isChecked());
- mergeFormatOnWordOrSelection(fmt);
- }
- void MTextEdit::textSize()
- {
- qreal pointSize = fontSize();
- if (pointSize > 0) {
- QTextCharFormat fmt;
- fmt.setFontPointSize(pointSize);
- mergeFormatOnWordOrSelection(fmt);
- }
- }
- void MTextEdit::textFgColor(const QColor& col)
- {
- QTextCursor cursor = textCursor();
- if (!cursor.hasSelection()) {
- cursor.select(QTextCursor::WordUnderCursor);
- }
- QTextCharFormat fmt = cursor.charFormat();
- if (col.isValid()) {
- fmt.setForeground(col);
- }
- else {
- fmt.clearForeground();
- }
- cursor.setCharFormat(fmt);
- setCurrentCharFormat(fmt);
- }
- void MTextEdit::textBgColor(const QColor& col)
- {
- QTextCursor cursor = textCursor();
- if (!cursor.hasSelection()) {
- cursor.select(QTextCursor::WordUnderCursor);
- }
- QTextCharFormat fmt = cursor.charFormat();
- if (col.isValid()) {
- fmt.setBackground(col);
- }
- else {
- fmt.clearBackground();
- }
- cursor.setCharFormat(fmt);
- setCurrentCharFormat(fmt);
- }
- void MTextEdit::listBullet(bool checked)
- {
- if (checked) {
- m_orderedListAction->setChecked(false);
- }
- list(checked, QTextListFormat::ListDisc);
- }
- void MTextEdit::listOrdered(bool checked)
- {
- if (checked) {
- m_unorderedListAction->setChecked(false);
- }
- list(checked, QTextListFormat::ListDecimal);
- }
- void MTextEdit::list(bool checked, QTextListFormat::Style style)
- {
- QTextCursor cursor = textCursor();
- cursor.beginEditBlock();
- if (!checked) {
- QTextBlockFormat obfmt = cursor.blockFormat();
- QTextBlockFormat bfmt;
- bfmt.setIndent(obfmt.indent());
- cursor.setBlockFormat(bfmt);
- }
- else {
- QTextListFormat listFmt;
- if (cursor.currentList()) {
- listFmt = cursor.currentList()->format();
- }
- listFmt.setStyle(style);
- cursor.createList(listFmt);
- }
- cursor.endEditBlock();
- }
- void MTextEdit::mergeFormatOnWordOrSelection(const QTextCharFormat &format)
- {
- QTextCursor cursor = textCursor();
- if (!cursor.hasSelection()) {
- cursor.select(QTextCursor::WordUnderCursor);
- }
- cursor.mergeCharFormat(format);
- mergeCurrentCharFormat(format);
- setFocus(Qt::TabFocusReason);
- }
- void MTextEdit::slotCursorPositionChanged()
- {
- QTextList *l = textCursor().currentList();
- if (m_lastBlockList && (l == m_lastBlockList || (l != 0 && m_lastBlockList != 0
- && l->format().style() == m_lastBlockList->format().style()))) {
- return;
- }
- m_lastBlockList = l;
- if (l) {
- QTextListFormat lfmt = l->format();
- if (lfmt.style() == QTextListFormat::ListDisc) {
- m_unorderedListAction->setChecked(true);
- m_orderedListAction->setChecked(false);
- }
- else if (lfmt.style() == QTextListFormat::ListDecimal) {
- m_unorderedListAction->setChecked(false);
- m_orderedListAction->setChecked(true);
- }
- else {
- m_unorderedListAction->setChecked(false);
- m_orderedListAction->setChecked(false);
- }
- }
- else {
- m_unorderedListAction->setChecked(false);
- m_orderedListAction->setChecked(false);
- }
- }
- void MTextEdit::fontChanged(const QFont &f)
- {
- setFontSize(f.pointSize());
- m_boldAction->setChecked(f.bold());
- m_italicAction->setChecked(f.italic());
- m_underlineAction->setChecked(f.underline());
- m_strikeoutAction->setChecked(f.strikeOut());
- if (textCursor().currentList()) {
- QTextListFormat lfmt = textCursor().currentList()->format();
- if (lfmt.style() == QTextListFormat::ListDisc) {
- m_unorderedListAction->setChecked(true);
- m_orderedListAction->setChecked(false);
- }
- else if (lfmt.style() == QTextListFormat::ListDecimal) {
- m_unorderedListAction->setChecked(false);
- m_orderedListAction->setChecked(true);
- }
- else {
- m_unorderedListAction->setChecked(false);
- m_orderedListAction->setChecked(false);
- }
- }
- else {
- m_unorderedListAction->setChecked(false);
- m_orderedListAction->setChecked(false);
- }
- }
- void MTextEdit::slotCurrentCharFormatChanged(const QTextCharFormat &format)
- {
- fontChanged(format.font());
- setBgColor((format.background().isOpaque()) ? format.background().color() : QColor());
- setFgColor((format.foreground().isOpaque()) ? format.foreground().color() : QColor());
- }
- void MTextEdit::slotClipboardDataChanged()
- {
- #ifndef QT_NO_CLIPBOARD
- if (const QMimeData *md = QApplication::clipboard()->mimeData())
- m_pasteAction->setEnabled(md->hasText());
- #endif
- }
- void MTextEdit::urlActivated(const QUrl &link)
- {
- if (link.isLocalFile()) {
- if (!QDesktopServices::openUrl(link)) {
- if (QMessageBox::critical(this, tr("Error"), tr("File not found.\nThe file could be temporarily unavailable or has been deleted"), QMessageBox::Retry, QMessageBox::Cancel) == QMessageBox::Retry)
- return urlActivated(link);
- }
- }
- }
- QString MTextEdit::toHtml() const
- {
- QString s = QTextBrowser::toHtml();
- // convert emails to links
- s = s.replace(QRegularExpression("(<[^a][^>]+>(?:<span[^>]+>)?|\\s)([a-zA-Z\\d]+@[a-zA-Z\\d]+\\.[a-zA-Z]+)"), "\\1<a href=\"mailto:\\2\">\\2</a>");
- // convert links
- s = s.replace(QRegularExpression("(<[^a][^>]+>(?:<span[^>]+>)?|\\s)((?:https?|ftp|file)://[^\\s'\"<>]+)"), "\\1<a href=\"\\2\">\\2</a>");
- // see also: Utils::linkify()
- return s;
- }
- QAction* MTextEdit::undoAction()
- {
- return m_undoAction;
- }
- QAction* MTextEdit::redoAction()
- {
- return m_redoAction;
- }
- QAction* MTextEdit::cutAction()
- {
- return m_cutAction;
- }
- QAction* MTextEdit::copyAction()
- {
- return m_copyAction;
- }
- QAction* MTextEdit::pasteAction()
- {
- return m_pasteAction;
- }
- QAction* MTextEdit::boldAction()
- {
- return m_boldAction;
- }
- QAction* MTextEdit::italicAction()
- {
- return m_italicAction;
- }
- QAction* MTextEdit::underlineAction()
- {
- return m_underlineAction;
- }
- QAction* MTextEdit::strikeoutAction()
- {
- return m_strikeoutAction;
- }
- QAction* MTextEdit::orderedListAction()
- {
- return m_orderedListAction;
- }
- QAction* MTextEdit::unorderedListAction()
- {
- return m_unorderedListAction;
- }
- QAction* MTextEdit::increaseIndentAction()
- {
- return m_increaseIndentAction;
- }
- QAction* MTextEdit::decreaseIndentAction()
- {
- return m_decreaseIndentAction;
- }
- QAction* MTextEdit::imageAction()
- {
- return m_imageAction;
- }
- void MTextEdit::increaseIndentation()
- {
- indent(+1);
- }
- void MTextEdit::decreaseIndentation()
- {
- indent(-1);
- }
- void MTextEdit::indent(int delta)
- {
- QTextCursor cursor = textCursor();
- cursor.beginEditBlock();
- QTextBlockFormat bfmt = cursor.blockFormat();
- int ind = bfmt.indent();
- if (ind + delta >= 0) {
- bfmt.setIndent(ind + delta);
- }
- cursor.setBlockFormat(bfmt);
- cursor.endEditBlock();
- }
- void MTextEdit::setText(const QString& text)
- {
- if (text.isEmpty()) {
- setPlainText(text);
- return;
- }
- if (text[0] == '<') {
- setHtml(text);
- }
- else {
- setPlainText(text);
- }
- }
- void MTextEdit::insertImage()
- {
- QSettings s;
- QString attdir = s.value("general/filedialog-path").toString();
- QString file = QFileDialog::getOpenFileName(this,
- tr("Select an image"),
- attdir,
- tr("Images (*.jpg *.gif *.png *.bmp)"));
- QImage image = QImageReader(file).read();
- dropImage(image);
- }
- const unsigned int& MTextEdit::fontSize() const
- {
- return m_fontSize;
- }
- void MTextEdit::setFontSize(const unsigned int& val)
- {
- if (val != m_fontSize && val > 0) {
- m_fontSize = val;
- emit fontSizeChanged(val);
- }
- }
- const QColor& MTextEdit::fgColor() const
- {
- return m_fgColor;
- }
- const QColor& MTextEdit::bgColor() const
- {
- return m_bgColor;
- }
- void MTextEdit::setFgColor(const QColor& val)
- {
- if (val != m_fgColor) {
- m_fgColor = val;
- emit fgColorChanged(m_fgColor);
- }
- }
- void MTextEdit::setBgColor(const QColor& val)
- {
- if (val != m_bgColor) {
- m_bgColor = val;
- emit bgColorChanged(m_bgColor);
- }
- }
- QByteArray MTextEdit::save() const
- {
- QHash<QString, QImage> imageHash;
- const QString htmlString = toHtml();
- for (auto i = m_imageList.constBegin();i!=m_imageList.constEnd();++i){
- if (htmlString.contains(*i))
- imageHash.insert(*i, document()->resource(QTextDocument::ImageResource, QUrl(*i)).value<QImage>());
- }
- QByteArray result;
- QDataStream writer(&result, QIODevice::WriteOnly);
- writer << htmlString << imageHash;
- return result;
- }
- void MTextEdit::load(const QByteArray& val)
- {
- m_imageCounter = 1U;
- m_imageList.clear();
- if (val.isEmpty())
- return setPlainText(QString());
- QDataStream reader(val);
- QString htmlString;
- QHash<QString, QImage> imageHash;
- reader >> htmlString >> imageHash;
- for (auto i = imageHash.constBegin(); i != imageHash.constEnd(); ++i) {
- m_imageList.insert(i.key());
- document()->addResource(QTextDocument::ImageResource, QUrl(i.key()), i.value());
- }
- setHtml(htmlString);
- }
- void MTextEdit::dropImage(const QImage& image)
- {
- QString resourceName;
- do{
- resourceName = QStringLiteral("data://image%1").arg(m_imageCounter++);
- } while (m_imageList.contains(resourceName));
- m_imageList.insert(resourceName);
- document()->addResource(QTextDocument::ImageResource, QUrl(resourceName), image);
- QTextCursor cursor = textCursor();
- cursor.insertImage(image, resourceName);
- }
- void MTextEdit::dropDocument(const QUrl& origFilePath)
- {
- const QString repositoryPath = PBglobals::docsRepository();
- if (!QDir().mkpath(repositoryPath))
- return;
- const QFileInfo origFile(origFilePath.toLocalFile());
- QString destinationPath = origFile.fileName();
- for (int i = 1; QFile::exists(repositoryPath + '/' + destinationPath); ++i)
- destinationPath = origFile.baseName() + QString::number(i) + '.' + origFile.completeSuffix();
- QFile::copy(origFile.absoluteFilePath(), repositoryPath + '/' + destinationPath);
- QTextCharFormat fmt;
- fmt.setAnchor(true);
- fmt.setAnchorHref(QUrl::fromLocalFile(repositoryPath + '/' + destinationPath).toString(QUrl::FullyEncoded));
- fmt.setForeground(QApplication::palette().color(QPalette::Link));
- fmt.setFontUnderline(true);
- debugConsole(toHtml());
- QTextCursor cursor = textCursor();
- const QTextCharFormat previousFormat = cursor.charFormat();
- cursor.insertText(origFile.fileName(), fmt);
- cursor.insertText(QStringLiteral(" "), previousFormat);
- debugConsole(toHtml());
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement