Skip to content

Commit

Permalink
Sanitize font sizes in internal editor
Browse files Browse the repository at this point in the history
Signed-off-by: Lukas Holecek <hluk@email.cz>
  • Loading branch information
hluk committed Jul 9, 2019
1 parent 6a6d654 commit b4349dd
Show file tree
Hide file tree
Showing 5 changed files with 113 additions and 53 deletions.
1 change: 1 addition & 0 deletions plugins/itemtext/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
set(copyq_plugin_itemtext_SOURCES
../../src/common/mimetypes.cpp
../../src/common/sanitize_text_document.cpp
../../src/common/textdata.cpp
)

Expand Down
54 changes: 3 additions & 51 deletions plugins/itemtext/itemtext.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
#include "ui_itemtextsettings.h"

#include "common/mimetypes.h"
#include "common/sanitize_text_document.h"
#include "common/textdata.h"

#include <QAbstractTextDocumentLayout>
Expand All @@ -35,10 +36,6 @@
#include <QTextDocument>
#include <QtPlugin>

#ifdef Q_OS_MAC
# include <QFontDatabase>
#endif

namespace {

// Limit number of characters for performance reasons.
Expand All @@ -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)
Expand Down Expand Up @@ -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);

Expand Down
77 changes: 77 additions & 0 deletions src/common/sanitize_text_document.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
/*
Copyright (c) 2019, Lukas Holecek <hluk@email.cz>
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 <http://www.gnu.org/licenses/>.
*/

#include "sanitize_text_document.h"

#include <QTextBlock>
#include <QTextCursor>
#include <QTextDocument>

#ifdef Q_OS_MAC
# include <QFontDatabase>
#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);
}
}
}
27 changes: 27 additions & 0 deletions src/common/sanitize_text_document.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
/*
Copyright (c) 2019, Lukas Holecek <hluk@email.cz>
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 <http://www.gnu.org/licenses/>.
*/

#ifndef SANITIZE_TEXT_DOCUMENT_H
#define SANITIZE_TEXT_DOCUMENT_H

class QTextDocument;

void sanitizeTextDocument(QTextDocument *document);

#endif // SANITIZE_TEXT_DOCUMENT_H
7 changes: 5 additions & 2 deletions src/item/itemdelegate.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -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();

Expand Down

0 comments on commit b4349dd

Please sign in to comment.