File indexing completed on 2024-05-12 16:59:35
0001 /* 0002 This file is part of the Qt Quick Controls module of the Qt Toolkit. 0003 SPDX-FileCopyrightText: 2013 Digia Plc and /or its subsidiary(-ies) <http://www.qt-project.org/legal> 0004 0005 SPDX-License-Identifier: BSD-3-Clause 0006 */ 0007 0008 /* 0009 * This file was imported from Qt into Plasma 0010 * I expect this to become public API at some point 0011 * at which point we should delete this 0012 */ 0013 0014 #include "documenthandler.h" 0015 0016 #include <QClipboard> 0017 #include <QFontDatabase> 0018 #include <QGuiApplication> 0019 #include <QMimeData> 0020 #include <QTextCursor> 0021 #include <QTextDocument> 0022 #include <QTextDocumentFragment> 0023 0024 #include <KTextToHTML> 0025 0026 DocumentHandler::DocumentHandler() 0027 : m_target(nullptr) 0028 , m_doc(nullptr) 0029 , m_cursorPosition(-1) 0030 , m_selectionStart(0) 0031 , m_selectionEnd(0) 0032 { 0033 } 0034 0035 void DocumentHandler::setTarget(QQuickItem *target) 0036 { 0037 m_doc = nullptr; 0038 m_target = target; 0039 if (!m_target) { 0040 return; 0041 } 0042 0043 QVariant doc = m_target->property("textDocument"); 0044 if (doc.canConvert<QQuickTextDocument *>()) { 0045 QQuickTextDocument *qqdoc = doc.value<QQuickTextDocument *>(); 0046 if (qqdoc) { 0047 m_doc = qqdoc->textDocument(); 0048 } 0049 } 0050 Q_EMIT targetChanged(); 0051 } 0052 0053 QString DocumentHandler::documentTitle() const 0054 { 0055 return m_documentTitle; 0056 } 0057 0058 void DocumentHandler::setDocumentTitle(QString arg) 0059 { 0060 if (m_documentTitle != arg) { 0061 m_documentTitle = arg; 0062 Q_EMIT documentTitleChanged(); 0063 } 0064 } 0065 0066 void DocumentHandler::pasteWithoutFormatting() 0067 { 0068 QTextCursor cursor = textCursor(); 0069 if (cursor.isNull()) { 0070 return; 0071 } 0072 0073 QClipboard *clipboard = QGuiApplication::clipboard(); 0074 if (!clipboard) { 0075 return; 0076 } 0077 0078 const QMimeData *mimeData = clipboard->mimeData(); 0079 if (!mimeData) { 0080 return; 0081 } 0082 0083 QString content = KTextToHTML::convertToHtml(mimeData->text(), KTextToHTML::Options(KTextToHTML::PreserveSpaces)); 0084 0085 if (content.endsWith("</a>", Qt::CaseInsensitive)) { 0086 content += " "; 0087 } 0088 0089 cursor.insertHtml(content); 0090 } 0091 0092 void DocumentHandler::setText(const QString &arg) 0093 { 0094 if (m_text != arg) { 0095 m_text = arg; 0096 Q_EMIT textChanged(); 0097 } 0098 } 0099 0100 QString DocumentHandler::text() const 0101 { 0102 return m_text; 0103 } 0104 0105 void DocumentHandler::setCursorPosition(int position) 0106 { 0107 if (position == m_cursorPosition) { 0108 return; 0109 } 0110 0111 m_cursorPosition = position; 0112 0113 reset(); 0114 } 0115 0116 void DocumentHandler::reset() 0117 { 0118 Q_EMIT fontFamilyChanged(); 0119 Q_EMIT alignmentChanged(); 0120 Q_EMIT boldChanged(); 0121 Q_EMIT italicChanged(); 0122 Q_EMIT underlineChanged(); 0123 Q_EMIT strikeOutChanged(); 0124 Q_EMIT fontSizeChanged(); 0125 Q_EMIT textColorChanged(); 0126 } 0127 0128 QTextCursor DocumentHandler::textCursor() const 0129 { 0130 if (!m_doc) { 0131 return QTextCursor(); 0132 } 0133 QTextCursor cursor = QTextCursor(m_doc); 0134 if (m_selectionStart != m_selectionEnd) { 0135 cursor.setPosition(m_selectionStart); 0136 cursor.setPosition(m_selectionEnd, QTextCursor::KeepAnchor); 0137 } else { 0138 cursor.setPosition(m_cursorPosition); 0139 } 0140 return cursor; 0141 } 0142 0143 void DocumentHandler::mergeFormatOnWordOrSelection(const QTextCharFormat &format) 0144 { 0145 QTextCursor cursor = textCursor(); 0146 if (!cursor.hasSelection()) { 0147 cursor.select(QTextCursor::WordUnderCursor); 0148 } 0149 cursor.mergeCharFormat(format); 0150 } 0151 0152 void DocumentHandler::setSelectionStart(int position) 0153 { 0154 m_selectionStart = position; 0155 } 0156 0157 void DocumentHandler::setSelectionEnd(int position) 0158 { 0159 m_selectionEnd = position; 0160 } 0161 0162 void DocumentHandler::setAlignment(Qt::Alignment a) 0163 { 0164 QTextBlockFormat fmt; 0165 fmt.setAlignment((Qt::Alignment)a); 0166 QTextCursor cursor = QTextCursor(m_doc); 0167 cursor.setPosition(m_selectionStart, QTextCursor::MoveAnchor); 0168 cursor.setPosition(m_selectionEnd, QTextCursor::KeepAnchor); 0169 cursor.mergeBlockFormat(fmt); 0170 Q_EMIT alignmentChanged(); 0171 } 0172 0173 Qt::Alignment DocumentHandler::alignment() const 0174 { 0175 QTextCursor cursor = textCursor(); 0176 if (cursor.isNull()) { 0177 return Qt::AlignLeft; 0178 } 0179 return textCursor().blockFormat().alignment(); 0180 } 0181 0182 bool DocumentHandler::bold() const 0183 { 0184 QTextCursor cursor = textCursor(); 0185 if (cursor.isNull()) { 0186 return false; 0187 } 0188 return textCursor().charFormat().fontWeight() == QFont::Bold; 0189 } 0190 0191 bool DocumentHandler::italic() const 0192 { 0193 QTextCursor cursor = textCursor(); 0194 if (cursor.isNull()) { 0195 return false; 0196 } 0197 return textCursor().charFormat().fontItalic(); 0198 } 0199 0200 bool DocumentHandler::underline() const 0201 { 0202 QTextCursor cursor = textCursor(); 0203 if (cursor.isNull()) { 0204 return false; 0205 } 0206 return textCursor().charFormat().fontUnderline(); 0207 } 0208 0209 bool DocumentHandler::strikeOut() const 0210 { 0211 QTextCursor cursor = textCursor(); 0212 if (cursor.isNull()) { 0213 return false; 0214 } 0215 return textCursor().charFormat().fontStrikeOut(); 0216 } 0217 0218 void DocumentHandler::setBold(bool arg) 0219 { 0220 QTextCharFormat fmt; 0221 fmt.setFontWeight(arg ? QFont::Bold : QFont::Normal); 0222 mergeFormatOnWordOrSelection(fmt); 0223 Q_EMIT boldChanged(); 0224 } 0225 0226 void DocumentHandler::setItalic(bool arg) 0227 { 0228 QTextCharFormat fmt; 0229 fmt.setFontItalic(arg); 0230 mergeFormatOnWordOrSelection(fmt); 0231 Q_EMIT italicChanged(); 0232 } 0233 0234 void DocumentHandler::setUnderline(bool arg) 0235 { 0236 QTextCharFormat fmt; 0237 fmt.setFontUnderline(arg); 0238 mergeFormatOnWordOrSelection(fmt); 0239 Q_EMIT underlineChanged(); 0240 } 0241 0242 void DocumentHandler::setStrikeOut(bool arg) 0243 { 0244 QTextCharFormat fmt; 0245 fmt.setFontStrikeOut(arg); 0246 mergeFormatOnWordOrSelection(fmt); 0247 Q_EMIT strikeOutChanged(); 0248 } 0249 0250 int DocumentHandler::fontSize() const 0251 { 0252 QTextCursor cursor = textCursor(); 0253 if (cursor.isNull()) { 0254 return 0; 0255 } 0256 QTextCharFormat format = cursor.charFormat(); 0257 return format.font().pointSize(); 0258 } 0259 0260 void DocumentHandler::setFontSize(int arg) 0261 { 0262 QTextCursor cursor = textCursor(); 0263 if (cursor.isNull()) { 0264 return; 0265 } 0266 QTextCharFormat format; 0267 format.setFontPointSize(arg); 0268 mergeFormatOnWordOrSelection(format); 0269 // Also set the block char format, otherwise the old block font will stay and 0270 // end up taking effect if the user deletes all the text. 0271 cursor.mergeBlockCharFormat(format); 0272 0273 Q_EMIT fontSizeChanged(); 0274 } 0275 0276 int DocumentHandler::defaultFontSize() const 0277 { 0278 return m_doc ? m_doc->defaultFont().pointSize() : 0; 0279 } 0280 0281 void DocumentHandler::setDefaultFontSize(int arg) 0282 { 0283 if (!m_doc) { 0284 return; 0285 } 0286 0287 auto font = m_doc->defaultFont(); 0288 font.setPointSize(arg); 0289 m_doc->setDefaultFont(font); 0290 Q_EMIT defaultFontSizeChanged(); 0291 } 0292 0293 QColor DocumentHandler::textColor() const 0294 { 0295 QTextCursor cursor = textCursor(); 0296 if (cursor.isNull()) { 0297 return QColor(Qt::black); 0298 } 0299 QTextCharFormat format = cursor.charFormat(); 0300 return format.foreground().color(); 0301 } 0302 0303 void DocumentHandler::setTextColor(const QColor &c) 0304 { 0305 QTextCursor cursor = textCursor(); 0306 if (cursor.isNull()) { 0307 return; 0308 } 0309 QTextCharFormat format; 0310 format.setForeground(QBrush(c)); 0311 mergeFormatOnWordOrSelection(format); 0312 Q_EMIT textColorChanged(); 0313 } 0314 0315 QString DocumentHandler::fontFamily() const 0316 { 0317 QTextCursor cursor = textCursor(); 0318 if (cursor.isNull()) { 0319 return QString(); 0320 } 0321 QTextCharFormat format = cursor.charFormat(); 0322 return format.font().family(); 0323 } 0324 0325 void DocumentHandler::setFontFamily(const QString &arg) 0326 { 0327 QTextCursor cursor = textCursor(); 0328 if (cursor.isNull()) { 0329 return; 0330 } 0331 QTextCharFormat format; 0332 format.setFontFamily(arg); 0333 mergeFormatOnWordOrSelection(format); 0334 Q_EMIT fontFamilyChanged(); 0335 } 0336 0337 QStringList DocumentHandler::defaultFontSizes() const 0338 { 0339 // uhm... this is quite ugly 0340 QStringList sizes; 0341 const QList<int> standardSizes = QFontDatabase::standardSizes(); 0342 sizes.reserve(standardSizes.count()); 0343 for (int size : standardSizes) { 0344 sizes.append(QString::number(size)); 0345 } 0346 return sizes; 0347 } 0348 0349 QString DocumentHandler::strip(const QString text) 0350 { 0351 return QTextDocumentFragment::fromHtml(text).toPlainText(); 0352 } 0353 0354 QString DocumentHandler::stripAndSimplify(const QString text) 0355 { 0356 QString myText = text; 0357 QString plainText = QTextDocumentFragment::fromHtml(myText).toPlainText(); 0358 // Normalize all whitespace to increase the fuzziness of the match 0359 plainText = plainText.simplified(); 0360 return plainText; 0361 } 0362 0363 QString DocumentHandler::strippedClipboardText() 0364 { 0365 QClipboard *clipboard = QGuiApplication::clipboard(); 0366 if (!clipboard) { 0367 return QString(); 0368 } 0369 0370 return stripAndSimplify(clipboard->text()); 0371 }