1 /***************************************************************************
2 * Copyright (C) 2008 by Simon Andreas Eugster (simon.eu@gmail.com) *
4 * This program is free software; you can redistribute it and/or modify *
5 * it under the terms of the GNU General Public License as published by *
6 * the Free Software Foundation; either version 2 of the License, or *
7 * (at your option) any later version. *
8 ***************************************************************************/
10 #include "unicodedialog.h"
14 const int MAX_LENGTH_HEX = 4;
15 const uint MAX_UNICODE_V1 = 65535;
18 /// CONSTRUCTORS/DECONSTRUCTORS
20 UnicodeDialog::UnicodeDialog(InputMethod inputMeth) : inputMethod(inputMeth), lastCursorPos(0), lastUnicodeNumber("")
23 connect(unicodeNumber, SIGNAL(textChanged(QString)), this, SLOT(slotTextChanged(QString)));
24 connect(unicodeNumber, SIGNAL(returnPressed()), this, SLOT(slotReturnPressed()));
25 connect(arrowUp, SIGNAL(clicked()), this, SLOT(slotNextUnicode()));
26 connect(arrowDown, SIGNAL(clicked()), this, SLOT(slotPrevUnicode()));
28 switch (inputMethod) {
30 unicodeNumber->setMaxLength(MAX_LENGTH_HEX);
37 arrowUp->setShortcut(Qt::Key_Up);
38 arrowDown->setShortcut(Qt::Key_Down);
40 arrowUp->setToolTip(i18n("Next Unicode character (Arrow Up)"));
41 arrowDown->setToolTip(i18n("Previous Unicode character (Arrow Down)"));
42 unicodeNumber->setToolTip(i18n("Enter your Unicode number here. Allowed characters: [0-9] and [a-f]."));
45 UnicodeDialog::~UnicodeDialog()
52 void UnicodeDialog::showLastUnicode()
54 unicodeNumber->setText(lastUnicodeNumber);
57 bool UnicodeDialog::controlCharacter(QString text)
59 bool isControlCharacter = false;
60 QString t = text.toLower();
62 switch (inputMethod) {
65 || (t.length() == 1 && !(t == "9" || t == "a" || t == "d"))
66 || (t.length() == 2 && t.at(0) == QChar('1'))) {
67 isControlCharacter = true;
73 isControlCharacter = controlCharacter(text.toUInt(&ok, 16));
77 return isControlCharacter;
80 bool UnicodeDialog::controlCharacter(uint value)
82 bool isControlCharacter = false;
84 if (value < 32 && !(value == 9 || value == 10 || value == 13)) {
85 isControlCharacter = true;
87 return isControlCharacter;
91 QString UnicodeDialog::trimmedUnicodeNumber(QString text)
93 while (text.length() > 0 && text.at(0) == QChar('0')) {
94 text = text.remove(0, 1);
99 QString UnicodeDialog::unicodeInfo(QString unicode_number)
101 QString infoText(i18n("<small>(no character selected)</small>"));
102 if (unicode_number.length() == 0) return infoText;
104 QString u = trimmedUnicodeNumber(unicode_number).toLower();
106 if (controlCharacter(u)) {
107 infoText = i18n("Control character. Cannot be inserted/printed. See <a href=\"http://en.wikipedia.org/wiki/Control_character\">Wikipedia:Control_character</a>");
108 } else if (u == "a") {
109 infoText = i18n("Line Feed (newline character, \\\\n)");
110 } else if (u == "20") {
111 infoText = i18n("Standard space character. (See U+00a0 and U+2000–200b)");
112 } else if (u == "a0") {
113 infoText = i18n("No-break space. &nbsp; in HTML. See U+0020.");
114 } else if (u == "2002") {
115 infoText = i18n("En Space (width of an n)");
116 } else if (u == "2003") {
117 infoText = i18n("Em Space (width of an m)");
118 } else if (u == "2004") {
119 infoText = i18n("Three-Per-Em Space. Width: 1/3 of one <em>em</em>");
120 } else if (u == "2005") {
121 infoText = i18n("Four-Per-Em Space. Width: 1/4 of one <em>em</em>");
122 } else if (u == "2006") {
123 infoText = i18n("Six-Per-Em Space. Width: 1/6 of one <em>em</em>");
124 } else if (u == "2007") {
125 infoText = i18n("Figure space (non-breaking). Width of a digit if digits have fixed width in this font.");
126 } else if (u == "2008") {
127 infoText = i18n("Punctuation Space. Width the same as between a punctuation character and the next character.");
128 } else if (u == "2009") {
129 infoText = i18n("Thin space, in HTML also &thinsp;. See <a href=\"http://en.wikipedia.org/wiki/Space_(punctuation)\">Wikipedia:Space_(punctuation)</a>");
130 } else if (u == "200a") {
131 infoText = i18n("Hair Space. Thinner than U+2009.");
132 } else if (u == "2019") {
133 infoText = i18n("Punctuation Apostrophe. Should be used instead of U+0027. See <a href=\"http://en.wikipedia.org/wiki/Apostrophe\">Wikipedia:Apostrophe</a>");
134 } else if (u == "2013") {
135 infoText = i18n("An en Dash (dash of the width of an n). See <a href=\"http://en.wikipedia.org/wiki/Dash\">Wikipedia:Dash</a>");
136 } else if (u == "2014") {
137 infoText = i18n("An em Dash (dash of the widht of an m). See <a href=\"http://en.wikipedia.org/wiki/Dash\">Wikipedia:Dash</a>");
138 } else if (u == "2026") {
139 infoText = i18n("Ellipsis: If text has been left out. See <a href=\"http://en.wikipedia.org/wiki/Ellipsis\">Wikipedia:Ellipsis</a>");
141 infoText = i18n("<small>No additional information available for this character.</small>");
147 QString UnicodeDialog::validateText(QString text)
149 QRegExp regex("([0-9]|[a-f])", Qt::CaseInsensitive, QRegExp::RegExp2);
150 QString newText = "";
153 switch (inputMethod) {
155 // Remove all characters we don't want
156 while ((pos = regex.indexIn(text, pos)) != -1) {
157 newText += regex.cap(1);
170 void UnicodeDialog::updateOverviewChars(uint unicode)
176 for (i = 1; i <= 4; i++) {
177 if (unicode > i && !controlCharacter(unicode - i)) {
179 left = QChar(unicode - i) + left;
183 for (i = 1; i <= 8; i++) {
184 if (unicode + i <= MAX_UNICODE_V1 && !controlCharacter(unicode + i)) {
185 right += QChar(unicode + i);
190 leftChars->setText(left);
191 rightChars->setText(right);
195 void UnicodeDialog::clearOverviewChars()
197 leftChars->setText("");
198 rightChars->setText("");
201 QString UnicodeDialog::nextUnicode(QString text, Direction direction)
204 QString newText = "";
207 switch (inputMethod) {
209 value = text.toUInt(&ok, 16);
219 if (value == (uint) - 1) value = MAX_UNICODE_V1;
220 if (value > MAX_UNICODE_V1) value = 0;
222 newText.setNum(value, 16);
236 * \brief Validates the entered Unicode number and displays its Unicode character.
238 void UnicodeDialog::slotTextChanged(QString text)
240 unicodeNumber->blockSignals(true);
242 QString newText = validateText(text);
243 if (newText.length() == 0) {
244 unicodeChar->setText("");
245 unicodeNumber->setText("");
246 clearOverviewChars();
248 lastUnicodeNumber = "";
249 labelInfoText->setText(unicodeInfo(""));
253 int cursorPos = unicodeNumber->cursorPosition();
255 unicodeNumber->setText(newText);
256 unicodeNumber->setCursorPosition(cursorPos);
258 // Get the decimal number as uint to create the QChar from
261 switch (inputMethod) {
263 value = newText.toUInt(&ok, 16);
266 value = newText.toUInt(&ok, 10);
269 updateOverviewChars(value);
272 // Impossible! validateText never fails!
275 // If an invalid character has been entered:
276 // Reset the cursor position because the entered char has been deleted.
277 if (text != newText && newText == lastUnicodeNumber) {
278 unicodeNumber->setCursorPosition(lastCursorPos);
281 lastCursorPos = unicodeNumber->cursorPosition();
282 lastUnicodeNumber = newText;
284 labelInfoText->setText(unicodeInfo(newText));
285 unicodeChar->setText(QChar(value));
288 unicodeNumber->blockSignals(false);
292 * When return pressed, we return the selected unicode character
293 * if it was not a control character.
295 void UnicodeDialog::slotReturnPressed()
297 QString text = trimmedUnicodeNumber(unicodeNumber->text());
298 if (!controlCharacter(text)) {
299 emit charSelected(unicodeChar->text());
304 void UnicodeDialog::slotNextUnicode()
306 QString text = unicodeNumber->text();
307 unicodeNumber->setText(nextUnicode(text, Forward));
310 void UnicodeDialog::slotPrevUnicode()
312 QString text = unicodeNumber->text();
313 unicodeNumber->setText(nextUnicode(text, Backward));
316 #include "unicodedialog.moc"