From b4349ddbd5da6fd11b468c72ca28e05e9e9f26b6 Mon Sep 17 00:00:00 2001 From: Lukas Holecek Date: Tue, 9 Jul 2019 19:54:36 +0200 Subject: [PATCH] Sanitize font sizes in internal editor Signed-off-by: Lukas Holecek --- plugins/itemtext/CMakeLists.txt | 1 + plugins/itemtext/itemtext.cpp | 54 ++----------------- src/common/sanitize_text_document.cpp | 77 +++++++++++++++++++++++++++ src/common/sanitize_text_document.h | 27 ++++++++++ src/item/itemdelegate.cpp | 7 ++- 5 files changed, 113 insertions(+), 53 deletions(-) create mode 100644 src/common/sanitize_text_document.cpp create mode 100644 src/common/sanitize_text_document.h diff --git a/plugins/itemtext/CMakeLists.txt b/plugins/itemtext/CMakeLists.txt index ce369d20c4..87ac98dea3 100644 --- a/plugins/itemtext/CMakeLists.txt +++ b/plugins/itemtext/CMakeLists.txt @@ -1,5 +1,6 @@ set(copyq_plugin_itemtext_SOURCES ../../src/common/mimetypes.cpp + ../../src/common/sanitize_text_document.cpp ../../src/common/textdata.cpp ) diff --git a/plugins/itemtext/itemtext.cpp b/plugins/itemtext/itemtext.cpp index 179d4533fa..0404d24973 100644 --- a/plugins/itemtext/itemtext.cpp +++ b/plugins/itemtext/itemtext.cpp @@ -21,6 +21,7 @@ #include "ui_itemtextsettings.h" #include "common/mimetypes.h" +#include "common/sanitize_text_document.h" #include "common/textdata.h" #include @@ -35,10 +36,6 @@ #include #include -#ifdef Q_OS_MAC -# include -#endif - namespace { // Limit number of characters for performance reasons. @@ -58,9 +55,6 @@ const char optionMaximumHeight[] = "max_height"; const char mimeRichText[] = "text/richtext"; -const int maxFontPointSize = 256; -const int maxFontPixelSize = maxFontPointSize * 4 / 3; - // Some applications insert \0 teminator at the end of text data. // It needs to be removed because QTextBrowser can render the character. void removeTrailingNull(QString *text) @@ -170,50 +164,8 @@ ItemText::ItemText(const QString &text, const QString &richText, int maxLines, i } } - if (m_isRichText) { -#ifdef Q_OS_MAC - // Prevent showing font download dialog on macOS. - QFontDatabase fontDatabase; - for (auto block = m_textDocument.begin(); block != m_textDocument.end(); block = block.next()) { - for (auto it = block.begin(); !it.atEnd(); ++it) { - const QTextFragment fragment = it.fragment(); - QTextCharFormat charFormat = fragment.charFormat(); - const QString fontFamily = charFormat.fontFamily(); - if ( !fontDatabase.hasFamily(fontFamily) ) { - QTextCursor tc(&m_textDocument); - tc.setPosition( fragment.position() ); - tc.setPosition( fragment.position() + fragment.length(), QTextCursor::KeepAnchor ); - charFormat.setFontFamily(QString()); - tc.setCharFormat(charFormat); - } - } - } -#endif - - // Sanitize font sizes to prevent app freeze. - for (auto block = m_textDocument.begin(); block != m_textDocument.end(); block = block.next()) { - for (auto it = block.begin(); !it.atEnd(); ++it) { - const QTextFragment fragment = it.fragment(); - QTextCharFormat charFormat = fragment.charFormat(); - QFont font = charFormat.font(); - - const int pixelSize = font.pixelSize(); - const int pointSize = font.pointSize(); - if (-maxFontPixelSize > pixelSize || pixelSize > maxFontPixelSize) - font.setPixelSize(maxFontPixelSize); - else if (-maxFontPointSize > pointSize || pointSize > maxFontPointSize) - font.setPointSize(maxFontPointSize); - else - continue; - - QTextCursor tc(&m_textDocument); - tc.setPosition( fragment.position() ); - tc.setPosition( fragment.position() + fragment.length(), QTextCursor::KeepAnchor ); - charFormat.setFont(font); - tc.setCharFormat(charFormat); - } - } - } + if (m_isRichText) + sanitizeTextDocument(&m_textDocument); setDocument(&m_textDocument); diff --git a/src/common/sanitize_text_document.cpp b/src/common/sanitize_text_document.cpp new file mode 100644 index 0000000000..225c9f4d34 --- /dev/null +++ b/src/common/sanitize_text_document.cpp @@ -0,0 +1,77 @@ +/* + Copyright (c) 2019, Lukas Holecek + + This file is part of CopyQ. + + CopyQ is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + CopyQ is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with CopyQ. If not, see . +*/ + +#include "sanitize_text_document.h" + +#include +#include +#include + +#ifdef Q_OS_MAC +# include +#endif + +constexpr int maxFontPointSize = 128; +constexpr int maxFontPixelSize = maxFontPointSize * 4 / 3; + +void sanitizeTextDocument(QTextDocument *document) +{ + QTextCursor tc(document); + +#ifdef Q_OS_MAC + // Prevent showing font download dialog on macOS. + QFontDatabase fontDatabase; + for (auto block = document->begin(); block != document->end(); block = block.next()) { + for (auto it = block.begin(); !it.atEnd(); ++it) { + const QTextFragment fragment = it.fragment(); + QTextCharFormat charFormat = fragment.charFormat(); + const QString fontFamily = charFormat.fontFamily(); + if ( !fontDatabase.hasFamily(fontFamily) ) { + tc.setPosition( fragment.position() ); + tc.setPosition( fragment.position() + fragment.length(), QTextCursor::KeepAnchor ); + charFormat.setFontFamily(QString()); + tc.setCharFormat(charFormat); + } + } + } +#endif + + // Sanitize font sizes to prevent app freeze. + for (auto block = document->begin(); block != document->end(); block = block.next()) { + for (auto it = block.begin(); !it.atEnd(); ++it) { + const QTextFragment fragment = it.fragment(); + QTextCharFormat charFormat = fragment.charFormat(); + QFont font = charFormat.font(); + + const int pixelSize = font.pixelSize(); + const int pointSize = font.pointSize(); + if (-maxFontPixelSize > pixelSize || pixelSize > maxFontPixelSize) + font.setPixelSize(maxFontPixelSize); + else if (-maxFontPointSize > pointSize || pointSize > maxFontPointSize) + font.setPointSize(maxFontPointSize); + else + continue; + + tc.setPosition( fragment.position() ); + tc.setPosition( fragment.position() + fragment.length(), QTextCursor::KeepAnchor ); + charFormat.setFont(font); + tc.setCharFormat(charFormat); + } + } +} diff --git a/src/common/sanitize_text_document.h b/src/common/sanitize_text_document.h new file mode 100644 index 0000000000..53cc1ae6be --- /dev/null +++ b/src/common/sanitize_text_document.h @@ -0,0 +1,27 @@ +/* + Copyright (c) 2019, Lukas Holecek + + This file is part of CopyQ. + + CopyQ is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + CopyQ is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with CopyQ. If not, see . +*/ + +#ifndef SANITIZE_TEXT_DOCUMENT_H +#define SANITIZE_TEXT_DOCUMENT_H + +class QTextDocument; + +void sanitizeTextDocument(QTextDocument *document); + +#endif // SANITIZE_TEXT_DOCUMENT_H diff --git a/src/item/itemdelegate.cpp b/src/item/itemdelegate.cpp index 700092411a..429f092d77 100644 --- a/src/item/itemdelegate.cpp +++ b/src/item/itemdelegate.cpp @@ -22,6 +22,7 @@ #include "common/client_server.h" #include "common/contenttype.h" #include "common/mimetypes.h" +#include "common/sanitize_text_document.h" #include "common/textdata.h" #include "gui/clipboardbrowser.h" #include "gui/iconfactory.h" @@ -213,10 +214,12 @@ ItemEditorWidget *ItemDelegate::createCustomEditor( connect(editor, &QObject::destroyed, editorParent, &QObject::deleteLater); - if (hasHtml) + if (hasHtml) { editor->setHtml(text); - else + sanitizeTextDocument(editor->document()); + } else { editor->setPlainText(text); + } editor->selectAll();