File indexing completed on 2024-04-21 05:50:08
0001 /* 0002 * SPDX-FileCopyrightText: 1999 Reginald Stadlbauer <reggie@kde.org> 0003 * 0004 * SPDX-License-Identifier: GPL-2.0-or-later 0005 */ 0006 0007 #include "kcharselectdia.h" 0008 0009 #include <QAction> 0010 #include <QApplication> 0011 #include <QClipboard> 0012 #include <QDir> 0013 #include <QFontDatabase> 0014 #include <QGridLayout> 0015 #include <QIcon> 0016 #include <QMenu> 0017 0018 #include <KActionCollection> 0019 #include <KBookmarkManager> 0020 #include <KBookmarkMenu> 0021 #include <KBookmarkOwner> 0022 #include <KConfigGroup> 0023 #include <KLocalizedString> 0024 #include <KSharedConfig> 0025 #include <KStandardAction> 0026 #include <KStandardShortcut> 0027 #include <KToggleAction> 0028 0029 class KCharSelectBookmarkOwner : public KBookmarkOwner 0030 { 0031 public: 0032 KCharSelectBookmarkOwner(KCharSelectDia *dia) 0033 : d(dia) 0034 { 0035 } 0036 ~KCharSelectBookmarkOwner() override 0037 { 0038 } 0039 0040 QString currentTitle() const override 0041 { 0042 char32_t ucs4 = d->charSelect->currentCodePoint(); 0043 if (QChar::isPrint(ucs4)) { 0044 return QString::fromUcs4(&ucs4, 1) + QLatin1Char(' ') + formatCodePoint(ucs4); 0045 } else { 0046 return formatCodePoint(ucs4); 0047 } 0048 } 0049 0050 QUrl currentUrl() const override 0051 { 0052 return QUrl(formatCodePoint(d->charSelect->currentCodePoint())); 0053 } 0054 0055 void openBookmark(const KBookmark &bm, Qt::MouseButtons, Qt::KeyboardModifiers) override 0056 { 0057 QString c = bm.url().toString(QUrl::PreferLocalFile | QUrl::RemoveScheme); 0058 if (c.startsWith(QLatin1String("U+"))) { 0059 uint uc = QStringView(c).mid(2).toUInt(nullptr, 16); 0060 d->charSelect->setCurrentCodePoint(uc); 0061 } 0062 } 0063 0064 private: 0065 static QString formatCodePoint(uint ucs4) 0066 { 0067 QString c = QString::number(ucs4, 16).toUpper(); 0068 while (c.length() < 4) { 0069 c.prepend(QLatin1Char('0')); 0070 } 0071 return QStringLiteral("U+") + c; 0072 } 0073 0074 private: 0075 KCharSelectDia *d; 0076 }; 0077 0078 /******************************************************************/ 0079 /* class KCharSelectDia */ 0080 /******************************************************************/ 0081 0082 //================================================================== 0083 KCharSelectDia::KCharSelectDia(QWidget *parent) 0084 : KXmlGuiWindow(parent) 0085 { 0086 KSharedConfig::Ptr config = KSharedConfig::openConfig(); 0087 KConfigGroup gr = config->group(QStringLiteral("General")); 0088 0089 vFont = gr.readEntry("selectedFont", QFontDatabase::systemFont(QFontDatabase::GeneralFont)); 0090 vChr = gr.readEntry("char", 33); 0091 _rtl = gr.readEntry("rtl", false); 0092 0093 QWidget *mainWidget = new QWidget(this); 0094 setCentralWidget(mainWidget); 0095 0096 grid = new QGridLayout(mainWidget); 0097 0098 // Add character selection widget from library kdeui 0099 charSelect = new KCharSelect(mainWidget, actionCollection()); 0100 charSelect->setAllPlanesEnabled(true); 0101 charSelect->setCurrentCodePoint(vChr); 0102 charSelect->setCurrentFont(vFont); 0103 charSelect->resize(charSelect->sizeHint()); 0104 connect(charSelect, &KCharSelect::currentCodePointChanged, this, &KCharSelectDia::charChanged); 0105 connect(charSelect, &KCharSelect::codePointSelected, this, qOverload<char32_t>(&KCharSelectDia::add)); 0106 0107 connect(charSelect, &KCharSelect::currentFontChanged, this, &KCharSelectDia::fontSelected); 0108 grid->addWidget(charSelect, 0, 0, 1, 4); 0109 0110 // Build line editor 0111 lined = new QLineEdit(mainWidget); 0112 lined->resize(lined->sizeHint()); 0113 lined->setClearButtonEnabled(true); 0114 0115 lined->setFont(vFont); 0116 0117 connect(lined, &QLineEdit::textChanged, this, &KCharSelectDia::lineEditChanged); 0118 grid->addWidget(lined, 1, 0, 1, 3); 0119 0120 bClip = new QPushButton(i18n("&To Clipboard"), mainWidget); 0121 bClip->setIcon(QIcon::fromTheme(QStringLiteral("edit-copy"))); 0122 bClip->setFixedSize(bClip->sizeHint()); 0123 connect(bClip, &QPushButton::clicked, this, &KCharSelectDia::toClip); 0124 grid->addWidget(bClip, 1, 3); 0125 0126 // Build menu 0127 KStandardAction::quit(this, SLOT(close()), actionCollection()); 0128 0129 QAction *action = actionCollection()->addAction(QStringLiteral("copy_clip")); 0130 action->setText(i18n("&To Clipboard")); 0131 action->setIcon(QIcon::fromTheme(QStringLiteral("edit-copy"))); 0132 connect(action, &QAction::triggered, this, &KCharSelectDia::toClip); 0133 actionCollection()->setDefaultShortcuts(action, KStandardShortcut::shortcut(KStandardShortcut::Copy)); 0134 0135 action = actionCollection()->addAction(QStringLiteral("copy_utf_8")); 0136 action->setText(i18n("To Clipboard &UTF-8")); 0137 connect(action, &QAction::triggered, this, &KCharSelectDia::toClipUTF8); 0138 action = actionCollection()->addAction(QStringLiteral("copy_html")); 0139 action->setText(i18n("To Clipboard &HTML")); 0140 connect(action, &QAction::triggered, this, &KCharSelectDia::toClipHTML); 0141 0142 action = actionCollection()->addAction(QStringLiteral("from_clip")); 0143 action->setText(i18n("&From Clipboard")); 0144 action->setIcon(QIcon::fromTheme(QStringLiteral("edit-paste"))); 0145 connect(action, &QAction::triggered, this, &KCharSelectDia::fromClip); 0146 actionCollection()->setDefaultShortcuts(action, KStandardShortcut::shortcut(KStandardShortcut::Paste)); 0147 action = actionCollection()->addAction(QStringLiteral("from_clip_utf8")); 0148 action->setText(i18n("From Clipboard UTF-8")); 0149 connect(action, &QAction::triggered, this, &KCharSelectDia::fromClipUTF8); 0150 0151 i18n("From Clipboard HTML"); // Intended for future use 0152 0153 action = actionCollection()->addAction(QStringLiteral("flip")); 0154 action->setText(i18n("&Flip Text")); 0155 connect(action, &QAction::triggered, this, &KCharSelectDia::flipText); 0156 0157 action = new KToggleAction(i18n("&Reverse Direction"), this); 0158 action->setChecked(_rtl); 0159 actionCollection()->addAction(QStringLiteral("rtl"), action); 0160 connect(action, &QAction::toggled, this, &KCharSelectDia::setRtl); 0161 0162 charSelect->setFocus(); 0163 0164 if (_rtl) 0165 lined->setAlignment(Qt::AlignRight); 0166 else 0167 lined->setAlignment(Qt::AlignLeft); 0168 0169 QString filename = QStandardPaths::locate(QStandardPaths::GenericDataLocation, QStringLiteral("kcharselect/bookmarks.xml")); 0170 if (filename.isEmpty()) { 0171 filename = QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation) + QStringLiteral("/kcharselect"); 0172 QDir().mkpath(filename); 0173 filename += QStringLiteral("/bookmarks.xml"); 0174 } 0175 0176 bookmarkManager = new KBookmarkManager(filename, this); 0177 0178 action = actionCollection()->addAction(QStringLiteral("bookmarks")); 0179 action->setText(i18n("Bookmarks")); 0180 QMenu *bmmenu = new QMenu(this); 0181 action->setMenu(bmmenu); 0182 0183 KBookmarkMenu *bm = new KBookmarkMenu(bookmarkManager, new KCharSelectBookmarkOwner(this), bmmenu); 0184 actionCollection()->addActions(bmmenu->actions()); 0185 0186 bm->setParent(this); 0187 0188 setupGUI(ToolBar | Keys | Save | Create); 0189 } 0190 0191 //================================================================== 0192 void KCharSelectDia::closeEvent(QCloseEvent *event) 0193 { 0194 KSharedConfig::Ptr config = KSharedConfig::openConfig(); 0195 KConfigGroup gr = config->group(QStringLiteral("General")); 0196 0197 gr.writeEntry("selectedFont", vFont); 0198 gr.writeEntry("char", (uint)vChr); 0199 gr.writeEntry("rtl", _rtl); 0200 0201 KXmlGuiWindow::closeEvent(event); 0202 } 0203 0204 //================================================================== 0205 void KCharSelectDia::charChanged(char32_t _chr) 0206 { 0207 vChr = _chr; 0208 } 0209 0210 //================================================================== 0211 void KCharSelectDia::fontSelected(const QFont &_font) 0212 { 0213 lined->setFont(_font); 0214 0215 vFont = _font; 0216 } 0217 0218 //================================================================== 0219 void KCharSelectDia::add(char32_t _chr) 0220 { 0221 charChanged(_chr); 0222 0223 QString str = lined->text(); 0224 const int pos = lined->cursorPosition(); 0225 str.insert(pos, QString::fromUcs4(&_chr, 1)); 0226 lined->setText(str); 0227 lined->setCursorPosition(pos + QString::fromUcs4(&_chr, 1).size()); 0228 } 0229 0230 //================================================================== 0231 void KCharSelectDia::toClip() 0232 { 0233 QString str = lined->text(); 0234 if (str.isEmpty()) 0235 str = QString::fromUcs4(&vChr, 1); 0236 QClipboard *cb = QApplication::clipboard(); 0237 cb->setText(str, QClipboard::Clipboard); 0238 cb->setText(str, QClipboard::Selection); 0239 } 0240 0241 //================================================================== 0242 // UTF-8 is rapidly becoming the favored 8-bit encoding for 0243 // Unicode (iso10646-1). 0244 // 0245 void KCharSelectDia::toClipUTF8() 0246 { 0247 QClipboard *cb = QApplication::clipboard(); 0248 QString str = lined->text(); 0249 if (str.isEmpty()) 0250 str = QString::fromUcs4(&vChr, 1); 0251 cb->setText(QLatin1String(str.toUtf8())); 0252 } 0253 0254 //================================================================== 0255 // Put valid HTML 4.0 into the clipboard. Valid ISO-8859-1 Latin 1 0256 // characters are left undisturbed. Everything else, including the 0257 // "c0 control characters" often used by Windows, are clipped 0258 // as a HTML entity. 0259 // 0260 void KCharSelectDia::toClipHTML() 0261 { 0262 QClipboard *cb = QApplication::clipboard(); 0263 QString input; 0264 QString html; 0265 QChar tempchar; 0266 int i = 0; 0267 0268 input = lined->text(); 0269 if (input.isEmpty()) 0270 input = QString::fromUcs4(&vChr, 1); 0271 const int inputLength = input.length(); 0272 for (i = 0; i < inputLength; ++i) { 0273 tempchar = input.at(i); 0274 if (tempchar.toLatin1() && ((tempchar.unicode() < 128) || (tempchar.unicode() >= 128 + 32))) { 0275 html.append(input.at(i)); 0276 } else { 0277 html.append(QString::asprintf("&#x%x;", tempchar.unicode())); 0278 } 0279 } 0280 cb->setText(html); 0281 } 0282 0283 //================================================================== 0284 // 0285 void KCharSelectDia::fromClip() 0286 { 0287 QClipboard *cb = QApplication::clipboard(); 0288 lined->setText(cb->text()); 0289 } 0290 0291 //================================================================== 0292 // UTF-8 is rapidly becoming the favored 8-bit encoding for 0293 // Unicode (iso10646-1). This function is handy for decoding 0294 // UTF-8 found in legacy applications, consoles, filenames, webpages, 0295 // etc. 0296 // 0297 void KCharSelectDia::fromClipUTF8() 0298 { 0299 QClipboard *cb = QApplication::clipboard(); 0300 const QString str = cb->text(); 0301 0302 lined->setText(str.fromUtf8(str.toLatin1())); 0303 } 0304 0305 //================================================================== 0306 // Reverse the text held in the line edit buffer. This is crucial 0307 // for dealing with visual vs. logical representations of 0308 // right to left languages, and handy for working around all 0309 // manner of legacy character order issues. 0310 // 0311 void KCharSelectDia::flipText() 0312 { 0313 QString input; 0314 QString output; 0315 int i; 0316 0317 input = lined->text(); 0318 const int nbLength = input.length(); 0319 for (i = 0; i < nbLength; ++i) { 0320 output.prepend(input.at(i)); 0321 } 0322 lined->setText(output); 0323 } 0324 0325 //================================================================== 0326 void KCharSelectDia::setRtl(bool rtl) 0327 { 0328 _rtl = rtl; 0329 if (_rtl) 0330 lined->setAlignment(Qt::AlignRight); 0331 else 0332 lined->setAlignment(Qt::AlignLeft); 0333 } 0334 0335 //================================================================== 0336 void KCharSelectDia::lineEditChanged() 0337 { 0338 if (_rtl) { 0339 if (lined->cursorPosition()) 0340 lined->setCursorPosition(lined->cursorPosition() - 1); 0341 } 0342 } 0343 0344 #include "moc_kcharselectdia.cpp"