File indexing completed on 2024-04-28 09:47:01

0001 /*
0002  *  SPDX-FileCopyrightText: 2002-2003 Jesper K. Pedersen <blackie@kde.org>
0003  *
0004  *  SPDX-License-Identifier: LGPL-2.0-only
0005  **/
0006 
0007 #include "charselector.h"
0008 
0009 #include <QComboBox>
0010 #include <QHBoxLayout>
0011 #include <QStackedWidget>
0012 
0013 #include <KLocalizedString>
0014 
0015 #include "limitedcharlineedit.h"
0016 #include "regexpconverter.h"
0017 
0018 /**
0019    In the class CharSelector, three LimitedCharLineEdit are used.
0020    These widgets are all used in a QWidgetStack. The LimitedCharLineEdit
0021    class is basically a QLineEdit, which is limited to a certain
0022    number of characters. This conflicts with the QWidgetStack, as this
0023    class expects the widgets on the stack to take up all space.
0024    StackContainer fills in this gab.
0025 */
0026 class StackContainer : public QWidget
0027 {
0028     Q_OBJECT
0029 public:
0030     explicit StackContainer(QWidget *child, QWidget *parent)
0031         : QWidget(parent)
0032     {
0033         QHBoxLayout *layout = new QHBoxLayout(this);
0034         child->setParent(this);
0035         layout->addWidget(child);
0036         layout->addStretch(1);
0037     }
0038 };
0039 
0040 CharSelector::CharSelector(QWidget *parent)
0041     : QWidget(parent)
0042 {
0043     QStringList items;
0044     QHBoxLayout *layout = new QHBoxLayout(this);
0045     layout->setContentsMargins(0, 0, 0, 0);
0046 
0047     _type = new QComboBox(this);
0048     _type->setObjectName(QStringLiteral("_type"));
0049     items << i18n("Normal Character") << i18n("Unicode Char in Hex.") << i18n("Unicode Char in Oct.") << QStringLiteral("----")
0050           << i18n("The Bell Character (\\a)") << i18n("The Form Feed Character (\\f)") << i18n("The Line Feed Character (\\n)")
0051           << i18n("The Carriage Return Character (\\r)") << i18n("The Horizontal Tab Character (\\t)") << i18n("The Vertical Tab Character (\\v)");
0052     _type->addItems(items);
0053     layout->addWidget(_type);
0054 
0055     _stack = new QStackedWidget(this /*, "_stack"*/);
0056     layout->addWidget(_stack);
0057 
0058     _normal = new LimitedCharLineEdit(LimitedCharLineEdit::NORMAL, nullptr, QStringLiteral("_normal"));
0059     _stack->insertWidget(0, new StackContainer(_normal, _stack));
0060 
0061     _hex = new LimitedCharLineEdit(LimitedCharLineEdit::HEX, _stack, QStringLiteral("_hex"));
0062     _stack->insertWidget(1, new StackContainer(_hex, _stack));
0063 
0064     _oct = new LimitedCharLineEdit(LimitedCharLineEdit::OCT, _stack, QStringLiteral("_oct"));
0065     _stack->insertWidget(2, new StackContainer(_oct, _stack));
0066 
0067     _stack->setCurrentIndex(0);
0068 
0069     connect(_type, SIGNAL(activated(int)), this, SLOT(slotNewItem(int)));
0070 }
0071 
0072 void CharSelector::slotNewItem(int which)
0073 {
0074     _type->setCurrentIndex(which);
0075     if (which <= 2) {
0076         _stack->setCurrentIndex(which);
0077         _normal->setEnabled(true);
0078         _hex->setEnabled(true);
0079         _oct->setEnabled(true);
0080     } else if (which == 3) {
0081         _type->setCurrentIndex(_oldIndex);
0082         slotNewItem(_oldIndex);
0083         return;
0084     } else {
0085         _normal->setEnabled(false);
0086         _hex->setEnabled(false);
0087         _oct->setEnabled(false);
0088     }
0089 
0090     _oldIndex = which;
0091 }
0092 
0093 void CharSelector::setText(const QString &text)
0094 {
0095     // This is the best I can do about missing character range features, unless all of
0096     // textrangeregexp is to be reworked. The problem is that textrangeregexp only allows to
0097     // get the characters, which would be something like \a, but \a does not work with say Emacs
0098     // style regexps -- ko28 Sep. 2003 10:55 -- Jesper K. Pedersen
0099     bool enabled = (RegExpConverter::current()->features() & RegExpConverter::ExtRange);
0100     _type->setEnabled(enabled);
0101 
0102     if (text.mid(0, 1) == QLatin1Char('\\')) {
0103         if (text.mid(1, 1) == QLatin1Char('x')) {
0104             _hex->setText(text.mid(2, 1));
0105             slotNewItem(1);
0106         } else if (text.mid(1, 1) == QLatin1Char('0')) {
0107             _oct->setText(text.mid(2, 1));
0108             slotNewItem(2);
0109         } else if (text.mid(1, 1) == QLatin1Char('a')) {
0110             slotNewItem(4);
0111         } else if (text.mid(1, 1) == QLatin1Char('f')) {
0112             slotNewItem(5);
0113         } else if (text.mid(1, 1) == QLatin1Char('n')) {
0114             slotNewItem(6);
0115         } else if (text.mid(1, 1) == QLatin1Char('r')) {
0116             slotNewItem(7);
0117         } else if (text.mid(1, 1) == QLatin1Char('t')) {
0118             slotNewItem(8);
0119         } else if (text.mid(1, 1) == QLatin1Char('v')) {
0120             slotNewItem(9);
0121         } else {
0122             qWarning("Warning %s:%d Unknown escape %s", __FILE__, __LINE__, qPrintable(text));
0123         }
0124     } else {
0125         slotNewItem(0);
0126         _normal->setText(text);
0127     }
0128 }
0129 
0130 bool CharSelector::isEmpty() const
0131 {
0132     return (_type->currentIndex() == 0 && _normal->text().isEmpty()) || (_type->currentIndex() == 1 && _hex->text().isEmpty())
0133         || (_type->currentIndex() == 2 && _oct->text().isEmpty());
0134 }
0135 
0136 QString CharSelector::text() const
0137 {
0138     switch (_type->currentIndex()) {
0139     case 0: // Normal Character
0140         return _normal->text();
0141     case 1: // Hex
0142         return QStringLiteral("\\x") + _hex->text();
0143     case 2: // Oct
0144         return QStringLiteral("\\0") + _oct->text();
0145     case 3: // The separator
0146         break;
0147     case 4:
0148         return QStringLiteral("\\a");
0149     case 5:
0150         return QStringLiteral("\\f");
0151     case 6:
0152         return QStringLiteral("\\n");
0153     case 7:
0154         return QStringLiteral("\\r");
0155     case 8:
0156         return QStringLiteral("\\t");
0157     case 9:
0158         return QStringLiteral("\\v");
0159     }
0160     return QString();
0161 }
0162 
0163 #include "charselector.moc"
0164 
0165 #include "moc_charselector.cpp"