X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=src%2Funicodedialog.cpp;h=d55c30dfaffe1edca32bda5b06fdb1b642d9e0f0;hb=56aee6aedeeed3efd10ada8fe3c229eddc01ef05;hp=af995cac3d1555050a9bcd17fd72ec119e7df173;hpb=f5fdff8ba148a9628e3e4b66377dda49312869f4;p=kdenlive diff --git a/src/unicodedialog.cpp b/src/unicodedialog.cpp index af995cac..d55c30df 100644 --- a/src/unicodedialog.cpp +++ b/src/unicodedialog.cpp @@ -6,88 +6,292 @@ * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * ***************************************************************************/ - + #include "unicodedialog.h" +#include + /// CONSTANTS const int MAX_LENGTH_HEX = 4; - - -/// CONSTRUCTORS/DECONSTRUCTORS +const uint MAX_UNICODE_V1 = 65535; -UnicodeDialog::UnicodeDialog(InputMethod inputMeth) : inputMethod(inputMeth), lastCursorPos(0), lastUnicodeNumber("") + +UnicodeDialog::UnicodeDialog(InputMethod inputMeth, QWidget *parent) + : KDialog(parent) { - setupUi(this); - connect(unicodeNumber, SIGNAL(textChanged(QString)), this, SLOT(slotTextChanged(QString))); - connect(unicodeNumber, SIGNAL(returnPressed()), this, SLOT(slotReturnPressed())); - - switch (inputMethod) { - case InputHex: - unicodeNumber->setMaxLength(MAX_LENGTH_HEX); - break; - - case InputDec: - break; - } + setCaption( i18n("Details") ); + setButtons( Ok|Cancel ); + mUnicodeWidget = new UnicodeWidget(inputMeth); + connect(mUnicodeWidget, SIGNAL(charSelected(QString)), SIGNAL(charSelected(QString))); + setMainWidget(mUnicodeWidget); + connect(this, SIGNAL(okClicked()), SLOT(slotAccept())); } UnicodeDialog::~UnicodeDialog() { } +void UnicodeDialog::slotAccept() +{ + mUnicodeWidget->slotReturnPressed(); + accept(); +} + + +/// CONSTRUCTORS/DECONSTRUCTORS + +UnicodeWidget::UnicodeWidget(UnicodeDialog::InputMethod inputMeth, QWidget *parent) + : QWidget(parent), + inputMethod(inputMeth), + m_lastCursorPos(0) +{ + setupUi(this); + readChoices(); + showLastUnicode(); + connect(unicodeNumber, SIGNAL(textChanged(QString)), this, SLOT(slotTextChanged(QString))); + connect(unicodeNumber, SIGNAL(returnPressed()), this, SLOT(slotReturnPressed())); + connect(arrowUp, SIGNAL(clicked()), this, SLOT(slotPrevUnicode())); + connect(arrowDown, SIGNAL(clicked()), this, SLOT(slotNextUnicode())); + + switch (inputMethod) { + case UnicodeDialog::InputHex: + unicodeNumber->setMaxLength(MAX_LENGTH_HEX); + break; + case UnicodeDialog::InputDec: + break; + } + + arrowUp->setShortcut(Qt::Key_Up); + arrowDown->setShortcut(Qt::Key_Down); + unicode_link->setText(i18n("Information about unicode characters: http://decodeunicode.org")); + arrowUp->setToolTip(i18n("Previous Unicode character (Arrow Up)")); + arrowDown->setToolTip(i18n("Next Unicode character (Arrow Down)")); + unicodeNumber->setToolTip(i18n("Enter your Unicode number here. Allowed characters: [0-9] and [a-f].")); + unicodeNumber->selectAll(); // Selection will be reset by setToolTip and similar, so set it here +} + +UnicodeWidget::~UnicodeWidget() +{ +} /// METHODS -QString UnicodeDialog::unicodeInfo(QString unicode_number) -{ - QString infoText(""); - QString u = unicode_number; - - while (unicode_number.at(0) == QChar('0')) { - unicode_number = unicode_number.remove(0, 1); - } - - if (false) { - // Just a placeholder for reason of ease (shifting around lines) - } else if (u == "2009") { - infoText = i18n("A thin space, in HTML also &thinsp;. See Wikipedia:Space_(punctuation)"); - } else if (u == "2019") { - infoText = i18n("Punctuation Apostrophe. Should be used instead of U+0027. See Wikipedia:Apostrophe"); - } else if (u == "2013") { - infoText = i18n("An en Dash (dash of the width of an n). See Wikipedia:Dash"); - } else if (u == "2014") { - infoText = i18n("An em Dash (dash of the widht of an m). See Wikipedia:Dash"); - } else if (u == "2026") { - infoText = i18n("Ellipsis: If text has been left out. See Wikipedia:Ellipsis"); - } - - return infoText; +void UnicodeWidget::showLastUnicode() +{ + unicodeNumber->setText(m_lastUnicodeNumber); + unicodeNumber->selectAll(); + slotTextChanged(m_lastUnicodeNumber); } -/** - * Validates an Unicode number. - */ -QString UnicodeDialog::validateText(QString text) -{ - QRegExp regex("([0-9]|[a-f])", Qt::CaseInsensitive, QRegExp::RegExp2); - QString newText = ""; - int pos = 0; - - switch (inputMethod) { - case InputHex: - while ((pos = regex.indexIn(text, pos)) != -1) { - newText += regex.cap(1); - pos++; - } - break; - - case InputDec: - // TODO - break; - } - - return newText; +bool UnicodeWidget::controlCharacter(const QString &text) +{ + bool isControlCharacter = false; + QString t = text.toLower(); + + switch (inputMethod) { + case UnicodeDialog::InputHex: + if (t.isEmpty() + || (t.length() == 1 && !(t == "9" || t == "a" || t == "d")) + || (t.length() == 2 && t.at(0) == QChar('1'))) { + isControlCharacter = true; + } + break; + + case UnicodeDialog::InputDec: + bool ok; + isControlCharacter = controlCharacter(text.toUInt(&ok, 16)); + break; + } + + return isControlCharacter; +} + +bool UnicodeWidget::controlCharacter(uint value) +{ + bool isControlCharacter = false; + + if (value < 32 && !(value == 9 || value == 10 || value == 13)) { + isControlCharacter = true; + } + return isControlCharacter; + +} + +QString UnicodeWidget::trimmedUnicodeNumber(QString text) +{ + while (!text.isEmpty() && text.at(0) == QChar('0')) { + text = text.remove(0, 1); + } + return text; +} + +QString UnicodeWidget::unicodeInfo(const QString &unicode) +{ + QString infoText(i18n("(no character selected)")); + if (unicode.length() == 0) return infoText; + + QString u = trimmedUnicodeNumber(unicode).toLower(); + + if (controlCharacter(u)) { + infoText = i18n("Control character. Cannot be inserted/printed. See Wikipedia:Control_character"); + } else if (u == "a") { + infoText = i18n("Line Feed (newline character, \\\\n)"); + } else if (u == "20") { + infoText = i18n("Standard space character. (Other space characters: U+00a0, U+2000–200b, U+202f)"); + } else if (u == "a0") { + infoText = i18n("No-break space. &nbsp; in HTML. See U+2009 and U+0020."); + } else if (u == "ab" || u == "bb" || u == "2039" || u == "203a") { + infoText = i18n("

« (u+00ab, &lfquo; in HTML) and » (u+00bb, &rfquo; in HTML) are called Guillemets or angle quotes. Usage in different countries: France (with non-breaking Space 0x00a0), Switzerland, Germany, Finland and Sweden.

and (U+2039/203a, &lsaquo;/&rsaquo;) are their single quote equivalents.

See Wikipedia:Guillemets

"); + } else if (u == "2002") { + infoText = i18n("En Space (width of an n)"); + } else if (u == "2003") { + infoText = i18n("Em Space (width of an m)"); + } else if (u == "2004") { + infoText = i18n("Three-Per-Em Space. Width: 1/3 of one em"); + } else if (u == "2005") { + infoText = i18n("Four-Per-Em Space. Width: 1/4 of one em"); + } else if (u == "2006") { + infoText = i18n("Six-Per-Em Space. Width: 1/6 of one em"); + } else if (u == "2007") { + infoText = i18n("Figure space (non-breaking). Width of a digit if digits have fixed width in this font."); + } else if (u == "2008") { + infoText = i18n("Punctuation Space. Width the same as between a punctuation character and the next character."); + } else if (u == "2009") { + infoText = i18n("Thin space, in HTML also &thinsp;. See U+202f and Wikipedia:Space_(punctuation)"); + } else if (u == "200a") { + infoText = i18n("Hair Space. Thinner than U+2009."); + } else if (u == "2019") { + infoText = i18n("Punctuation Apostrophe. Should be used instead of U+0027. See Wikipedia:Apostrophe"); + } else if (u == "2013") { + infoText = i18n("

An en Dash (dash of the width of an n).

Usage examples: In English language for value ranges (1878–1903), for relationships/connections (Zurich–Dublin). In the German language it is also used (with spaces!) for showing thoughts: “Es war – wie immer in den Ferien – ein regnerischer Tag.

See Wikipedia:Dash

"); + } else if (u == "2014") { + infoText = i18n("

An em Dash (dash of the width of an m).

Usage examples: In English language to mark—like here—thoughts. Traditionally without spaces.

See Wikipedia:Dash

"); + } else if (u == "202f") { + infoText = i18n("

Narrow no-break space. Has the same width as U+2009.

Usage: For units (spaces are marked with U+2423, ␣): 230␣V, −21␣°C, 50␣lb, but 90° (no space). In German for abbreviations (like: i. d. R. instead of i. d. R. with U+00a0).

See Wikipedia:de:Schmales_Leerzeichen

"); + } else if (u == "2026") { + infoText = i18n("Ellipsis: If text has been left o… See Wikipedia:Ellipsis"); + } else if (u == "2212") { + infoText = i18n("Minus sign. For numbers: −42"); + } else if (u == "2423") { + infoText = i18n("Open box; stands for a space."); + } else if (u == "2669") { + infoText = i18n("Quarter note (Am.) or crochet (Brit.). See Wikipedia:Quarter_note"); + } else if (u == "266a" || u == "266b") { + infoText = i18n("Eighth note (Am.) or quaver (Brit.). Half as long as a quarter note (U+2669). See Wikipedia:Eighth_note"); + } else if (u == "266c") { + infoText = i18n("Sixteenth note (Am.) or semiquaver (Brit.). Half as long as an eighth note (U+266a). See Wikipedia:Sixteenth_note"); + } else if (u == "1D162") { + infoText = i18n("Thirty-second note (Am.) or demisemiquaver (Brit.). Half as long as a sixteenth note (U+266b). See Wikipedia:Thirty-second_note"); + } else { + infoText = i18n("No additional information available for this character."); + } + + return infoText; +} + +QString UnicodeWidget::validateText(const QString &text) +{ + QRegExp regex("([0-9]|[a-f])", Qt::CaseInsensitive, QRegExp::RegExp2); + QString newText; + int pos = 0; + + switch (inputMethod) { + case UnicodeDialog::InputHex: + // Remove all characters we don't want + while ((pos = regex.indexIn(text, pos)) != -1) { + newText += regex.cap(1); + pos++; + } + break; + + case UnicodeDialog::InputDec: + // TODO + break; + } + + return newText; +} + +void UnicodeWidget::updateOverviewChars(uint unicode) +{ + QString left; + QString right; + uint i; + + for (i = 1; i <= 4; ++i) { + if (unicode > i && !controlCharacter(unicode - i)) { + left = ' ' + left; + left = QChar(unicode - i) + left; + } + } + + for (i = 1; i <= 8; ++i) { + if (unicode + i <= MAX_UNICODE_V1 && !controlCharacter(unicode + i)) { + right += QChar(unicode + i); + right += ' '; + } + } + + leftChars->setText(left); + rightChars->setText(right); + +} + +void UnicodeWidget::clearOverviewChars() +{ + leftChars->setText(""); + rightChars->setText(""); +} + +QString UnicodeWidget::nextUnicode(const QString &text, Direction direction) +{ + uint value = 0; + QString newText; + bool ok; + + switch (inputMethod) { + case UnicodeDialog::InputHex: + value = text.toUInt(&ok, 16); + switch (direction) { + case Backward: + value--; + break; + default: + value++; + break; + } + // Wrapping + if (value == (uint) - 1) value = MAX_UNICODE_V1; + if (value > MAX_UNICODE_V1) value = 0; + + newText.setNum(value, 16); + break; + + case UnicodeDialog::InputDec: + break; + } + + return newText; +} + +void UnicodeWidget::readChoices() +{ + // Get a pointer to a shared configuration instance, then get the TitleWidget group. + KSharedConfigPtr config = KGlobal::config(); + KConfigGroup titleConfig(config, "TitleWidget"); + + // Default is 2013 because there is also (perhaps interesting) information. + m_lastUnicodeNumber = titleConfig.readEntry("unicode_number", QString("2013")); +} + +void UnicodeWidget::writeChoices() +{ + // Get a pointer to a shared configuration instance, then get the TitleWidget group. + KSharedConfigPtr config = KGlobal::config(); + KConfigGroup titleConfig(config, "TitleWidget"); + + titleConfig.writeEntry("unicode_number", m_lastUnicodeNumber); } @@ -96,49 +300,93 @@ QString UnicodeDialog::validateText(QString text) /** * \brief Validates the entered Unicode number and displays its Unicode character. */ -void UnicodeDialog::slotTextChanged(QString text) -{ - unicodeNumber->blockSignals(true); - - bool ok; - int cursorPos = unicodeNumber->cursorPosition(); - QString newText = validateText(text); - - unicodeNumber->setText(newText); - unicodeNumber->setCursorPosition(cursorPos); - - uint value; - switch (inputMethod) { - case InputHex: - value = newText.toUInt(&ok, 16); - break; - case InputDec: - value = newText.toUInt(&ok, 10); - break; - } - - if (!ok) { - //TODO! - } - - // If an invalid character has been entered: - // Reset the cursor position because the entered char has been deleted. - if (text != newText && newText == lastUnicodeNumber) { - unicodeNumber->setCursorPosition(lastCursorPos); - } - - lastCursorPos = unicodeNumber->cursorPosition(); - lastUnicodeNumber = newText; - - labelInfoText->setText(unicodeInfo(newText)); - unicodeChar->setText(QChar(value)); - unicodeNumber->blockSignals(false); -} - -void UnicodeDialog::slotReturnPressed() -{ - emit charSelected(unicodeChar->text()); - emit accept(); +void UnicodeWidget::slotTextChanged(const QString &text) +{ + unicodeNumber->blockSignals(true); + + QString newText = validateText(text); + if (newText.length() == 0) { + unicodeChar->setText(""); + unicodeNumber->setText(""); + clearOverviewChars(); + m_lastCursorPos = 0; + m_lastUnicodeNumber = ""; + labelInfoText->setText(unicodeInfo("")); + + } else { + + int cursorPos = unicodeNumber->cursorPosition(); + + unicodeNumber->setText(newText); + unicodeNumber->setCursorPosition(cursorPos); + + // Get the decimal number as uint to create the QChar from + bool ok; + uint value = 0; + switch (inputMethod) { + case UnicodeDialog::InputHex: + value = newText.toUInt(&ok, 16); + break; + case UnicodeDialog::InputDec: + value = newText.toUInt(&ok, 10); + break; + } + updateOverviewChars(value); + + if (!ok) { + // Impossible! validateText never fails! + } + + // If an invalid character has been entered: + // Reset the cursor position because the entered char has been deleted. + if (text != newText && newText == m_lastUnicodeNumber) { + unicodeNumber->setCursorPosition(m_lastCursorPos); + } + + m_lastCursorPos = unicodeNumber->cursorPosition(); + m_lastUnicodeNumber = newText; + + labelInfoText->setText(unicodeInfo(newText)); + unicodeChar->setText(QChar(value)); + } + + unicodeNumber->blockSignals(false); +} + +/** + * When return pressed, we return the selected unicode character + * if it was not a control character. + */ +void UnicodeWidget::slotReturnPressed() +{ + unicodeNumber->setFocus(); + const QString text = trimmedUnicodeNumber(unicodeNumber->text()); + if (!controlCharacter(text)) { + emit charSelected(unicodeChar->text()); + writeChoices(); + } +} + +void UnicodeWidget::slotNextUnicode() +{ + const QString text = unicodeNumber->text(); + unicodeNumber->setText(nextUnicode(text, Forward)); +} + +void UnicodeWidget::slotPrevUnicode() +{ + const QString text = unicodeNumber->text(); + unicodeNumber->setText(nextUnicode(text, Backward)); +} + +void UnicodeWidget::wheelEvent(QWheelEvent * event) +{ + if (frame->underMouse()) { + if (event->delta() > 0) + slotNextUnicode(); + else + slotPrevUnicode(); + } } #include "unicodedialog.moc"