]> git.sesse.net Git - kdenlive/blob - src/unicodedialog.cpp
Unicode Dialog extended (character list, shortcuts for next/prev character, test...
[kdenlive] / src / unicodedialog.cpp
1 /***************************************************************************
2  *   Copyright (C) 2008 by Simon Andreas Eugster (simon.eu@gmail.com)      *
3  *                                                                         *
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  ***************************************************************************/
9  
10 #include "unicodedialog.h"
11
12 /// CONSTANTS
13
14 const int MAX_LENGTH_HEX = 4;
15 const uint MAX_UNICODE_V1 = 65535;
16  
17  
18 /// CONSTRUCTORS/DECONSTRUCTORS
19
20 UnicodeDialog::UnicodeDialog(InputMethod inputMeth) : inputMethod(inputMeth), lastCursorPos(0), lastUnicodeNumber("")
21 {
22         setupUi(this);
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()));
27         
28         switch (inputMethod) {
29                 case InputHex:
30                         unicodeNumber->setMaxLength(MAX_LENGTH_HEX);
31                 break;
32                 
33                 case InputDec:
34                 break;
35         }
36         
37         arrowUp->setShortcut(Qt::Key_Up);
38         arrowDown->setShortcut(Qt::Key_Down);
39         
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]."));
43 }
44
45 UnicodeDialog::~UnicodeDialog()
46 {
47 }
48
49
50 /// METHODS
51
52 void UnicodeDialog::showLastUnicode()
53 {
54         unicodeNumber->setText(lastUnicodeNumber);
55 }
56
57 bool UnicodeDialog::controlCharacter(QString text)
58 {
59         bool isControlCharacter = false;
60         QString t = text.toLower();
61         
62         switch (inputMethod) {
63                 case InputHex:
64                         if (t == "" 
65                                 || (t.length() == 1 && !(t == "9" || t == "a" || t == "d"))
66                                 || (t.length() == 2 && t.at(0) == QChar('1'))) {
67                                 isControlCharacter = true;
68                         }
69                         break;
70                         
71                 case InputDec:
72                         bool ok;
73                         isControlCharacter = controlCharacter(text.toUInt(&ok, 16));
74                         break;
75         }
76         
77         return isControlCharacter;
78 }
79
80 bool UnicodeDialog::controlCharacter(uint value)
81 {
82         bool isControlCharacter = false;
83         
84         if (value < 32 && !(value == 9 || value == 10 || value == 13)) {
85                 isControlCharacter = true;
86         }
87         return isControlCharacter;
88         
89 }
90
91 QString UnicodeDialog::trimmedUnicodeNumber(QString text)
92 {
93         while (text.length() > 0 && text.at(0) == QChar('0')) {
94                 text = text.remove(0, 1);
95         }
96         return text;
97 }
98
99 QString UnicodeDialog::unicodeInfo(QString unicode_number)
100 {
101         QString infoText(i18n("<small>(no character selected)</small>"));
102         if (unicode_number.length() == 0) return infoText;
103         
104         QString u = trimmedUnicodeNumber(unicode_number).toLower();
105         
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&#x2013;200b)");
112         } else if (u == "a0") {
113                 infoText = i18n("No-break space. &amp;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 &amp;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>");
140         } else {
141                 infoText = i18n("<small>No additional information available for this character.</small>");
142         }
143         
144         return infoText;
145 }
146
147 QString UnicodeDialog::validateText(QString text)
148 {
149         QRegExp regex("([0-9]|[a-f])", Qt::CaseInsensitive, QRegExp::RegExp2);
150         QString newText = "";
151         int pos = 0;
152         
153         switch (inputMethod) {
154                 case InputHex:
155                         // Remove all characters we don't want
156                         while ((pos = regex.indexIn(text, pos)) != -1) {
157                                 newText += regex.cap(1);
158                                 pos++;
159                         }
160                 break;
161                 
162                 case InputDec:
163                         // TODO
164                 break;
165         }
166         
167         return newText;
168 }
169
170 void UnicodeDialog::updateOverviewChars(uint unicode)
171 {
172         QString left = "";
173         QString right = "";
174         uint i;
175         
176         for (i = 1; i <= 4; i++) {
177                 if (unicode > i && !controlCharacter(unicode-i)) {
178                         left = " " + left;
179                         left = QChar(unicode-i) + left;
180                 }
181         }
182         
183         for (i = 1; i <= 8; i++) {
184                 if (unicode + i <= MAX_UNICODE_V1 && !controlCharacter(unicode+i)) {
185                         right += QChar(unicode+i);
186                         right += " ";
187                 }
188         }
189         
190         leftChars->setText(left);
191         rightChars->setText(right);
192         
193 }
194
195 QString UnicodeDialog::nextUnicode(QString text, Direction direction)
196 {
197         uint value = 0;
198         QString newText = "";
199         bool ok;
200         
201         switch (inputMethod) {
202                 case InputHex:
203                         value = text.toUInt(&ok, 16);
204                         switch (direction) {
205                                 case Backward:
206                                         value--;
207                                         break;
208                                 default:
209                                         value++;
210                                         break;
211                         }
212                         // Wrapping
213                         if (value == (uint) -1) value = MAX_UNICODE_V1;
214                         if (value > MAX_UNICODE_V1) value = 0;
215                         
216                         newText.setNum(value, 16);
217                         break;
218                         
219                 case InputDec:
220                         break;
221         }
222         
223         return newText;
224 }
225
226
227 /// SLOTS
228
229 /**
230  * \brief Validates the entered Unicode number and displays its Unicode character.
231  */
232 void UnicodeDialog::slotTextChanged(QString text)
233 {
234         unicodeNumber->blockSignals(true);
235         
236         QString newText = validateText(text);
237         if (newText.length() == 0) {
238                 unicodeChar->setText("");
239                 unicodeNumber->setText("");
240                 lastCursorPos = 0;
241                 lastUnicodeNumber = "";
242                 labelInfoText->setText(unicodeInfo(""));
243                 
244         } else {
245                 
246                 int cursorPos = unicodeNumber->cursorPosition();
247                 
248                 unicodeNumber->setText(newText);
249                 unicodeNumber->setCursorPosition(cursorPos);
250                 
251                 // Get the decimal number as uint to create the QChar from
252                 bool ok;
253                 uint value = 0;
254                 switch (inputMethod) {
255                         case InputHex:
256                                 value = newText.toUInt(&ok, 16);
257                         break;
258                         case InputDec:
259                                 value = newText.toUInt(&ok, 10);
260                         break;
261                 }
262                 updateOverviewChars(value);
263                 
264                 if (!ok) {
265                         // Impossible! validateText never fails!
266                 }
267                 
268                 // If an invalid character has been entered:
269                 // Reset the cursor position because the entered char has been deleted.
270                 if (text != newText && newText == lastUnicodeNumber) {
271                         unicodeNumber->setCursorPosition(lastCursorPos);
272                 }
273                 
274                 lastCursorPos = unicodeNumber->cursorPosition();
275                 lastUnicodeNumber = newText;
276                 
277                 labelInfoText->setText(unicodeInfo(newText));
278                 unicodeChar->setText(QChar(value));
279         }
280         
281         unicodeNumber->blockSignals(false);
282 }
283
284 /**
285  * When return pressed, we return the selected unicode character
286  * if it was not a control character.
287  */
288 void UnicodeDialog::slotReturnPressed() 
289 {
290         QString text = trimmedUnicodeNumber(unicodeNumber->text());
291         if (!controlCharacter(text)) {
292                 emit charSelected(unicodeChar->text());
293         }
294         emit accept();
295 }
296
297 void UnicodeDialog::slotNextUnicode()
298 {
299         QString text = unicodeNumber->text();
300         unicodeNumber->setText(nextUnicode(text, Forward));
301 }
302
303 void UnicodeDialog::slotPrevUnicode()
304 {
305         QString text = unicodeNumber->text();
306         unicodeNumber->setText(nextUnicode(text, Backward));
307 }
308
309 #include "unicodedialog.moc"