File indexing completed on 2024-05-12 16:16:11

0001 /*
0002    SPDX-FileCopyrightText: 2023 Laurent Montel <montel@kde.org>
0003 
0004    SPDX-License-Identifier: LGPL-2.0-or-later
0005 */
0006 
0007 #include "converttext.h"
0008 #include <QChar>
0009 #include <QString>
0010 
0011 using namespace TextUtils;
0012 
0013 // code from kitinerary/src/lib/stringutil.cpp
0014 QString ConvertText::normalize(QStringView str)
0015 {
0016     QString out;
0017     out.reserve(str.size());
0018     for (const auto c : str) {
0019         // case folding
0020         const auto n = c.toCaseFolded();
0021 
0022         // if the character has a canonical decomposition use that and skip the
0023         // combining diacritic markers following it
0024         // see https://en.wikipedia.org/wiki/Unicode_equivalence
0025         // see https://en.wikipedia.org/wiki/Combining_character
0026         if (n.decompositionTag() == QChar::Canonical) {
0027             out.push_back(n.decomposition().at(0));
0028         }
0029         // handle compatibility compositions such as ligatures
0030         // see https://en.wikipedia.org/wiki/Unicode_compatibility_characters
0031         else if (n.decompositionTag() == QChar::Compat && n.isLetter() && n.script() == QChar::Script_Latin) {
0032             out.append(n.decomposition());
0033         } else {
0034             out.push_back(n);
0035         }
0036     }
0037     return out;
0038 }
0039 
0040 void ConvertText::upperCase(QTextCursor &cursor)
0041 {
0042     if (cursor.hasSelection()) {
0043         const QString newText = cursor.selectedText().toUpper();
0044         cursor.insertText(newText);
0045     }
0046 }
0047 
0048 void ConvertText::lowerCase(QTextCursor &cursor)
0049 {
0050     if (cursor.hasSelection()) {
0051         const QString newText = cursor.selectedText().toLower();
0052         cursor.insertText(newText);
0053     }
0054 }
0055 
0056 void ConvertText::sentenceCase(QTextCursor &cursor)
0057 {
0058     if (cursor.hasSelection()) {
0059         QString newText = cursor.selectedText();
0060         const int nbChar(newText.length());
0061         for (int i = 0; i < nbChar; ++i) {
0062             if (i == 0 && newText.at(0).isLetter()) {
0063                 newText.replace(0, 1, newText.at(0).toUpper());
0064             } else if (newText.at(i) == QChar::ParagraphSeparator || newText.at(i) == QChar::LineSeparator) {
0065                 ++i;
0066                 if (i < nbChar) {
0067                     if (newText.at(i).isLetter()) {
0068                         newText.replace(i, 1, newText.at(i).toUpper());
0069                     }
0070                 }
0071             }
0072         }
0073         cursor.insertText(newText);
0074     }
0075 }
0076 
0077 void ConvertText::reverseCase(QTextCursor &cursor)
0078 {
0079     if (cursor.hasSelection()) {
0080         const QString newText = cursor.selectedText();
0081         QString reverseCaseText;
0082         const int nbChar(newText.length());
0083         for (int i = 0; i < nbChar; ++i) {
0084             QChar charVal = newText.at(i);
0085             if (charVal.isLetter()) {
0086                 if (charVal.isLower()) {
0087                     charVal = charVal.toUpper();
0088                 } else {
0089                     charVal = charVal.toLower();
0090                 }
0091             }
0092             reverseCaseText += charVal;
0093         }
0094         cursor.insertText(reverseCaseText);
0095     }
0096 }