diff --git a/kcms/keyboard/CMakeLists.txt b/kcms/keyboard/CMakeLists.txt --- a/kcms/keyboard/CMakeLists.txt +++ b/kcms/keyboard/CMakeLists.txt @@ -1,8 +1,9 @@ add_definitions(-DTRANSLATION_DOMAIN=\"kcmkeyboard\") +add_subdirectory(tastenbrett) + option(HAVE_XINPUT "X11 XInput" OFF) option(HAVE_UDEV "UDev" OFF) -option(NEW_GEOMETRY "Keyboard geometry preview" OFF) if (X11_Xinput_FOUND) set(HAVE_XINPUT ON) @@ -12,7 +13,6 @@ message(STATUS "X11 XInput and UDev is not found, either is required to keep layouts with keyboard hotplugging") endif() - ### kded daemon ### set( kded_keyboard_SRCS @@ -79,37 +79,6 @@ install( TARGETS kded_keyboard DESTINATION ${KDE_INSTALL_PLUGINDIR}/kf5/kded ) ### kcm keyboard ### -include_directories("preview") - -find_package(Boost) - -if(Boost_FOUND) - set(NEW_GEOMETRY ON) - - set(preview_SRCS - preview/geometry_components.cpp - preview/geometry_parser.cpp - preview/kbpreviewframe.cpp - preview/keyboardlayout.cpp - preview/symbol_parser.cpp - preview/keyaliases.cpp - preview/keyboardlayout.cpp - preview/keyboardpainter.cpp - preview/keysymhelper.cpp - preview/keysym2ucs.cpp - ) - - set_source_files_properties(preview/geometry_parser.cpp preview/symbol_parser.cpp PROPERTIES COMPILE_FLAGS "-fexceptions") - if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang") - # the default maximum template expansion depth (256) is not enough - set_property(SOURCE preview/geometry_parser.cpp APPEND_STRING PROPERTY COMPILE_FLAGS " -ftemplate-depth=512") - endif() -else(Boost_FOUND) - - message("Boost not found, install Boost libraries to enable keyboard geometry preview") - -endif(Boost_FOUND) - set(kcm_keyboard_PART_SRCS kcm_keyboard.cpp @@ -124,7 +93,7 @@ iso_codes.cpp kcmmisc.cpp bindings.cpp - ${preview_SRCS} ) + tastenbrett.cpp) ecm_qt_declare_logging_category(kcm_keyboard_PART_SRCS HEADER debug.h @@ -173,3 +142,5 @@ find_package(Qt5Test ${QT_MIN_VERSION} CONFIG REQUIRED) add_subdirectory( tests ) endif() + +add_dependencies(kcm_keyboard tastenbrett) diff --git a/kcms/keyboard/config-keyboard.h.cmake b/kcms/keyboard/config-keyboard.h.cmake --- a/kcms/keyboard/config-keyboard.h.cmake +++ b/kcms/keyboard/config-keyboard.h.cmake @@ -4,6 +4,4 @@ #cmakedefine HAVE_XINPUT #cmakedefine HAVE_UDEV -#cmakedefine NEW_GEOMETRY - #endif // CONFIG_KEYBOARD_H diff --git a/kcms/keyboard/kcm_add_layout_dialog.h b/kcms/keyboard/kcm_add_layout_dialog.h --- a/kcms/keyboard/kcm_add_layout_dialog.h +++ b/kcms/keyboard/kcm_add_layout_dialog.h @@ -23,7 +23,6 @@ #include #include "keyboard_config.h" -#include "preview/keyboardpainter.h" #include @@ -36,23 +35,23 @@ Q_OBJECT public: - AddLayoutDialog(const Rules* rules, Flags* flags, const QString& model, bool showLabel, QWidget* parent=nullptr); + AddLayoutDialog(const Rules* rules, Flags* flags, const QString& model, + const QStringList &options, bool showLabel, QWidget* parent=nullptr); LayoutUnit getSelectedLayoutUnit() { return selectedLayoutUnit; } QString getvariant(QString variant); void accept() override; public Q_SLOTS: void languageChanged(int langIdx); - void layoutChanged(int layoutIdx); -#ifdef NEW_GEOMETRY - void preview(); -#endif + void layoutChanged(int layoutIdx); + void preview(); private: const Rules* rules; Flags* flags; const QString& model; + const QStringList &options; Ui_AddLayoutDialog* layoutDialogUi; QString selectedLanguage; QString selectedLayout; diff --git a/kcms/keyboard/kcm_add_layout_dialog.cpp b/kcms/keyboard/kcm_add_layout_dialog.cpp --- a/kcms/keyboard/kcm_add_layout_dialog.cpp +++ b/kcms/keyboard/kcm_add_layout_dialog.cpp @@ -23,17 +23,19 @@ #include "xkb_rules.h" #include "flags.h" #include "iso_codes.h" +#include "tastenbrett.h" #include "ui_kcm_add_layout_dialog.h" #include - -AddLayoutDialog::AddLayoutDialog(const Rules* rules_, Flags* flags_, const QString& model_, bool showLabel, QWidget* parent): +AddLayoutDialog::AddLayoutDialog(const Rules* rules_, Flags* flags_, const QString& model_, + const QStringList &options_, bool showLabel, QWidget* parent): QDialog(parent), rules(rules_), flags(flags_), - model(model_), + model(model_), + options(options_), selectedLanguage(QStringLiteral("no_language")) { layoutDialogUi = new Ui_AddLayoutDialog(); @@ -69,11 +71,9 @@ languageChanged(0); connect(layoutDialogUi->languageComboBox, static_cast(&QComboBox::activated), this, &AddLayoutDialog::languageChanged); connect(layoutDialogUi->layoutComboBox, static_cast(&QComboBox::activated), this, &AddLayoutDialog::layoutChanged); -#ifdef NEW_GEOMETRY + connect(layoutDialogUi->prevbutton, &QPushButton::clicked, this, &AddLayoutDialog::preview); -#else - layoutDialogUi->prevbutton->setVisible(false); -#endif + layoutDialogUi->prevbutton->setVisible(Tastenbrett::exists()); } void AddLayoutDialog::languageChanged(int langIdx) @@ -160,19 +160,9 @@ QDialog::accept(); } - -#ifdef NEW_GEOMETRY void AddLayoutDialog::preview() { int index = layoutDialogUi->variantComboBox->currentIndex(); QString variant = layoutDialogUi->variantComboBox->itemData(index).toString(); - KeyboardPainter* layoutPreview = new KeyboardPainter(); - - QString title = Flags::getLongText(LayoutUnit(selectedLayout, variant), rules); - layoutPreview->generateKeyboardLayout(selectedLayout, variant, model, title); - layoutPreview->setModal(true); - layoutPreview->exec(); - - delete layoutPreview; + Tastenbrett::launch(model, selectedLayout, variant, options.join(',')); } -#endif diff --git a/kcms/keyboard/kcm_keyboard_widget.h b/kcms/keyboard/kcm_keyboard_widget.h --- a/kcms/keyboard/kcm_keyboard_widget.h +++ b/kcms/keyboard/kcm_keyboard_widget.h @@ -68,9 +68,7 @@ void moveDown(); void configureLayoutsChanged(); void configureXkbOptionsChanged(); -#ifdef NEW_GEOMETRY void previewLayout(); -#endif private: Rules *rules; diff --git a/kcms/keyboard/kcm_keyboard_widget.cpp b/kcms/keyboard/kcm_keyboard_widget.cpp --- a/kcms/keyboard/kcm_keyboard_widget.cpp +++ b/kcms/keyboard/kcm_keyboard_widget.cpp @@ -34,15 +34,13 @@ #include #include "keyboard_config.h" -#ifdef NEW_GEOMETRY -#include "preview/keyboardpainter.h" -#endif #include "xkb_rules.h" #include "flags.h" #include "x11_helper.h" #include "kcm_view_models.h" #include "kcm_add_layout_dialog.h" #include "bindings.h" +#include "tastenbrett.h" #include "kcmmisc.h" #include "ui_kcm_add_layout_dialog.h" @@ -231,7 +229,12 @@ return; } - AddLayoutDialog dialog(rules, keyboardConfig->isFlagShown() ? flags : nullptr, keyboardConfig->keyboardModel, keyboardConfig->isLabelShown(), this); + AddLayoutDialog dialog(rules, + keyboardConfig->isFlagShown() ? flags : nullptr, + keyboardConfig->keyboardModel, + keyboardConfig->xkbOptions, + keyboardConfig->isLabelShown(), + this); dialog.setModal(true); if( dialog.exec() == QDialog::Accepted ) { keyboardConfig->layouts.append( dialog.getSelectedLayoutUnit() ); @@ -335,9 +338,7 @@ connect(uiWidget->moveUpBtn, &QAbstractButton::clicked, this, &KCMKeyboardWidget::moveUp); connect(uiWidget->moveDownBtn, &QAbstractButton::clicked, this, &KCMKeyboardWidget::moveDown); -#ifdef NEW_GEOMETRY connect(uiWidget->previewButton, &QAbstractButton::clicked, this, &KCMKeyboardWidget::previewLayout); -#endif connect(uiWidget->xkbGrpClearBtn, &QAbstractButton::clicked, this, &KCMKeyboardWidget::clearGroupShortcuts); connect(uiWidget->xkb3rdLevelClearBtn, &QAbstractButton::clicked, this, &KCMKeyboardWidget::clear3rdLevelShortcuts); @@ -362,35 +363,32 @@ connect(uiWidget->layoutLoopCountSpinBox, SIGNAL(valueChanged(int)), this, SLOT(uiChanged())); } -#ifdef NEW_GEOMETRY -void KCMKeyboardWidget::previewLayout(){ +void KCMKeyboardWidget::previewLayout() +{ QModelIndex index = uiWidget->layoutsTableView->currentIndex(); QModelIndex idcountry = index.sibling(index.row(),0) ; - QString country=uiWidget->layoutsTableView->model()->data(idcountry).toString(); - QModelIndex idvariant = index.sibling(index.row(),2) ; + const QString country=uiWidget->layoutsTableView->model()->data(idcountry).toString(); + const QModelIndex idvariant = index.sibling(index.row(),2) ; QString variant=uiWidget->layoutsTableView->model()->data(idvariant).toString(); - QString model = keyboardConfig->keyboardModel; + const QString model = keyboardConfig->keyboardModel; + const QStringList options = keyboardConfig->xkbOptions; - KeyboardPainter layoutPreview; const LayoutInfo* layoutInfo = rules->getLayoutInfo(country); if (!layoutInfo) { return; } - foreach(const VariantInfo* variantInfo, layoutInfo->variantInfos) { - if(variant==variantInfo->description){ - variant=variantInfo->name; + for (const VariantInfo *variantInfo : layoutInfo->variantInfos) { + if (variant == variantInfo->description) { + variant = variantInfo->name; break; } } - QString title = Flags::getLongText( LayoutUnit(country, variant), rules ); - layoutPreview.generateKeyboardLayout(country,variant, model, title); - layoutPreview.setModal(true); - layoutPreview.exec(); + const QString title = Flags::getLongText( LayoutUnit(country, variant), rules ); + Tastenbrett::launch(model, country, variant, options.join(','), title); } -#endif void KCMKeyboardWidget::configureLayoutsChanged() { @@ -420,11 +418,8 @@ uiWidget->removeLayoutBtn->setEnabled( ! selected.isEmpty() ); QPair rowsRange( getSelectedRowRange(selected) ); uiWidget->moveUpBtn->setEnabled( ! selected.isEmpty() && rowsRange.first > 0); -#ifdef NEW_GEOMETRY uiWidget->previewButton->setEnabled( uiWidget->layoutsTableView->selectionModel()->selectedRows().size() == 1 ); -#else - uiWidget->previewButton->setVisible(false); -#endif + uiWidget->previewButton->setVisible(Tastenbrett::exists()); uiWidget->moveDownBtn->setEnabled( ! selected.isEmpty() && rowsRange.second < keyboardConfig->layouts.size()-1 ); } diff --git a/kcms/keyboard/preview/TODO b/kcms/keyboard/preview/TODO deleted file mode 100644 --- a/kcms/keyboard/preview/TODO +++ /dev/null @@ -1,7 +0,0 @@ -Important: - -Good to have: -* replace symkey2ucs with something more reliable (e.g. XLookupString?) - -Cleanup: -* clean up the code (especially kbpreviewframe.cpp) diff --git a/kcms/keyboard/preview/geometry_components.h b/kcms/keyboard/preview/geometry_components.h deleted file mode 100644 --- a/kcms/keyboard/preview/geometry_components.h +++ /dev/null @@ -1,362 +0,0 @@ -/* - * Copyright (C) 2012 Shivam Makkar (amourphious1992@gmail.com) - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -#ifndef GEOMETRY_COMPONENTS_H -#define GEOMETRY_COMPONENTS_H - -#include -#include -#include -#include - - -Q_DECLARE_LOGGING_CATEGORY(KEYBOARD_PREVIEW) - - -class GShape -{ -private: - QString sname; - QPoint approx; - QList cordii; - int cordi_count; - -public: - GShape(); - void setCordinate(double a, double b); - void setApprox(double a, double b); - QPoint getCordii(int i) const; - void display(); - double size(int vertical) const; - - void setShapeName(const QString &n) - { - sname = n; - } - - QPoint getApprox() const - { - return approx; - } - - QString getShapeName() - { - return sname; - } - - int getCordi_count() const - { - return cordi_count; - } -}; - -class Key -{ -private: - QString name, shapeName; - double offset; - QPoint position; - -public: - Key(); - void setKeyPosition(double x, double y); - - void setOffset(double o) - { - offset = o; - } - - void setKeyName(const QString &n) - { - name = n; - } - - void setShapeName(const QString &n) - { - shapeName = n; - } - - QString getName() - { - return name; - } - - QString getShapeName() - { - return shapeName; - } - - double getOffset() - { - return offset; - } - - QPoint getPosition() - { - return position; - } - - void showKey(); -}; - -class Row -{ -private: - double top, left; - int keyCount, vertical; - QString shapeName; - -public : - QList keyList; - - Row(); - void addKey(); - - void setTop(double t) - { - top = t; - } - - void setLeft(double l) - { - left = l; - } - - void setVertical(int v) - { - vertical = v; - } - - void setShapeName(const QString &n) - { - shapeName = n; - } - - double getTop() - { - return top; - } - - double getLeft() - { - return left; - } - - int getKeyCount() - { - return keyCount; - } - - int getVertical() - { - return vertical; - } - - QString getShapeName() - { - return shapeName; - } - - void displayRow(); -}; - -class Section -{ -private: - QString name, shapeName; - double top, left, angle; - int rowCount, vertical; - -public: - QList rowList; - - Section(); - void addRow(); - - void setName(const QString &n) - { - name = n; - } - - void setShapeName(const QString &n) - { - shapeName = n; - } - - void setTop(double t) - { - top = t; - } - - void setLeft(double l) - { - left = l; - } - - void setAngle(double a) - { - angle = a; - } - - void setVertical(int v) - { - vertical = v; - } - - QString getName() - { - return name; - } - - QString getShapeName() - { - return shapeName; - } - - double getTop() - { - return top; - } - - double getLeft() - { - return left; - } - - double getAngle() - { - return angle; - } - - int getVertical() - { - return vertical; - } - - int getRowCount() - { - return rowCount; - } - - void displaySection(); -}; - -class Geometry -{ -private: - QString name, description, keyShape; - int shape_count, vertical; - int sectionCount; - -public: - QList shapes; - QList
sectionList; - double width, height, sectionTop, sectionLeft, rowTop, rowLeft, keyGap; - bool parsedGeometry; - Geometry(); - - void setWidth(double a) - { - width = a; - } - - void setParsing(bool state) - { - parsedGeometry = state; - } - - void setHeight(double a) - { - height = a; - } - - void setName(const QString &n) - { - name = n; - } - - void setDescription(const QString &d) - { - description = d; - } - - void setKeyShape(const QString &s) - { - keyShape = s; - } - - void setVertical(int v) - { - vertical = v; - } - - double getWidth() - { - return width; - } - - double getHeight() - { - return height; - } - - QString getName() - { - return name; - } - - QString getDescription() - { - return description; - } - - QString getKeyShape() - { - return keyShape; - } - - int getVertical() - { - return vertical; - } - - int getShapeCount() - { - return shape_count; - } - - int getSectionCount() - { - return sectionCount; - } - - bool getParsing() - { - return parsedGeometry; - } - - void setShapeName(const QString &n); - void setShapeCord(double a, double b); - void setShapeApprox(double a, double b); - void addShape(); - void display(); - void addSection(); - GShape findShape(const QString &name); -}; - -#endif //geometry_componets.h diff --git a/kcms/keyboard/preview/geometry_components.cpp b/kcms/keyboard/preview/geometry_components.cpp deleted file mode 100644 --- a/kcms/keyboard/preview/geometry_components.cpp +++ /dev/null @@ -1,245 +0,0 @@ -/* - * Copyright (C) 2012 Shivam Makkar (amourphious1992@gmail.com) - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - - -#include "geometry_components.h" - -#include -#include -#include - - -Q_LOGGING_CATEGORY(KEYBOARD_PREVIEW, "keyboard_preview") - - -GShape::GShape() -{ - cordi_count = 0; -} - -void GShape::setCordinate(double a, double b) -{ - cordii << QPoint(a, b); - cordi_count++; -} - -void GShape::setApprox(double a, double b) -{ - a -= approx.x(); - b -= approx.y(); - approx = QPoint(a, b); -} - -QPoint GShape :: getCordii(int i) const -{ - if (i < cordi_count) { - return cordii[i]; - } - - return QPoint(); -} - -void GShape::display() -{ - qCDebug(KEYBOARD_PREVIEW) << "shape: " << sname << "\n"; - qCDebug(KEYBOARD_PREVIEW) << "(" << approx.x() << "," << approx.y() << ");"; - - for (int i = 0; i < cordi_count; i++) { - qCDebug(KEYBOARD_PREVIEW) << cordii[i]; - } -} - -double GShape::size(int vertical) const -{ - if (!cordii.isEmpty()) { - if (vertical == 0) { - if (approx.x() == 0 && approx.y() == 0) { - int max = 0; - for (int i = 0; i < cordi_count; i++) { - if (max < cordii[i].x()) { - max = cordii[i].x(); - } - } - return max; - } else { - return approx.x(); - } - } else { - if (approx.x() == 0 && approx.y() == 0) { - int max = 0; - for (int i = 0; i < cordi_count; i++) { - if (max < cordii[i].y()) { - max = cordii[i].y(); - } - } - return max; - } - - return approx.y(); - } - } - - return 0; -} - - -Key::Key() -{ - offset = 0; -} - -void Key::setKeyPosition(double x, double y) -{ - position = QPoint(x, y); -} - -void Key::showKey() -{ - qCDebug(KEYBOARD_PREVIEW) << "\n\tKey: " << name << "\tshape: " << shapeName << "\toffset: " << offset; - qCDebug(KEYBOARD_PREVIEW) << "\tposition" << position; -} - - -Row::Row() -{ - top = 0; - left = 0; - keyCount = 0; - vertical = 0; - keyList << Key(); -} - -void Row::addKey() -{ - //qCDebug(KEYBOARD_PREVIEW) << "keyCount: " << keyCount; - keyCount++; - keyList << Key(); -} - -void Row::displayRow() -{ - qCDebug(KEYBOARD_PREVIEW) << "\nRow: (" << left << "," << top << ")\n"; - qCDebug(KEYBOARD_PREVIEW) << "vertical: " << vertical; - for (int i = 0; i < keyCount; i++) { - keyList[i].showKey(); - } -} - - -Section::Section() -{ - top = 0; - left = 0; - angle = 0; - rowCount = 0; - vertical = 0; - rowList << Row(); -} - -void Section::addRow() -{ - //qCDebug(KEYBOARD_PREVIEW) << "\nrowCount: " << rowCount; - rowCount++; - rowList << Row(); -} - -void Section::displaySection() -{ - //qCDebug(KEYBOARD_PREVIEW) << "\nSection: " << name << "\n\tposition: (" << left << "," << top << ");" << angle << "\n"; - //qCDebug(KEYBOARD_PREVIEW) << "vertical: " << vertical; - for (int i = 0; i < rowCount; i++) { - qCDebug(KEYBOARD_PREVIEW) << "\n\t"; - rowList[i].displayRow(); - } -} - - -Geometry::Geometry() -{ - sectionTop = 0; - sectionLeft = 0; - rowTop = 0; - rowLeft = 0; - keyGap = 0; - shape_count = 0; - width = 0; - height = 0; - sectionCount = 0; - vertical = 0; - sectionList << Section(); - shapes << GShape(); - keyShape = QStringLiteral("NORM"); - parsedGeometry = true; -} - -void Geometry::setShapeName(const QString &n) -{ - shapes[shape_count].setShapeName(n); -} - -void Geometry::setShapeCord(double a, double b) -{ - shapes[shape_count].setCordinate(a, b); -} - -void Geometry::setShapeApprox(double a, double b) -{ - shapes[shape_count].setApprox(a, b); -} - -void Geometry::addShape() -{ - shape_count++; - shapes << GShape(); -} - -void Geometry::display() -{ - qCDebug(KEYBOARD_PREVIEW) << name << "\n" << description << "\nwidth:" << width - << "\nheight:" << height << "\n" << "sectionTop:" << sectionTop; - qCDebug(KEYBOARD_PREVIEW) << "\nsectionLeft:" << sectionLeft << "\nrowTop:" << rowTop << "\nrowLeft:" - << rowLeft << "\nkeyGap: " << keyGap << "\nkeyShape:" << keyShape << "\n"; - qCDebug(KEYBOARD_PREVIEW) << "vertical:" << vertical; - - for (int i = 0; i < shape_count; i++) { - shapes[i].display(); - } - - for (int j = 0; j < sectionCount; j++) { - sectionList[j].displaySection(); - } -} - -void Geometry::addSection() -{ - //qCDebug(KEYBOARD_PREVIEW) << "\nsectionCount: " << sectionCount; - sectionCount++; - sectionList << Section(); -} - -GShape Geometry::findShape(const QString &name) -{ - GShape l; - - for (int i = 0; i < shape_count; i++) { - if (shapes[i].getShapeName() == name) { - return shapes[i]; - } - } - return l; -} diff --git a/kcms/keyboard/preview/geometry_parser.h b/kcms/keyboard/preview/geometry_parser.h deleted file mode 100644 --- a/kcms/keyboard/preview/geometry_parser.h +++ /dev/null @@ -1,161 +0,0 @@ -/* - * Copyright (C) 2012 Shivam Makkar (amourphious1992@gmail.com) - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - - -#ifndef GEOMETRY_PARSER_H -#define GEOMETRY_PARSER_H - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - - -#include -#include -#include - -#include "geometry_components.h" - -namespace qi = boost::spirit::qi; -namespace ascii = boost::spirit::ascii; -namespace phx = boost::phoenix; -namespace iso = boost::spirit::iso8859_1; - - -namespace grammar -{ - -struct keywords : qi::symbols { - keywords(); -}; - -template -struct GeometryParser : qi::grammar { - - //comments - qi::rulecomments, ignore; - qi::rulelocalDimension, priority; - - //general non-terminals - qi::rulename; - qi::ruledescription; - qi::ruleinput; - - //non-terminals for shape - qi::ruleshape; - qi::ruleshapeDef; - qi::ruleshapeC; - qi::ruleset; - qi::rulesetap; - qi::ruleseta; - qi::rulecornerRadius; - qi::rulecordinatea; - qi::rulecordinates; - - //non-terminals for key - qi::rulekeygap; - qi::rulekeyName; - qi::rulekeyShape; - qi::rulekeyColor; - qi::rulekeyDesc; - qi::rulekeys; - - qi::rulerow; - - qi::rulesection; - - //non-terminals related to local data - qi::rulelocalShape; - qi::rulelocalColor; - - //Geometry non-terminals - qi::rulegeomShape; - qi::rulegeomTop, geomVertical; - qi::rulegeomLeft; - qi::rulegeomRowTop; - qi::rulegeomRowLeft; - qi::rulegeomGap; - qi::rulegeomAtt; - qi::ruleangle; - qi::ruletop; - qi::ruleleft; - qi::rulewidth; - qi::ruleheight; - - qi::rulestart; - Geometry geom; - keywords keyword; - double shapeLenX, shapeLenY, approxLenX, approxLenY, keyCordiX, keyCordiY, KeyOffset; - GeometryParser(); - - //functions for shape - void getShapeName(std::string n); - void setCord(); - void setApprox(); - - //functions for section - void sectionName(std::string n); - void setSectionShape(std::string n); - void setSectionTop(double a); - void setSectionLeft(double a); - void setSectionAngle(double a); - void sectioninit(); - - //functions for row - void setRowShape(std::string n); - void setRowTop(double a); - void setRowLeft(double a); - void rowinit(); - void addRow(); - - //functions for key - void setKeyName(std::string n); - void setKeyShape(std::string n); - void setKeyNameandShape(std::string n); - void setKeyOffset(); - void setKeyCordi(); - - //functions for geometry - void setGeomShape(std::string n); - void getName(std::string n); - void getDescription(std::string n); - - //functions for alignment - void setVerticalRow(); - void setVerticalSection(); - void setVerticalGeometry(); -}; - - - -Geometry parseGeometry(const QString &model); -QString getGeometry(QString geometryFile, QString geometryName); -QString includeGeometry(QString geometry); -QString getGeometryStrContent(QString geometryStr); -QString findGeometryBaseDir(); -} - -#endif //geometry_parser diff --git a/kcms/keyboard/preview/geometry_parser.cpp b/kcms/keyboard/preview/geometry_parser.cpp deleted file mode 100644 --- a/kcms/keyboard/preview/geometry_parser.cpp +++ /dev/null @@ -1,593 +0,0 @@ -/* -* Copyright (C) 2013 Shivam Makkar (amourphious1992@gmail.com) -* -* This program is free software; you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation; either version 2 of the License, or -* (at your option) any later version. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. -* -* You should have received a copy of the GNU General Public License -* along with this program; if not, write to the Free Software -* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -#include "geometry_parser.h" -#include "geometry_components.h" -#include "xkb_rules.h" - -#include -#include -#include -#include -#include - - -#include -#include - -namespace grammar -{ -keywords::keywords() -{ - add - ("shape", 1) - ("height", 2) - ("width", 3) - ("description", 4) - ("keys", 5) - ("row", 6) - ("section", 7) - ("key", 8) - ("//", 9) - ("/*", 10) - ; -} - - -template -GeometryParser::GeometryParser(): GeometryParser::base_type(start) -{ - - using qi::lexeme; - using qi::char_; - using qi::lit; - using qi::_1; - using qi::_val; - using qi::int_; - using qi::double_; - using qi::eol; - - - name = '"' >> +(char_ - '"') >> '"'; - - ignore = (lit("outline") || lit("overlay") || lit("text")) >> *(char_ - lit("};")) >> lit("};") - || lit("solid") >> *(char_ - lit("};")) >> lit("};") - || lit("indicator") >> *(char_ - ';' - '{') >> ';' || '{' >> *(char_ - lit("};")) >> lit("};") - || lit("indicator") >> '.' >> lit("shape") >> '=' >> name >> ';'; - - comments = lexeme[ lit("//") >> *(char_ - eol || keyword - eol) >> eol || lit("/*") >> *(char_ - lit("*/") || keyword - lit("*/")) >> lit("*/") ]; - - cordinates = ('[' - >> double_[phx::ref(shapeLenX) = _1] - >> ',' - >> double_[phx::ref(shapeLenY) = _1] - >> ']') - || '[' >> double_ >> "," >> double_ >> ']' - ; - - cordinatea = '[' >> double_[phx::ref(approxLenX) = _1] >> "," >> double_[phx::ref(approxLenY) = _1] >> ']'; - - set = '{' >> cordinates >> *(',' >> cordinates) >> '}'; - - setap = '{' >> cordinatea >> *(',' >> cordinatea) >> '}'; - - seta = '{' - >> cordinates[phx::bind(&GeometryParser::setCord, this)] - >> *(',' >> cordinates[phx::bind(&GeometryParser::setCord, this)]) - >> '}' - ; - - description = lit("description") >> '=' >> name[phx::bind(&GeometryParser::getDescription, this, _1)] >> ';'; - - cornerRadius = (lit("cornerRadius") || lit("corner")) >> '=' >> double_; - - shapeDef = lit("shape") - >> name[phx::bind(&GeometryParser::getShapeName, this, _1)] - >> '{' - >> *(lit("approx") >> '=' >> setap[phx::bind(&GeometryParser::setApprox, this)] >> ',' || cornerRadius >> ',' || comments) - >> seta - >> *((',' >> (set || lit("approx") >> '=' >> setap[phx::bind(&GeometryParser::setApprox, this)] || cornerRadius) || comments)) - >> lit("};") - ; - - keyName = '<' >> +(char_ - '>') >> '>'; - - keyShape = *(lit("key.")) >> lit("shape") >> '=' >> name[phx::bind(&GeometryParser::setKeyShape, this, _1)] - || name[phx::bind(&GeometryParser::setKeyShape, this, _1)]; - - keyColor = lit("color") >> '=' >> name; - - keygap = lit("gap") >> '=' >> double_[phx::ref(KeyOffset) = _1] || double_[phx::ref(KeyOffset) = _1]; - - keyDesc = keyName[phx::bind(&GeometryParser::setKeyNameandShape, this, _1)] - || '{' >> (keyName[phx::bind(&GeometryParser::setKeyNameandShape, this, _1)] || keyShape - || keygap[phx::bind(&GeometryParser::setKeyOffset, this)] - || keyColor) - >> *((',' - >> (keyName - || keyShape - || keygap[phx::bind(&GeometryParser::setKeyOffset, this)] - || keyColor)) - || comments) - >> '}'; - - keys = lit("keys") - >> '{' - >> keyDesc[phx::bind(&GeometryParser::setKeyCordi, this)] - >> *((*lit(',') >> keyDesc[phx::bind(&GeometryParser::setKeyCordi, this)] >> *lit(',')) || comments) - >> lit("};"); - - geomShape = ((lit("key.shape") >> '=' >> name[phx::bind(&GeometryParser::setGeomShape, this, _1)]) || (lit("key.color") >> '=' >> name)) >> ';'; - geomLeft = lit("section.left") >> '=' >> double_[phx::ref(geom.sectionLeft) = _1] >> ';'; - geomTop = lit("section.top") >> '=' >> double_[phx::ref(geom.sectionTop) = _1] >> ';'; - geomRowTop = lit("row.top") >> '=' >> double_[phx::ref(geom.rowTop) = _1] >> ';'; - geomRowLeft = lit("row.left") >> '=' >> double_[phx::ref(geom.rowLeft) = _1] >> ';'; - geomGap = lit("key.gap") >> '=' >> double_[phx::ref(geom.keyGap) = _1] >> ';'; - geomVertical = *lit("row.") >> lit("vertical") >> '=' >> (lit("True") || lit("true")) >> ';'; - geomAtt = geomLeft || geomTop || geomRowTop || geomRowLeft || geomGap; - - top = lit("top") >> '=' >> double_ >> ';'; - left = lit("left") >> '=' >> double_ >> ';'; - - row = lit("row")[phx::bind(&GeometryParser::rowinit, this)] - >> '{' - >> *(top[phx::bind(&GeometryParser::setRowTop, this, _1)] - || left[phx::bind(&GeometryParser::setRowLeft, this, _1)] - || localShape[phx::bind(&GeometryParser::setRowShape, this, _1)] - || localColor - || comments - || geomVertical[phx::bind(&GeometryParser::setVerticalRow, this)] - || keys - ) - >> lit("};") || ignore || geomVertical[phx::bind(&GeometryParser::setVerticalSection, this)]; - - angle = lit("angle") >> '=' >> double_ >> ';'; - - localShape = lit("key.shape") >> '=' >> name[_val = _1] >> ';'; - localColor = lit("key.color") >> '=' >> name >> ';'; - localDimension = (lit("height") || lit("width")) >> '=' >> double_ >> ';'; - priority = lit("priority") >> '=' >> double_ >> ';'; - - section = lit("section")[phx::bind(&GeometryParser::sectioninit, this)] - >> name[phx::bind(&GeometryParser::sectionName, this, _1)] - >> '{' - >> *(top[phx::bind(&GeometryParser::setSectionTop, this, _1)] - || left[phx::bind(&GeometryParser::setSectionLeft, this, _1)] - || angle[phx::bind(&GeometryParser::setSectionAngle, this, _1)] - || row[phx::bind(&GeometryParser::addRow, this)] - || localShape[phx::bind(&GeometryParser::setSectionShape, this, _1)] - || geomAtt - || localColor - || localDimension - || priority - || comments) - >> lit("};") || geomVertical[phx::bind(&GeometryParser::setVerticalGeometry, this)]; - - shapeC = lit("shape") >> '.' >> cornerRadius >> ';'; - - shape = shapeDef || shapeC; - - - input = '{' - >> +(width - || height - || comments - || ignore - || description - || (char_ - keyword - '}' - || shape[phx::bind(&Geometry::addShape, &geom)] - || section[phx::bind(&Geometry::addSection, &geom)] - || geomAtt - || geomShape - )) - >> '}'; - - width = lit("width") >> '=' >> double_[phx::bind(&Geometry::setWidth, &geom, _1)] >> ";"; - height = lit("height") >> '=' >> double_[phx::bind(&Geometry::setHeight, &geom, _1)] >> ";"; - - start %= *(lit("default")) - >> lit("xkb_geometry") - >> name[phx::bind(&GeometryParser::getName, this, _1)] - >> input - >> ';' >> *(comments || char_ - lit("xkb_geometry")); -} - -template -void GeometryParser::setCord() -{ - geom.setShapeCord(shapeLenX, shapeLenY); -} - - -template -void GeometryParser::setSectionShape(std::string n) -{ - geom.sectionList[geom.getSectionCount()].setShapeName(QString::fromUtf8(n.data(), n.size())); -} - - -template -void GeometryParser::getName(std::string n) -{ - geom.setName(QString::fromUtf8(n.data(), n.size())); -} - - -template -void GeometryParser::getDescription(std::string n) -{ - geom.setDescription(QString::fromUtf8(n.data(), n.size())); -} - - -template -void GeometryParser::getShapeName(std::string n) -{ - geom.setShapeName(QString::fromUtf8(n.data(), n.size())); -} - - -template -void GeometryParser::setGeomShape(std::string n) -{ - geom.setKeyShape(QString::fromUtf8(n.data(), n.size())); -} - - -template -void GeometryParser::setRowShape(std::string n) -{ - int secn = geom.getSectionCount(); - int rown = geom.sectionList[secn].getRowCount(); - geom.sectionList[secn].rowList[rown].setShapeName(QString::fromUtf8(n.data(), n.size())); -} - - -template -void GeometryParser::setApprox() -{ - geom.setShapeApprox(approxLenX, approxLenY); -} - - -template -void GeometryParser::addRow() -{ - geom.sectionList[geom.getSectionCount()].addRow(); -} - - -template -void GeometryParser::sectionName(std::string n) -{ - geom.sectionList[geom.getSectionCount()].setName(QString::fromUtf8(n.data(), n.size())); -} - - -template -void GeometryParser::rowinit() -{ - int secn = geom.getSectionCount(); - int rown = geom.sectionList[secn].getRowCount(); - double tempTop = geom.sectionList[secn].getTop(); - QString tempShape = geom.sectionList[secn].getShapeName(); - geom.sectionList[secn].rowList[rown].setTop(tempTop); - geom.sectionList[secn].rowList[rown].setLeft(geom.sectionList[secn].getLeft()); - geom.sectionList[secn].rowList[rown].setShapeName(tempShape); - keyCordiX = geom.sectionList[secn].rowList[rown].getLeft(); - keyCordiY = geom.sectionList[secn].rowList[rown].getTop(); - tempTop = geom.sectionList[secn].getVertical(); - geom.sectionList[secn].rowList[rown].setVertical(tempTop); -} - - -template -void GeometryParser::sectioninit() -{ - int secn = geom.getSectionCount(); - geom.sectionList[secn].setTop(geom.sectionTop); - geom.sectionList[secn].setLeft(geom.sectionLeft); - keyCordiX = geom.sectionList[secn].getLeft(); - keyCordiY = geom.sectionList[secn].getTop(); - geom.sectionList[secn].setShapeName(geom.getKeyShape()); - geom.sectionList[secn].setVertical(geom.getVertical()); -} - - -template -void GeometryParser::setRowTop(double a) -{ - int secn = geom.getSectionCount(); - int rown = geom.sectionList[secn].getRowCount(); - double tempTop = geom.sectionList[secn].getTop(); - geom.sectionList[secn].rowList[rown].setTop(a + tempTop); - keyCordiY = geom.sectionList[secn].rowList[rown].getTop(); -} - - -template -void GeometryParser::setRowLeft(double a) -{ - int secn = geom.getSectionCount(); - int rown = geom.sectionList[secn].getRowCount(); - double tempLeft = geom.sectionList[secn].getLeft(); - geom.sectionList[secn].rowList[rown].setLeft(a + tempLeft); - keyCordiX = geom.sectionList[secn].rowList[rown].getLeft(); -} - - -template -void GeometryParser::setSectionTop(double a) -{ - //qCDebug(KEYBOARD_PREVIEW) << "\nsectionCount" << geom.sectionCount; - int secn = geom.getSectionCount(); - geom.sectionList[secn].setTop(a + geom.sectionTop); - keyCordiY = geom.sectionList[secn].getTop(); -} - - -template -void GeometryParser::setSectionLeft(double a) -{ - //qCDebug(KEYBOARD_PREVIEW) << "\nsectionCount" << geom.sectionCount; - int secn = geom.getSectionCount(); - geom.sectionList[secn].setLeft(a + geom.sectionLeft); - keyCordiX = geom.sectionList[secn].getLeft(); - -} - - -template -void GeometryParser::setSectionAngle(double a) -{ - //qCDebug(KEYBOARD_PREVIEW) << "\nsectionCount" << geom.sectionCount; - int secn = geom.getSectionCount(); - geom.sectionList[secn].setAngle(a); -} - - -template -void GeometryParser::setVerticalRow() -{ - int secn = geom.getSectionCount(); - int rown = geom.sectionList[secn].getRowCount(); - geom.sectionList[secn].rowList[rown].setVertical(1); -} - - -template -void GeometryParser::setVerticalSection() -{ - int secn = geom.getSectionCount(); - geom.sectionList[secn].setVertical(1); -} - - -template -void GeometryParser::setVerticalGeometry() -{ - geom.setVertical(1); -} - - -template -void GeometryParser::setKeyName(std::string n) -{ - int secn = geom.getSectionCount(); - int rown = geom.sectionList[secn].getRowCount(); - int keyn = geom.sectionList[secn].rowList[rown].getKeyCount(); - //qCDebug(KEYBOARD_PREVIEW) << "\nsC: " << secn << "\trC: " << rown << "\tkn: " << keyn; - geom.sectionList[secn].rowList[rown].keyList[keyn].setKeyName(QString::fromUtf8(n.data(), n.size())); -} - - -template -void GeometryParser::setKeyShape(std::string n) -{ - int secn = geom.getSectionCount(); - int rown = geom.sectionList[secn].getRowCount(); - int keyn = geom.sectionList[secn].rowList[rown].getKeyCount(); - //qCDebug(KEYBOARD_PREVIEW) << "\nsC: " << secn << "\trC: " << rown << "\tkn: " << keyn; - geom.sectionList[secn].rowList[rown].keyList[keyn].setShapeName(QString::fromUtf8(n.data(), n.size())); -} - - -template -void GeometryParser::setKeyNameandShape(std::string n) -{ - int secn = geom.getSectionCount(); - int rown = geom.sectionList[secn].getRowCount(); - setKeyName(n); - setKeyShape(geom.sectionList[secn].rowList[rown].getShapeName().toUtf8().constData()); -} - - -template -void GeometryParser::setKeyOffset() -{ - //qCDebug(KEYBOARD_PREVIEW) << "\nhere\n"; - int secn = geom.getSectionCount(); - int rown = geom.sectionList[secn].getRowCount(); - int keyn = geom.sectionList[secn].rowList[rown].getKeyCount(); - //qCDebug(KEYBOARD_PREVIEW) << "\nsC: " << secn << "\trC: " << rown << "\tkn: " << keyn; - geom.sectionList[secn].rowList[rown].keyList[keyn].setOffset(KeyOffset); -} - - -template -void GeometryParser::setKeyCordi() -{ - int secn = geom.getSectionCount(); - int rown = geom.sectionList[secn].getRowCount(); - int keyn = geom.sectionList[secn].rowList[rown].getKeyCount(); - int vertical = geom.sectionList[secn].rowList[rown].getVertical(); - - Key key = geom.sectionList[secn].rowList[rown].keyList[keyn]; - - if (vertical == 0) { - keyCordiX += key.getOffset(); - } else { - keyCordiY += key.getOffset(); - } - - geom.sectionList[secn].rowList[rown].keyList[keyn].setKeyPosition(keyCordiX, keyCordiY); - - QString shapeStr = key.getShapeName(); - if (shapeStr.isEmpty()) { - shapeStr = geom.getKeyShape(); - } - - GShape shapeObj = geom.findShape(shapeStr); - int a = shapeObj.size(vertical); - - if (vertical == 0) { - keyCordiX += a + geom.keyGap; - } else { - keyCordiY += a + geom.keyGap; - } - - geom.sectionList[secn].rowList[rown].addKey(); -} - - -Geometry parseGeometry(const QString &model) -{ - using boost::spirit::iso8859_1::space; - typedef std::string::const_iterator iterator_type; - typedef grammar::GeometryParser GeometryParser; - GeometryParser geometryParser; - - Rules::GeometryId geoId = Rules::getGeometryId(model); - QString geometryFile = geoId.fileName; - QString geometryName = geoId.geoName; - - qCDebug(KEYBOARD_PREVIEW) << "looking for model" << model << "geometryName" << geometryName << "in" << geometryFile; - - QString input = getGeometry(geometryFile, geometryName); - if (! input.isEmpty()) { - geometryParser.geom = Geometry(); - input = includeGeometry(input); - std::string parserInput = input.toUtf8().constData(); - - std::string::const_iterator iter = parserInput.begin(); - std::string::const_iterator end = parserInput.end(); - - bool success = phrase_parse(iter, end, geometryParser, space); - - if (success && iter == end) { -// qCDebug(KEYBOARD_PREVIEW) << "Geometry parsing succeeded for" << input.left(20); - geometryParser.geom.setParsing(true); - return geometryParser.geom; - } else { - qCritical() << "Geometry parsing failed for\n\t" << input.left(30); - geometryParser.geom.setParsing(false); - } - } - - if (geometryParser.geom.getParsing()) { - return geometryParser.geom; - } - - qCritical() << "Failed to get geometry" << geometryParser.geom.getName() << "falling back to pc104"; - return parseGeometry(QStringLiteral("pc104")); -} - -QString includeGeometry(QString geometry) -{ - QStringList lines = geometry.split(QLatin1Char('\n')); - int includeLine = -1; - QString includeLineStr; - QString startLine = lines[0]; - for (int i = 0; i < lines.size(); i++) { - includeLineStr = lines[i]; - lines[i].remove(QStringLiteral(" ")); - lines[i].remove(QStringLiteral("\r")); - if (lines[i].startsWith(QLatin1String("include"))) { - includeLine = i; - break; - } - } - if (includeLine == -1) { - return geometry; - } - geometry.remove(includeLineStr); - lines[includeLine].remove(QStringLiteral("include")); - lines[includeLine].remove(QStringLiteral("\"")); - lines[includeLine].remove(QStringLiteral(")")); - if (lines[includeLine].contains(QLatin1Char('('))) { - QString includeFile = lines[includeLine].split(QLatin1Char('('))[0]; - QString includeGeom = lines[includeLine].split(QLatin1Char('('))[1]; - qCDebug(KEYBOARD_PREVIEW) << "looking to include " << "geometryName" << includeGeom << "in" << includeFile; - QString includeStr = getGeometry(includeFile, includeGeom); - includeStr = getGeometryStrContent(includeStr); - geometry.remove(startLine); - geometry.prepend(includeStr); - geometry.prepend(startLine); - includeGeometry(geometry); - - } - return geometry; -} - -QString getGeometryStrContent(QString geometryStr) -{ - int k = geometryStr.indexOf(QLatin1String("{")); - int k2 = geometryStr.lastIndexOf(QLatin1String("};")); - geometryStr = geometryStr.mid(k + 1, k2 - k - 2); - return geometryStr; -} - -QString getGeometry(QString geometryFile, QString geometryName) -{ - - QString xkbParentDir = findGeometryBaseDir(); - geometryFile.prepend(xkbParentDir); - QFile gfile(geometryFile); - - if (!gfile.open(QIODevice::ReadOnly | QIODevice::Text)) { - qCritical() << "Unable to open the file" << geometryFile; - return QString(); - } - - QString gcontent = gfile.readAll(); - gfile.close(); - - QStringList gcontentList = gcontent.split(QStringLiteral("xkb_geometry ")); - - int current = 0; - for (int i = 1; i < gcontentList.size(); i++) { - if (gcontentList[i].startsWith("\"" + geometryName + "\"")) { - current = i; - break; - } - } - if (current != 0) { - return gcontentList[current].prepend("xkb_geometry "); - } else { - return QString(); - } -} - - -QString findGeometryBaseDir() -{ - QString xkbDir = Rules::findXkbDir(); - return QStringLiteral("%1/geometry/").arg(xkbDir); -} - -} diff --git a/kcms/keyboard/preview/kbpreviewframe.h b/kcms/keyboard/preview/kbpreviewframe.h deleted file mode 100644 --- a/kcms/keyboard/preview/kbpreviewframe.h +++ /dev/null @@ -1,95 +0,0 @@ -/* - * Copyright (C) 2012 Shivam Makkar (amourphious1992@gmail.com) - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -#ifndef KBPREVIEWFRAME_H -#define KBPREVIEWFRAME_H - -#include "keyboardlayout.h" - -#include "keysymhelper.h" -#include "keyaliases.h" - -#include -#include -#include -#include -#include - - -Q_DECLARE_LOGGING_CATEGORY(KEYBOARD_PREVIEW) - - -class Geometry; -class GShape; - - -class KbPreviewFrame : public QFrame -{ - Q_OBJECT - -private: - static const int width = 1100, height = 490; - - KeySymHelper symbol; - Aliases alias; - QStringList tooltip; - QList tipPoint; - int l_id; - Geometry &geometry; - float scaleFactor; - KbLayout keyboardLayout; - - void drawKeySymbols(QPainter &painter, QPoint temp[], const GShape &s, const QString &name); - void drawShape(QPainter &painter, const GShape &s, int x, int y, int i, const QString &name); - - int itemAt(const QPoint &pos); - - -protected: - bool event(QEvent *event) override; - -public: - explicit KbPreviewFrame(QWidget *parent = nullptr); - ~KbPreviewFrame() override; - void paintEvent(QPaintEvent *event) override; - void generateKeyboardLayout(const QString &layout, const QString &layoutVariant, const QString &model); - int getWidth() const; - int getHeight() const; - - int getLevel() - { - return keyboardLayout.getLevel(); - } - - void setL_id(int lId) - { - l_id = lId; - repaint(); - } - - QString getLayoutName() const - { - return keyboardLayout.getLayoutName(); - } - - float getScaleFactor() - { - return scaleFactor; - } -}; - -#endif // KBPREVIEWFRAME_H diff --git a/kcms/keyboard/preview/kbpreviewframe.cpp b/kcms/keyboard/preview/kbpreviewframe.cpp deleted file mode 100644 --- a/kcms/keyboard/preview/kbpreviewframe.cpp +++ /dev/null @@ -1,375 +0,0 @@ -/* - * Copyright (C) 2012 Shivam Makkar (amourphious1992@gmail.com) - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - - -#include "kbpreviewframe.h" - -#include "geometry_parser.h" -#include "geometry_components.h" -#include "keyboardlayout.h" -#include "symbol_parser.h" - -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#include - - -static const QColor keyBorderColor("#d4d4d4"); -static const QColor lev12color(Qt::black); -static const QColor lev34color("#0033FF"); -static const QColor unknownSymbolColor("#FF3300"); -static const int xOffset[] = {10, 10, -15, -15 }; -static const int yOffset[] = {5, -20, 5, -20 }; -static const QColor color[] = { lev12color, lev12color, lev34color, lev34color }; -static const int keyLevel[3][4] = { { 1, 0, 3, 2}, { 1, 0, 5, 4}, { 1, 0, 7, 6} }; -static const QRegExp fkKey(QStringLiteral("^FK\\d+$")); - - -KbPreviewFrame::KbPreviewFrame(QWidget *parent) : - QFrame(parent), - geometry(*new Geometry()) -{ - setFrameStyle(QFrame::Box); - setFrameShadow(QFrame::Sunken); - setMouseTracking(true); - scaleFactor = 1; - l_id = 0; -} - -KbPreviewFrame::~KbPreviewFrame() -{ - delete &geometry; -} - - -int KbPreviewFrame::getWidth() const -{ - return geometry.width; -} -int KbPreviewFrame::getHeight() const -{ - return geometry.height; -} - - -//writes text on the keys call only by paintevent -void KbPreviewFrame::drawKeySymbols(QPainter &painter, QPoint temp[], const GShape &s, const QString &name) -{ - int keyindex = keyboardLayout.findKey(name); - int szx = scaleFactor * s.size(0) / 2 < 20 ? scaleFactor * s.size(0) / 3 : 20; - int szy = scaleFactor * s.size(1) / 2 < 20 ? scaleFactor * s.size(1) / 3 : 20; - QFont kbfont; - if (szx > szy) { - kbfont.setPointSize(szy / 2 < 9 ? szy : 9); - } else { - kbfont.setPointSize(szx / 2 < 9 ? szx / 2 : 9); - } - - painter.setFont(kbfont); - - int cordinate[] = {0, 3, 1, 2}; - float tooltipX = 0, toolTipY = 0; - QString tip; - if (keyindex != -1) { - KbKey key = keyboardLayout.keyList.at(keyindex); - - for (int level = 0; level < (key.getSymbolCount() < 4 ? key.getSymbolCount() : 4); level++) { - - if (keyLevel[l_id][level] < key.getSymbolCount()) { - - QString txt = symbol.getKeySymbol(key.getSymbol(keyLevel[l_id][level])); - - QColor txtColor = txt[0] == -1 ? unknownSymbolColor : color[level]; - - painter.setPen(txtColor); - - painter.drawText(temp[cordinate[level]].x() + xOffset[level]*scaleFactor / 2.5, temp[cordinate[level]].y() + yOffset[level]*scaleFactor / 2.5, szx, szy, Qt::AlignTop, txt); - - QString currentSymbol = key.getSymbol(keyLevel[l_id][level]); - currentSymbol = currentSymbol.size() < 3 ? currentSymbol.append("\t") : currentSymbol; - - if (level == 0) { - tip.append(currentSymbol); - } else { - tip.append("\n" + currentSymbol); - } - } - } - - for (int i = 0 ; i < 4; i++) { - tooltipX += temp[i].x(); - toolTipY += temp[i].y(); - } - - tooltipX = tooltipX / 4; - toolTipY = toolTipY / 4; - QPoint tooltipPoint = QPoint(tooltipX, toolTipY); - - tooltip.append(tip); - tipPoint.append(tooltipPoint); - } else { - painter.setPen(Qt::black); - - if (name.contains(fkKey)) { - QString tempName = name; - tempName.remove(QStringLiteral("K")); - painter.drawText(temp[0].x() + s.size(0) - 10, temp[0].y() + 3 * scaleFactor * s.size(1) / 5, tempName); - } else { - painter.setFont(kbfont); - painter.drawText(temp[0].x() + s.size(0) - 10, temp[0].y() + 3 * scaleFactor * s.size(1) / 5, name); - } - tip = name; - - for (int i = 0 ; i < 4; i++) { - tooltipX += temp[i].x(); - toolTipY += temp[i].y(); - } - - tooltipX = tooltipX / 4; - toolTipY = toolTipY / 4; - QPoint tooltipPoint = QPoint(tooltipX, toolTipY); - - tooltip.append(tip); - tipPoint.append(tooltipPoint); - } -} - - -//draws key shape on QFrame called only by paint event -void KbPreviewFrame::drawShape(QPainter &painter, const GShape &s, int x, int y, int i, const QString &name) -{ - painter.setPen(Qt::black); - int cordi_count = s.getCordi_count(); - - if (geometry.sectionList[i].getAngle() == 0) { - if (cordi_count == 1) { - int width = s.getCordii(0).x(); - int height = s.getCordii(0).y(); - - painter.drawRoundedRect(scaleFactor * x + 2, scaleFactor * y, scaleFactor * width, scaleFactor * height, 4, 4); - - QPoint temp[4]; - - temp[0] = QPoint(scaleFactor * x, scaleFactor * y); - temp[1] = QPoint(scaleFactor * (s.getCordii(0).x() + x), scaleFactor * y); - temp[2] = QPoint(scaleFactor * (s.getCordii(0).x() + x), scaleFactor * (s.getCordii(0).y() + y)); - temp[3] = QPoint(scaleFactor * (x), scaleFactor * (s.getCordii(0).y() + y)); - - drawKeySymbols(painter, temp, s, name); - } else { - QVarLengthArray temp(cordi_count); - for (int i = 0; i < cordi_count; i++) { - temp[i].setX(scaleFactor * (s.getCordii(i).x() + x + 1)); - temp[i].setY(scaleFactor * (s.getCordii(i).y() + y + 1)); - } - - painter.drawPolygon(temp.data(), cordi_count); - drawKeySymbols(painter, temp.data(), s, name); // no length passed here, is this safe? - } - } else { - QVarLengthArray temp(cordi_count == 1 ? 4 : cordi_count); - int size; - - if (cordi_count == 1) { - temp[0] = QPoint(x, y); - temp[1] = QPoint(s.getCordii(0).x() + x, y); - temp[2] = QPoint(s.getCordii(0).x() + x, s.getCordii(0).y() + y); - temp[3] = QPoint(x, s.getCordii(0).y() + y); - size = 4; - } else { - size = cordi_count; - - for (int i = 0; i < cordi_count; i++) { - temp[i].setX((s.getCordii(i).x() + x + 1)); - temp[i].setY((s.getCordii(i).y() + y + 1)); - } - } - - double refX, refY; - - refX = geometry.sectionList[i].getLeft(); - refY = geometry.sectionList[i].getTop(); - - //qCDebug(KEYBOARD_PREVIEW) <<"\ntransform"; - for (int j = 0; j < size; j++) { - double x = temp[j].x() - refX; - double y = temp[j].y() - refY; - - //qCDebug(KEYBOARD_PREVIEW) <<"(" <"; - - float theta = (3.1459 * geometry.sectionList[i].getAngle()) / 180; - double x_ = x * cos(theta) - y * sin(theta); - - //qCDebug(KEYBOARD_PREVIEW) <<"x_= " <type() == QEvent::ToolTip) { - QHelpEvent *helpEvent = static_cast(event); - int index = itemAt(helpEvent->pos()); - - if (index != -1) { - QToolTip::showText(helpEvent->globalPos(), tooltip.at(index)); - } else { - QToolTip::hideText(); - event->ignore(); - } - - return true; - } - return QWidget::event(event); -} - - -void KbPreviewFrame::paintEvent(QPaintEvent *) -{ - if (geometry.getParsing() && keyboardLayout.getParsedSymbol()) { - QPainter painter(this); - - QFont kbfont; - kbfont.setPointSize(9); - - painter.setFont(kbfont); - painter.setBrush(QBrush("#C3C8CB")); - painter.setRenderHint(QPainter::Antialiasing); - - const int strtx = 0, strty = 0, endx = geometry.getWidth(), endy = geometry.getHeight(); - - - painter.setPen("#EDEEF2"); - - painter.drawRect(strtx, strty, scaleFactor * endx + 60, scaleFactor * endy + 60); - - painter.setPen(Qt::black); - painter.setBrush(QBrush("#EDEEF2")); - - for (int i = 0; i < geometry.getSectionCount(); i++) { - - painter.setPen(Qt::black); - - for (int j = 0; j < geometry.sectionList[i].getRowCount(); j++) { - - int keyn = geometry.sectionList[i].rowList[j].getKeyCount(); - - for (int k = 0; k < keyn; k++) { - - Key temp = geometry.sectionList[i].rowList[j].keyList[k]; - - int x = temp.getPosition().x(); - int y = temp.getPosition().y(); - - GShape s; - - s = geometry.findShape(temp.getShapeName()); - QString name = temp.getName(); - - drawShape(painter, s, x, y, i, name); - - } - } - } - - if (symbol.isFailed()) { - painter.setPen(keyBorderColor); - painter.drawRect(strtx, strty, endx, endy); - - const int midx = 470, midy = 240; - painter.setPen(lev12color); - painter.drawText(midx, midy, i18n("No preview found")); - } - } else { - QMessageBox errorBox; - errorBox.setText(i18n("Unable to open Preview !")); - errorBox.exec(); - } - -} - -// this function draws the keyboard preview on a QFrame -void KbPreviewFrame::generateKeyboardLayout(const QString &layout, const QString &layoutVariant, const QString &model) -{ - geometry = grammar::parseGeometry(model); - int endx = geometry.getWidth(), endy = geometry.getHeight(); - - QDesktopWidget *desktopWidget = qApp->desktop(); - QRect screenGeometry = desktopWidget->screenGeometry(); - int screenWidth = screenGeometry.width(); - - scaleFactor = 2.5; - while (scaleFactor * endx + screenWidth / 20 > screenWidth) { - scaleFactor -= 0.2; - } - qCDebug(KEYBOARD_PREVIEW) << "scale factor: 2.5 ->" << scaleFactor; - - setFixedSize(scaleFactor * endx + 60, scaleFactor * endy + 60); - qCDebug(KEYBOARD_PREVIEW) << screenWidth << ":" << scaleFactor << scaleFactor *endx + 60 << scaleFactor *endy + 60; - keyboardLayout = grammar::parseSymbols(layout, layoutVariant); -} - - -// this functions gives the index of the tooltip over which mouse hovers -int KbPreviewFrame::itemAt(const QPoint &pos) -{ - int distance = 10000; - int closest = 0; - for (int i = 0; i < tipPoint.size(); i++) { - - int temp = sqrt((pos.x() - tipPoint.at(i).x()) * (pos.x() - tipPoint.at(i).x()) + (pos.y() - tipPoint.at(i).y()) * (pos.y() - tipPoint.at(i).y())); - - if (distance > temp) { - distance = temp; - closest = i; - } - } - - if (distance < 25) { - return closest; - } - - return -1; -} diff --git a/kcms/keyboard/preview/keyaliases.h b/kcms/keyboard/preview/keyaliases.h deleted file mode 100644 --- a/kcms/keyboard/preview/keyaliases.h +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright (C) 2012 Shivam Makkar (amourphious1992@gmail.com) - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -#ifndef ALIASES_H -#define ALIASES_H - -#include - -class Aliases -{ -private: - QMapqwerty; - QMapazerty; - QMapqwertz; - QString findaliasdir(); - -public: - Aliases(); - QString getAlias(const QString &type, const QString &name); -}; - -#endif // ALIASES_H diff --git a/kcms/keyboard/preview/keyaliases.cpp b/kcms/keyboard/preview/keyaliases.cpp deleted file mode 100644 --- a/kcms/keyboard/preview/keyaliases.cpp +++ /dev/null @@ -1,128 +0,0 @@ -/* - * Copyright (C) 2012 Shivam Makkar (amourphious1992@gmail.com) - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -#include "keyaliases.h" -#include "xkb_rules.h" - -#include -#include -#include -#include - -#include -#include -#include -#include - -#include -#include - - -Aliases::Aliases() -{ - QString filename = findaliasdir(); - QFile file(filename); - file.open(QIODevice::ReadOnly | QIODevice::Text); - QString content = file.readAll(); - file.close(); - - QListals; - als = content.split(QStringLiteral("xkb_keycodes")); - - for (int i = 1; i < als.size(); i++) { - - QString temp = als.at(i); - - temp.remove(QStringLiteral(" ")); - temp.remove(QStringLiteral("\n")); - temp.remove(QStringLiteral("\"")); - temp.remove(QStringLiteral(">")); - temp.remove(QStringLiteral("<")); - temp.remove(QStringLiteral(";")); - temp.remove(QStringLiteral("}")); - temp.remove(QStringLiteral("{")); - - QListalskeys; - - alskeys = temp.split(QStringLiteral("alias")); - - if (temp.startsWith(QLatin1String("qwerty"))) { - - for (int k = 1; k < alskeys.size(); k++) { - - QString tmp = alskeys.at(k); - int inofeq = tmp.indexOf(QLatin1String("=")); - - QString lat = tmp.left(inofeq); - QString key = tmp.mid(inofeq + 1); - - qwerty[lat] = key; - } - } - - if (temp.startsWith(QLatin1String("azerty"))) { - - for (int k = 1; k < alskeys.size(); k++) { - QString tmp = alskeys.at(k); - - int inofeq = tmp.indexOf(QLatin1String("=")); - - QString lat = tmp.left(inofeq); - QString key = tmp.mid(inofeq + 1); - - azerty[lat] = key; - } - } - - if (temp.startsWith(QLatin1String("qwertz"))) { - for (int k = 1; k < alskeys.size(); k++) { - - QString tmp = alskeys.at(k); - - int inofeq = tmp.indexOf(QLatin1String("=")); - - QString lat = tmp.left(inofeq); - QString key = tmp.mid(inofeq + 1); - - qwertz[lat] = key; - } - } - } - -} - - -QString Aliases::getAlias(const QString &cname, const QString &name) -{ - QMessageBox q; - QString a = name; - - if (cname == QLatin1String("ma") || cname == QLatin1String("be") || cname == QLatin1String("fr")) { - a = azerty.value(name); - } else { - a = qwerty.value(name); - } - - return a; -} - -QString Aliases::findaliasdir() -{ - QString xkbDir = Rules::findXkbDir(); - return QStringLiteral("%1/keycodes/aliases").arg(xkbDir); -} diff --git a/kcms/keyboard/preview/keyboardlayout.h b/kcms/keyboard/preview/keyboardlayout.h deleted file mode 100644 --- a/kcms/keyboard/preview/keyboardlayout.h +++ /dev/null @@ -1,115 +0,0 @@ -/* - * Copyright (C) 2012 Shivam Makkar (amourphious1992@gmail.com) - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -#ifndef KEYBOARDLAYOUT_NEW_H -#define KEYBOARDLAYOUT_NEW_H - -#include "keyaliases.h" - -#include -#include -#include -#include - - -Q_DECLARE_LOGGING_CATEGORY(KEYBOARD_PREVIEW) - - -class KbKey -{ -private: - QList symbols; - int symbolCount; - -public: - QString keyName; - - KbKey(); - - void setKeyName(QString n); - void addSymbol(QString n, int i); - QString getSymbol(int i); - - int getSymbolCount() - { - return symbolCount; - } - - void display(); -}; - - -class KbLayout -{ -private: - QList include; - QString name; - int keyCount, includeCount, level; - bool parsedSymbol; - -public: - QList keyList; - QString country; - - KbLayout(); - - void setName(QString n); - void addInclude(QString n); - void addKey(); - QString getInclude(int i); - int findKey(QString n); - - void setLevel(int lvl) - { - level = lvl; - } - - int getLevel() - { - return level; - } - - int getKeyCount() - { - return keyCount; - } - - int getIncludeCount() - { - return includeCount; - } - - QString getLayoutName() const - { - return name; - } - - void setParsedSymbol(bool state) - { - parsedSymbol = state; - } - - bool getParsedSymbol() - { - return parsedSymbol; - } - - void display(); -}; - -#endif //KEYBOARDLAYOUT_NEW_H diff --git a/kcms/keyboard/preview/keyboardlayout.cpp b/kcms/keyboard/preview/keyboardlayout.cpp deleted file mode 100644 --- a/kcms/keyboard/preview/keyboardlayout.cpp +++ /dev/null @@ -1,133 +0,0 @@ -/* - * Copyright (C) 2013 Shivam Makkar (amourphious1992@gmail.com) - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - - -#include "keyboardlayout.h" - -#include -#include -#include - - -KbKey::KbKey() -{ - symbolCount = 0; - symbols << QString(); -} - - -void KbKey::setKeyName(QString n) -{ - keyName = n; -} - - -void KbKey::addSymbol(QString n, int i) -{ - if (!symbols.contains(n)) { - symbols[i] = n; - symbolCount++; - symbols << QString(); - } -} - - -QString KbKey::getSymbol(int i) -{ - if (i < symbolCount) { - return symbols[i]; - } else { - return QString(); - } -} - - -void KbKey::display() -{ - qCDebug(KEYBOARD_PREVIEW) << keyName << " : "; - for (int i = 0; i < symbolCount; i++) { - qCDebug(KEYBOARD_PREVIEW) << "\t" << symbols[i]; - } -} - - -KbLayout::KbLayout() -{ - keyCount = 0; - includeCount = 0; - level = 4; - keyList << KbKey(); - include << QString(); - parsedSymbol = true; -} - - -void KbLayout::setName(QString n) -{ - name = n; -} - - -void KbLayout::addInclude(QString n) -{ - if (!include.contains(n)) { - include[includeCount] = n; - includeCount++; - include << QString(); - } -} - - -void KbLayout :: addKey() -{ - keyCount++; - keyList << KbKey(); -} - - -QString KbLayout :: getInclude(int i) -{ - if (i < includeCount) { - return include[i]; - } else { - return QString(); - } -} - - -int KbLayout :: findKey(QString n) -{ - for (int i = 0 ; i < keyCount ; i++) { - if (keyList[i].keyName == n) { - return i; - } - } - return -1; -} - - -void KbLayout::display() -{ -// qCDebug(KEYBOARD_PREVIEW) << name << "\n"; -// for(int i = 0; i - -class QPushButton; -class QComboBox; - -class KeyboardPainter : public QDialog -{ - Q_OBJECT - -public: - explicit KeyboardPainter(); - ~KeyboardPainter() override; - void generateKeyboardLayout(const QString &layout, const QString &variant, const QString &model, const QString &title); - int getHeight(); - int getWidth(); - -public Q_SLOTS: - void levelChanged(int l_id); - -private: - QDialog *kbDialog; - KbPreviewFrame *kbframe; - QPushButton *exitButton; - QComboBox *levelBox; -}; - -#endif // KEYBOARDPAINTER_H diff --git a/kcms/keyboard/preview/keyboardpainter.cpp b/kcms/keyboard/preview/keyboardpainter.cpp deleted file mode 100644 --- a/kcms/keyboard/preview/keyboardpainter.cpp +++ /dev/null @@ -1,100 +0,0 @@ -/* - * Copyright (C) 2012 Shivam Makkar (amourphious1992@gmail.com) - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -#include "keyboardpainter.h" -#include "geometry_components.h" -#include "../flags.h" - -#include -#include -#include -#include -#include - - -KeyboardPainter::KeyboardPainter(): - kbDialog(new QDialog(this)), - kbframe(new KbPreviewFrame(this)), - exitButton(new QPushButton(i18n("Close"), this)), - levelBox(new QComboBox(this)) -{ - kbframe->setFixedSize(1100, 490); - exitButton->setFixedSize(120, 30); - levelBox->setFixedSize(360, 30); - - QVBoxLayout *vLayout = new QVBoxLayout(this); - QHBoxLayout *hLayout = new QHBoxLayout(); - - hLayout->addWidget(exitButton, 0, Qt::AlignLeft); - hLayout->addWidget(levelBox, 0, Qt::AlignRight); - hLayout->addSpacing(30); - - vLayout->addWidget(kbframe); - vLayout->addLayout(hLayout); - - connect(exitButton, &QPushButton::clicked, this, &KeyboardPainter::close); - connect(levelBox, SIGNAL(activated(int)), this, SLOT(levelChanged(int))); - - setWindowTitle(kbframe->getLayoutName()); -} - - -void KeyboardPainter::generateKeyboardLayout(const QString &layout, const QString &variant, const QString &model, const QString &title) -{ - kbframe->generateKeyboardLayout(layout, variant, model); - kbframe->setFixedSize(getWidth(), getHeight()); - kbDialog->setFixedSize(getWidth(), getWidth()); - setWindowTitle(title); - - int level = kbframe->getLevel(); - - if (level > 4) { - levelBox->addItem(i18nc("Keyboard layout levels", "Level %1, %2", 3, 4)); - for (int i = 5; i <= level; i += 2) { - levelBox->addItem(i18nc("Keyboard layout levels", "Level %1, %2", i, i + 1)); - } - } else { - levelBox->setVisible(false); - } -} - -void KeyboardPainter::levelChanged(int l_id) -{ - kbframe->setL_id(l_id); -} - -int KeyboardPainter::getHeight() -{ - int height = kbframe->getHeight(); - height = kbframe->getScaleFactor() * height + 50; - return height; -} - -int KeyboardPainter::getWidth() -{ - int width = kbframe->getWidth(); - width = kbframe->getScaleFactor() * width + 20; - return width; -} - -KeyboardPainter::~KeyboardPainter() -{ - delete kbframe; - delete exitButton; - delete levelBox; -} diff --git a/kcms/keyboard/preview/keysym2ucs.h b/kcms/keyboard/preview/keysym2ucs.h deleted file mode 100644 --- a/kcms/keyboard/preview/keysym2ucs.h +++ /dev/null @@ -1,27 +0,0 @@ -/* - * Copyright (C) 2012 Andriy Rysin (arysin@gmail.com) - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -#ifndef KEYSYM2UCS_H -#define KEYSYM2UCS_H - -#include -#include - -extern long keysym2ucs(KeySym keysym); - -#endif diff --git a/kcms/keyboard/preview/keysym2ucs.cpp b/kcms/keyboard/preview/keysym2ucs.cpp deleted file mode 100644 --- a/kcms/keyboard/preview/keysym2ucs.cpp +++ /dev/null @@ -1,901 +0,0 @@ -/* - * Copyright (C) 2010 Andriy Rysin (rysin@kde.org) - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -/* $XFree86$ - * This module converts keysym values into the corresponding ISO 10646-1 - * (UCS, Unicode) values. - * - * The array keysymtab[] contains pairs of X11 keysym values for graphical - * characters and the corresponding Unicode value. The function - * keysym2ucs() maps a keysym onto a Unicode value using a binary search, - * therefore keysymtab[] must remain SORTED by keysym value. - * - * The keysym -> UTF-8 conversion will hopefully one day be provided - * by Xlib via XmbLookupString() and should ideally not have to be - * done in X applications. But we are not there yet. - * - * We allow to represent any UCS character in the range U+00000000 to - * U+00FFFFFF by a keysym value in the range 0x01000000 to 0x01ffffff. - * This admittedly does not cover the entire 31-bit space of UCS, but - * it does cover all of the characters up to U+10FFFF, which can be - * represented by UTF-16, and more, and it is very unlikely that higher - * UCS codes will ever be assigned by ISO. So to get Unicode character - * U+ABCD you can directly use keysym 0x1000abcd. - * - * NOTE: The comments in the table below contain the actual character - * encoded in UTF-8, so for viewing and editing best use an editor in - * UTF-8 mode. - * - * Author: Markus G. Kuhn , University of Cambridge, June 1999 - * - * Special thanks to Richard Verhoeven for preparing - * an initial draft of the mapping table. - */ - -#include - -struct codepair { - unsigned short keysym; - unsigned short ucs; -} keysymtab[] = { - { 0x01a1, 0x0104 }, /* Aogonek Ą LATIN CAPITAL LETTER A WITH OGONEK */ - { 0x01a2, 0x02d8 }, /* breve ˘ BREVE */ - { 0x01a3, 0x0141 }, /* Lstroke Ł LATIN CAPITAL LETTER L WITH STROKE */ - { 0x01a5, 0x013d }, /* Lcaron Ľ LATIN CAPITAL LETTER L WITH CARON */ - { 0x01a6, 0x015a }, /* Sacute Ś LATIN CAPITAL LETTER S WITH ACUTE */ - { 0x01a9, 0x0160 }, /* Scaron Š LATIN CAPITAL LETTER S WITH CARON */ - { 0x01aa, 0x015e }, /* Scedilla Ş LATIN CAPITAL LETTER S WITH CEDILLA */ - { 0x01ab, 0x0164 }, /* Tcaron Ť LATIN CAPITAL LETTER T WITH CARON */ - { 0x01ac, 0x0179 }, /* Zacute Ź LATIN CAPITAL LETTER Z WITH ACUTE */ - { 0x01ae, 0x017d }, /* Zcaron Ž LATIN CAPITAL LETTER Z WITH CARON */ - { 0x01af, 0x017b }, /* Zabovedot Ż LATIN CAPITAL LETTER Z WITH DOT ABOVE */ - { 0x01b1, 0x0105 }, /* aogonek ą LATIN SMALL LETTER A WITH OGONEK */ - { 0x01b2, 0x02db }, /* ogonek ˛ OGONEK */ - { 0x01b3, 0x0142 }, /* lstroke ł LATIN SMALL LETTER L WITH STROKE */ - { 0x01b5, 0x013e }, /* lcaron ľ LATIN SMALL LETTER L WITH CARON */ - { 0x01b6, 0x015b }, /* sacute ś LATIN SMALL LETTER S WITH ACUTE */ - { 0x01b7, 0x02c7 }, /* caron ˇ CARON */ - { 0x01b9, 0x0161 }, /* scaron š LATIN SMALL LETTER S WITH CARON */ - { 0x01ba, 0x015f }, /* scedilla ş LATIN SMALL LETTER S WITH CEDILLA */ - { 0x01bb, 0x0165 }, /* tcaron ť LATIN SMALL LETTER T WITH CARON */ - { 0x01bc, 0x017a }, /* zacute ź LATIN SMALL LETTER Z WITH ACUTE */ - { 0x01bd, 0x02dd }, /* doubleacute ˝ DOUBLE ACUTE ACCENT */ - { 0x01be, 0x017e }, /* zcaron ž LATIN SMALL LETTER Z WITH CARON */ - { 0x01bf, 0x017c }, /* zabovedot ż LATIN SMALL LETTER Z WITH DOT ABOVE */ - { 0x01c0, 0x0154 }, /* Racute Ŕ LATIN CAPITAL LETTER R WITH ACUTE */ - { 0x01c3, 0x0102 }, /* Abreve Ă LATIN CAPITAL LETTER A WITH BREVE */ - { 0x01c5, 0x0139 }, /* Lacute Ĺ LATIN CAPITAL LETTER L WITH ACUTE */ - { 0x01c6, 0x0106 }, /* Cacute Ć LATIN CAPITAL LETTER C WITH ACUTE */ - { 0x01c8, 0x010c }, /* Ccaron Č LATIN CAPITAL LETTER C WITH CARON */ - { 0x01ca, 0x0118 }, /* Eogonek Ę LATIN CAPITAL LETTER E WITH OGONEK */ - { 0x01cc, 0x011a }, /* Ecaron Ě LATIN CAPITAL LETTER E WITH CARON */ - { 0x01cf, 0x010e }, /* Dcaron Ď LATIN CAPITAL LETTER D WITH CARON */ - { 0x01d0, 0x0110 }, /* Dstroke Đ LATIN CAPITAL LETTER D WITH STROKE */ - { 0x01d1, 0x0143 }, /* Nacute Ń LATIN CAPITAL LETTER N WITH ACUTE */ - { 0x01d2, 0x0147 }, /* Ncaron Ň LATIN CAPITAL LETTER N WITH CARON */ - { 0x01d5, 0x0150 }, /* Odoubleacute Ő LATIN CAPITAL LETTER O WITH DOUBLE ACUTE */ - { 0x01d8, 0x0158 }, /* Rcaron Ř LATIN CAPITAL LETTER R WITH CARON */ - { 0x01d9, 0x016e }, /* Uring Ů LATIN CAPITAL LETTER U WITH RING ABOVE */ - { 0x01db, 0x0170 }, /* Udoubleacute Ű LATIN CAPITAL LETTER U WITH DOUBLE ACUTE */ - { 0x01de, 0x0162 }, /* Tcedilla Ţ LATIN CAPITAL LETTER T WITH CEDILLA */ - { 0x01e0, 0x0155 }, /* racute ŕ LATIN SMALL LETTER R WITH ACUTE */ - { 0x01e3, 0x0103 }, /* abreve ă LATIN SMALL LETTER A WITH BREVE */ - { 0x01e5, 0x013a }, /* lacute ĺ LATIN SMALL LETTER L WITH ACUTE */ - { 0x01e6, 0x0107 }, /* cacute ć LATIN SMALL LETTER C WITH ACUTE */ - { 0x01e8, 0x010d }, /* ccaron č LATIN SMALL LETTER C WITH CARON */ - { 0x01ea, 0x0119 }, /* eogonek ę LATIN SMALL LETTER E WITH OGONEK */ - { 0x01ec, 0x011b }, /* ecaron ě LATIN SMALL LETTER E WITH CARON */ - { 0x01ef, 0x010f }, /* dcaron ď LATIN SMALL LETTER D WITH CARON */ - { 0x01f0, 0x0111 }, /* dstroke đ LATIN SMALL LETTER D WITH STROKE */ - { 0x01f1, 0x0144 }, /* nacute ń LATIN SMALL LETTER N WITH ACUTE */ - { 0x01f2, 0x0148 }, /* ncaron ň LATIN SMALL LETTER N WITH CARON */ - { 0x01f5, 0x0151 }, /* odoubleacute ő LATIN SMALL LETTER O WITH DOUBLE ACUTE */ - { 0x01f8, 0x0159 }, /* rcaron ř LATIN SMALL LETTER R WITH CARON */ - { 0x01f9, 0x016f }, /* uring ů LATIN SMALL LETTER U WITH RING ABOVE */ - { 0x01fb, 0x0171 }, /* udoubleacute ű LATIN SMALL LETTER U WITH DOUBLE ACUTE */ - { 0x01fe, 0x0163 }, /* tcedilla ţ LATIN SMALL LETTER T WITH CEDILLA */ - { 0x01ff, 0x02d9 }, /* abovedot ˙ DOT ABOVE */ - { 0x02a1, 0x0126 }, /* Hstroke Ħ LATIN CAPITAL LETTER H WITH STROKE */ - { 0x02a6, 0x0124 }, /* Hcircumflex Ĥ LATIN CAPITAL LETTER H WITH CIRCUMFLEX */ - { 0x02a9, 0x0130 }, /* Iabovedot İ LATIN CAPITAL LETTER I WITH DOT ABOVE */ - { 0x02ab, 0x011e }, /* Gbreve Ğ LATIN CAPITAL LETTER G WITH BREVE */ - { 0x02ac, 0x0134 }, /* Jcircumflex Ĵ LATIN CAPITAL LETTER J WITH CIRCUMFLEX */ - { 0x02b1, 0x0127 }, /* hstroke ħ LATIN SMALL LETTER H WITH STROKE */ - { 0x02b6, 0x0125 }, /* hcircumflex ĥ LATIN SMALL LETTER H WITH CIRCUMFLEX */ - { 0x02b9, 0x0131 }, /* idotless ı LATIN SMALL LETTER DOTLESS I */ - { 0x02bb, 0x011f }, /* gbreve ğ LATIN SMALL LETTER G WITH BREVE */ - { 0x02bc, 0x0135 }, /* jcircumflex ĵ LATIN SMALL LETTER J WITH CIRCUMFLEX */ - { 0x02c5, 0x010a }, /* Cabovedot Ċ LATIN CAPITAL LETTER C WITH DOT ABOVE */ - { 0x02c6, 0x0108 }, /* Ccircumflex Ĉ LATIN CAPITAL LETTER C WITH CIRCUMFLEX */ - { 0x02d5, 0x0120 }, /* Gabovedot Ġ LATIN CAPITAL LETTER G WITH DOT ABOVE */ - { 0x02d8, 0x011c }, /* Gcircumflex Ĝ LATIN CAPITAL LETTER G WITH CIRCUMFLEX */ - { 0x02dd, 0x016c }, /* Ubreve Ŭ LATIN CAPITAL LETTER U WITH BREVE */ - { 0x02de, 0x015c }, /* Scircumflex Ŝ LATIN CAPITAL LETTER S WITH CIRCUMFLEX */ - { 0x02e5, 0x010b }, /* cabovedot ċ LATIN SMALL LETTER C WITH DOT ABOVE */ - { 0x02e6, 0x0109 }, /* ccircumflex ĉ LATIN SMALL LETTER C WITH CIRCUMFLEX */ - { 0x02f5, 0x0121 }, /* gabovedot ġ LATIN SMALL LETTER G WITH DOT ABOVE */ - { 0x02f8, 0x011d }, /* gcircumflex ĝ LATIN SMALL LETTER G WITH CIRCUMFLEX */ - { 0x02fd, 0x016d }, /* ubreve ŭ LATIN SMALL LETTER U WITH BREVE */ - { 0x02fe, 0x015d }, /* scircumflex ŝ LATIN SMALL LETTER S WITH CIRCUMFLEX */ - { 0x03a2, 0x0138 }, /* kra ĸ LATIN SMALL LETTER KRA */ - { 0x03a3, 0x0156 }, /* Rcedilla Ŗ LATIN CAPITAL LETTER R WITH CEDILLA */ - { 0x03a5, 0x0128 }, /* Itilde Ĩ LATIN CAPITAL LETTER I WITH TILDE */ - { 0x03a6, 0x013b }, /* Lcedilla Ļ LATIN CAPITAL LETTER L WITH CEDILLA */ - { 0x03aa, 0x0112 }, /* Emacron Ē LATIN CAPITAL LETTER E WITH MACRON */ - { 0x03ab, 0x0122 }, /* Gcedilla Ģ LATIN CAPITAL LETTER G WITH CEDILLA */ - { 0x03ac, 0x0166 }, /* Tslash Ŧ LATIN CAPITAL LETTER T WITH STROKE */ - { 0x03b3, 0x0157 }, /* rcedilla ŗ LATIN SMALL LETTER R WITH CEDILLA */ - { 0x03b5, 0x0129 }, /* itilde ĩ LATIN SMALL LETTER I WITH TILDE */ - { 0x03b6, 0x013c }, /* lcedilla ļ LATIN SMALL LETTER L WITH CEDILLA */ - { 0x03ba, 0x0113 }, /* emacron ē LATIN SMALL LETTER E WITH MACRON */ - { 0x03bb, 0x0123 }, /* gcedilla ģ LATIN SMALL LETTER G WITH CEDILLA */ - { 0x03bc, 0x0167 }, /* tslash ŧ LATIN SMALL LETTER T WITH STROKE */ - { 0x03bd, 0x014a }, /* ENG Ŋ LATIN CAPITAL LETTER ENG */ - { 0x03bf, 0x014b }, /* eng ŋ LATIN SMALL LETTER ENG */ - { 0x03c0, 0x0100 }, /* Amacron Ā LATIN CAPITAL LETTER A WITH MACRON */ - { 0x03c7, 0x012e }, /* Iogonek Į LATIN CAPITAL LETTER I WITH OGONEK */ - { 0x03cc, 0x0116 }, /* Eabovedot Ė LATIN CAPITAL LETTER E WITH DOT ABOVE */ - { 0x03cf, 0x012a }, /* Imacron Ī LATIN CAPITAL LETTER I WITH MACRON */ - { 0x03d1, 0x0145 }, /* Ncedilla Ņ LATIN CAPITAL LETTER N WITH CEDILLA */ - { 0x03d2, 0x014c }, /* Omacron Ō LATIN CAPITAL LETTER O WITH MACRON */ - { 0x03d3, 0x0136 }, /* Kcedilla Ķ LATIN CAPITAL LETTER K WITH CEDILLA */ - { 0x03d9, 0x0172 }, /* Uogonek Ų LATIN CAPITAL LETTER U WITH OGONEK */ - { 0x03dd, 0x0168 }, /* Utilde Ũ LATIN CAPITAL LETTER U WITH TILDE */ - { 0x03de, 0x016a }, /* Umacron Ū LATIN CAPITAL LETTER U WITH MACRON */ - { 0x03e0, 0x0101 }, /* amacron ā LATIN SMALL LETTER A WITH MACRON */ - { 0x03e7, 0x012f }, /* iogonek į LATIN SMALL LETTER I WITH OGONEK */ - { 0x03ec, 0x0117 }, /* eabovedot ė LATIN SMALL LETTER E WITH DOT ABOVE */ - { 0x03ef, 0x012b }, /* imacron ī LATIN SMALL LETTER I WITH MACRON */ - { 0x03f1, 0x0146 }, /* ncedilla ņ LATIN SMALL LETTER N WITH CEDILLA */ - { 0x03f2, 0x014d }, /* omacron ō LATIN SMALL LETTER O WITH MACRON */ - { 0x03f3, 0x0137 }, /* kcedilla ķ LATIN SMALL LETTER K WITH CEDILLA */ - { 0x03f9, 0x0173 }, /* uogonek ų LATIN SMALL LETTER U WITH OGONEK */ - { 0x03fd, 0x0169 }, /* utilde ũ LATIN SMALL LETTER U WITH TILDE */ - { 0x03fe, 0x016b }, /* umacron ū LATIN SMALL LETTER U WITH MACRON */ - { 0x047e, 0x203e }, /* overline ‾ OVERLINE */ - { 0x04a1, 0x3002 }, /* kana_fullstop 。 IDEOGRAPHIC FULL STOP */ - { 0x04a2, 0x300c }, /* kana_openingbracket 「 LEFT CORNER BRACKET */ - { 0x04a3, 0x300d }, /* kana_closingbracket 」 RIGHT CORNER BRACKET */ - { 0x04a4, 0x3001 }, /* kana_comma 、 IDEOGRAPHIC COMMA */ - { 0x04a5, 0x30fb }, /* kana_conjunctive ・ KATAKANA MIDDLE DOT */ - { 0x04a6, 0x30f2 }, /* kana_WO ヲ KATAKANA LETTER WO */ - { 0x04a7, 0x30a1 }, /* kana_a ァ KATAKANA LETTER SMALL A */ - { 0x04a8, 0x30a3 }, /* kana_i ィ KATAKANA LETTER SMALL I */ - { 0x04a9, 0x30a5 }, /* kana_u ゥ KATAKANA LETTER SMALL U */ - { 0x04aa, 0x30a7 }, /* kana_e ェ KATAKANA LETTER SMALL E */ - { 0x04ab, 0x30a9 }, /* kana_o ォ KATAKANA LETTER SMALL O */ - { 0x04ac, 0x30e3 }, /* kana_ya ャ KATAKANA LETTER SMALL YA */ - { 0x04ad, 0x30e5 }, /* kana_yu ュ KATAKANA LETTER SMALL YU */ - { 0x04ae, 0x30e7 }, /* kana_yo ョ KATAKANA LETTER SMALL YO */ - { 0x04af, 0x30c3 }, /* kana_tsu ッ KATAKANA LETTER SMALL TU */ - { 0x04b0, 0x30fc }, /* prolongedsound ー KATAKANA-HIRAGANA PROLONGED SOUND MARK */ - { 0x04b1, 0x30a2 }, /* kana_A ア KATAKANA LETTER A */ - { 0x04b2, 0x30a4 }, /* kana_I イ KATAKANA LETTER I */ - { 0x04b3, 0x30a6 }, /* kana_U ウ KATAKANA LETTER U */ - { 0x04b4, 0x30a8 }, /* kana_E エ KATAKANA LETTER E */ - { 0x04b5, 0x30aa }, /* kana_O オ KATAKANA LETTER O */ - { 0x04b6, 0x30ab }, /* kana_KA カ KATAKANA LETTER KA */ - { 0x04b7, 0x30ad }, /* kana_KI キ KATAKANA LETTER KI */ - { 0x04b8, 0x30af }, /* kana_KU ク KATAKANA LETTER KU */ - { 0x04b9, 0x30b1 }, /* kana_KE ケ KATAKANA LETTER KE */ - { 0x04ba, 0x30b3 }, /* kana_KO コ KATAKANA LETTER KO */ - { 0x04bb, 0x30b5 }, /* kana_SA サ KATAKANA LETTER SA */ - { 0x04bc, 0x30b7 }, /* kana_SHI シ KATAKANA LETTER SI */ - { 0x04bd, 0x30b9 }, /* kana_SU ス KATAKANA LETTER SU */ - { 0x04be, 0x30bb }, /* kana_SE セ KATAKANA LETTER SE */ - { 0x04bf, 0x30bd }, /* kana_SO ソ KATAKANA LETTER SO */ - { 0x04c0, 0x30bf }, /* kana_TA タ KATAKANA LETTER TA */ - { 0x04c1, 0x30c1 }, /* kana_CHI チ KATAKANA LETTER TI */ - { 0x04c2, 0x30c4 }, /* kana_TSU ツ KATAKANA LETTER TU */ - { 0x04c3, 0x30c6 }, /* kana_TE テ KATAKANA LETTER TE */ - { 0x04c4, 0x30c8 }, /* kana_TO ト KATAKANA LETTER TO */ - { 0x04c5, 0x30ca }, /* kana_NA ナ KATAKANA LETTER NA */ - { 0x04c6, 0x30cb }, /* kana_NI ニ KATAKANA LETTER NI */ - { 0x04c7, 0x30cc }, /* kana_NU ヌ KATAKANA LETTER NU */ - { 0x04c8, 0x30cd }, /* kana_NE ネ KATAKANA LETTER NE */ - { 0x04c9, 0x30ce }, /* kana_NO ノ KATAKANA LETTER NO */ - { 0x04ca, 0x30cf }, /* kana_HA ハ KATAKANA LETTER HA */ - { 0x04cb, 0x30d2 }, /* kana_HI ヒ KATAKANA LETTER HI */ - { 0x04cc, 0x30d5 }, /* kana_FU フ KATAKANA LETTER HU */ - { 0x04cd, 0x30d8 }, /* kana_HE ヘ KATAKANA LETTER HE */ - { 0x04ce, 0x30db }, /* kana_HO ホ KATAKANA LETTER HO */ - { 0x04cf, 0x30de }, /* kana_MA マ KATAKANA LETTER MA */ - { 0x04d0, 0x30df }, /* kana_MI ミ KATAKANA LETTER MI */ - { 0x04d1, 0x30e0 }, /* kana_MU ム KATAKANA LETTER MU */ - { 0x04d2, 0x30e1 }, /* kana_ME メ KATAKANA LETTER ME */ - { 0x04d3, 0x30e2 }, /* kana_MO モ KATAKANA LETTER MO */ - { 0x04d4, 0x30e4 }, /* kana_YA ヤ KATAKANA LETTER YA */ - { 0x04d5, 0x30e6 }, /* kana_YU ユ KATAKANA LETTER YU */ - { 0x04d6, 0x30e8 }, /* kana_YO ヨ KATAKANA LETTER YO */ - { 0x04d7, 0x30e9 }, /* kana_RA ラ KATAKANA LETTER RA */ - { 0x04d8, 0x30ea }, /* kana_RI リ KATAKANA LETTER RI */ - { 0x04d9, 0x30eb }, /* kana_RU ル KATAKANA LETTER RU */ - { 0x04da, 0x30ec }, /* kana_RE レ KATAKANA LETTER RE */ - { 0x04db, 0x30ed }, /* kana_RO ロ KATAKANA LETTER RO */ - { 0x04dc, 0x30ef }, /* kana_WA ワ KATAKANA LETTER WA */ - { 0x04dd, 0x30f3 }, /* kana_N ン KATAKANA LETTER N */ - { 0x04de, 0x309b }, /* voicedsound ゛ KATAKANA-HIRAGANA VOICED SOUND MARK */ - { 0x04df, 0x309c }, /* semivoicedsound ゜ KATAKANA-HIRAGANA SEMI-VOICED SOUND MARK */ - { 0x05ac, 0x060c }, /* Arabic_comma ، ARABIC COMMA */ - { 0x05bb, 0x061b }, /* Arabic_semicolon ؛ ARABIC SEMICOLON */ - { 0x05bf, 0x061f }, /* Arabic_question_mark ؟ ARABIC QUESTION MARK */ - { 0x05c1, 0x0621 }, /* Arabic_hamza ء ARABIC LETTER HAMZA */ - { 0x05c2, 0x0622 }, /* Arabic_maddaonalef آ ARABIC LETTER ALEF WITH MADDA ABOVE */ - { 0x05c3, 0x0623 }, /* Arabic_hamzaonalef أ ARABIC LETTER ALEF WITH HAMZA ABOVE */ - { 0x05c4, 0x0624 }, /* Arabic_hamzaonwaw ؤ ARABIC LETTER WAW WITH HAMZA ABOVE */ - { 0x05c5, 0x0625 }, /* Arabic_hamzaunderalef إ ARABIC LETTER ALEF WITH HAMZA BELOW */ - { 0x05c6, 0x0626 }, /* Arabic_hamzaonyeh ئ ARABIC LETTER YEH WITH HAMZA ABOVE */ - { 0x05c7, 0x0627 }, /* Arabic_alef ا ARABIC LETTER ALEF */ - { 0x05c8, 0x0628 }, /* Arabic_beh ب ARABIC LETTER BEH */ - { 0x05c9, 0x0629 }, /* Arabic_tehmarbuta ة ARABIC LETTER TEH MARBUTA */ - { 0x05ca, 0x062a }, /* Arabic_teh ت ARABIC LETTER TEH */ - { 0x05cb, 0x062b }, /* Arabic_theh ث ARABIC LETTER THEH */ - { 0x05cc, 0x062c }, /* Arabic_jeem ج ARABIC LETTER JEEM */ - { 0x05cd, 0x062d }, /* Arabic_hah ح ARABIC LETTER HAH */ - { 0x05ce, 0x062e }, /* Arabic_khah خ ARABIC LETTER KHAH */ - { 0x05cf, 0x062f }, /* Arabic_dal د ARABIC LETTER DAL */ - { 0x05d0, 0x0630 }, /* Arabic_thal ذ ARABIC LETTER THAL */ - { 0x05d1, 0x0631 }, /* Arabic_ra ر ARABIC LETTER REH */ - { 0x05d2, 0x0632 }, /* Arabic_zain ز ARABIC LETTER ZAIN */ - { 0x05d3, 0x0633 }, /* Arabic_seen س ARABIC LETTER SEEN */ - { 0x05d4, 0x0634 }, /* Arabic_sheen ش ARABIC LETTER SHEEN */ - { 0x05d5, 0x0635 }, /* Arabic_sad ص ARABIC LETTER SAD */ - { 0x05d6, 0x0636 }, /* Arabic_dad ض ARABIC LETTER DAD */ - { 0x05d7, 0x0637 }, /* Arabic_tah ط ARABIC LETTER TAH */ - { 0x05d8, 0x0638 }, /* Arabic_zah ظ ARABIC LETTER ZAH */ - { 0x05d9, 0x0639 }, /* Arabic_ain ع ARABIC LETTER AIN */ - { 0x05da, 0x063a }, /* Arabic_ghain غ ARABIC LETTER GHAIN */ - { 0x05e0, 0x0640 }, /* Arabic_tatweel ـ ARABIC TATWEEL */ - { 0x05e1, 0x0641 }, /* Arabic_feh ف ARABIC LETTER FEH */ - { 0x05e2, 0x0642 }, /* Arabic_qaf ق ARABIC LETTER QAF */ - { 0x05e3, 0x0643 }, /* Arabic_kaf ك ARABIC LETTER KAF */ - { 0x05e4, 0x0644 }, /* Arabic_lam ل ARABIC LETTER LAM */ - { 0x05e5, 0x0645 }, /* Arabic_meem م ARABIC LETTER MEEM */ - { 0x05e6, 0x0646 }, /* Arabic_noon ن ARABIC LETTER NOON */ - { 0x05e7, 0x0647 }, /* Arabic_ha ه ARABIC LETTER HEH */ - { 0x05e8, 0x0648 }, /* Arabic_waw و ARABIC LETTER WAW */ - { 0x05e9, 0x0649 }, /* Arabic_alefmaksura ى ARABIC LETTER ALEF MAKSURA */ - { 0x05ea, 0x064a }, /* Arabic_yeh ي ARABIC LETTER YEH */ - { 0x05eb, 0x064b }, /* Arabic_fathatan ً ARABIC FATHATAN */ - { 0x05ec, 0x064c }, /* Arabic_dammatan ٌ ARABIC DAMMATAN */ - { 0x05ed, 0x064d }, /* Arabic_kasratan ٍ ARABIC KASRATAN */ - { 0x05ee, 0x064e }, /* Arabic_fatha َ ARABIC FATHA */ - { 0x05ef, 0x064f }, /* Arabic_damma ُ ARABIC DAMMA */ - { 0x05f0, 0x0650 }, /* Arabic_kasra ِ ARABIC KASRA */ - { 0x05f1, 0x0651 }, /* Arabic_shadda ّ ARABIC SHADDA */ - { 0x05f2, 0x0652 }, /* Arabic_sukun ْ ARABIC SUKUN */ - { 0x06a1, 0x0452 }, /* Serbian_dje ђ CYRILLIC SMALL LETTER DJE */ - { 0x06a2, 0x0453 }, /* Macedonia_gje ѓ CYRILLIC SMALL LETTER GJE */ - { 0x06a3, 0x0451 }, /* Cyrillic_io ё CYRILLIC SMALL LETTER IO */ - { 0x06a4, 0x0454 }, /* Ukrainian_ie є CYRILLIC SMALL LETTER UKRAINIAN IE */ - { 0x06a5, 0x0455 }, /* Macedonia_dse ѕ CYRILLIC SMALL LETTER DZE */ - { 0x06a6, 0x0456 }, /* Ukrainian_i і CYRILLIC SMALL LETTER BYELORUSSIAN-UKRAINIAN I */ - { 0x06a7, 0x0457 }, /* Ukrainian_yi ї CYRILLIC SMALL LETTER YI */ - { 0x06a8, 0x0458 }, /* Cyrillic_je ј CYRILLIC SMALL LETTER JE */ - { 0x06a9, 0x0459 }, /* Cyrillic_lje љ CYRILLIC SMALL LETTER LJE */ - { 0x06aa, 0x045a }, /* Cyrillic_nje њ CYRILLIC SMALL LETTER NJE */ - { 0x06ab, 0x045b }, /* Serbian_tshe ћ CYRILLIC SMALL LETTER TSHE */ - { 0x06ac, 0x045c }, /* Macedonia_kje ќ CYRILLIC SMALL LETTER KJE */ - { 0x06ad, 0x0491 }, /* Ukrainian_ghe_with_upturn ґ CYRILLIC SMALL LETTER GHE WITH UPTURN */ - { 0x06ae, 0x045e }, /* Byelorussian_shortu ў CYRILLIC SMALL LETTER SHORT U */ - { 0x06af, 0x045f }, /* Cyrillic_dzhe џ CYRILLIC SMALL LETTER DZHE */ - { 0x06b0, 0x2116 }, /* numerosign № NUMERO SIGN */ - { 0x06b1, 0x0402 }, /* Serbian_DJE Ђ CYRILLIC CAPITAL LETTER DJE */ - { 0x06b2, 0x0403 }, /* Macedonia_GJE Ѓ CYRILLIC CAPITAL LETTER GJE */ - { 0x06b3, 0x0401 }, /* Cyrillic_IO Ё CYRILLIC CAPITAL LETTER IO */ - { 0x06b4, 0x0404 }, /* Ukrainian_IE Є CYRILLIC CAPITAL LETTER UKRAINIAN IE */ - { 0x06b5, 0x0405 }, /* Macedonia_DSE Ѕ CYRILLIC CAPITAL LETTER DZE */ - { 0x06b6, 0x0406 }, /* Ukrainian_I І CYRILLIC CAPITAL LETTER BYELORUSSIAN-UKRAINIAN I */ - { 0x06b7, 0x0407 }, /* Ukrainian_YI Ї CYRILLIC CAPITAL LETTER YI */ - { 0x06b8, 0x0408 }, /* Cyrillic_JE Ј CYRILLIC CAPITAL LETTER JE */ - { 0x06b9, 0x0409 }, /* Cyrillic_LJE Љ CYRILLIC CAPITAL LETTER LJE */ - { 0x06ba, 0x040a }, /* Cyrillic_NJE Њ CYRILLIC CAPITAL LETTER NJE */ - { 0x06bb, 0x040b }, /* Serbian_TSHE Ћ CYRILLIC CAPITAL LETTER TSHE */ - { 0x06bc, 0x040c }, /* Macedonia_KJE Ќ CYRILLIC CAPITAL LETTER KJE */ - { 0x06bd, 0x0490 }, /* Ukrainian_GHE_WITH_UPTURN Ґ CYRILLIC CAPITAL LETTER GHE WITH UPTURN */ - { 0x06be, 0x040e }, /* Byelorussian_SHORTU Ў CYRILLIC CAPITAL LETTER SHORT U */ - { 0x06bf, 0x040f }, /* Cyrillic_DZHE Џ CYRILLIC CAPITAL LETTER DZHE */ - { 0x06c0, 0x044e }, /* Cyrillic_yu ю CYRILLIC SMALL LETTER YU */ - { 0x06c1, 0x0430 }, /* Cyrillic_a а CYRILLIC SMALL LETTER A */ - { 0x06c2, 0x0431 }, /* Cyrillic_be б CYRILLIC SMALL LETTER BE */ - { 0x06c3, 0x0446 }, /* Cyrillic_tse ц CYRILLIC SMALL LETTER TSE */ - { 0x06c4, 0x0434 }, /* Cyrillic_de д CYRILLIC SMALL LETTER DE */ - { 0x06c5, 0x0435 }, /* Cyrillic_ie е CYRILLIC SMALL LETTER IE */ - { 0x06c6, 0x0444 }, /* Cyrillic_ef ф CYRILLIC SMALL LETTER EF */ - { 0x06c7, 0x0433 }, /* Cyrillic_ghe г CYRILLIC SMALL LETTER GHE */ - { 0x06c8, 0x0445 }, /* Cyrillic_ha х CYRILLIC SMALL LETTER HA */ - { 0x06c9, 0x0438 }, /* Cyrillic_i и CYRILLIC SMALL LETTER I */ - { 0x06ca, 0x0439 }, /* Cyrillic_shorti й CYRILLIC SMALL LETTER SHORT I */ - { 0x06cb, 0x043a }, /* Cyrillic_ka к CYRILLIC SMALL LETTER KA */ - { 0x06cc, 0x043b }, /* Cyrillic_el л CYRILLIC SMALL LETTER EL */ - { 0x06cd, 0x043c }, /* Cyrillic_em м CYRILLIC SMALL LETTER EM */ - { 0x06ce, 0x043d }, /* Cyrillic_en н CYRILLIC SMALL LETTER EN */ - { 0x06cf, 0x043e }, /* Cyrillic_o о CYRILLIC SMALL LETTER O */ - { 0x06d0, 0x043f }, /* Cyrillic_pe п CYRILLIC SMALL LETTER PE */ - { 0x06d1, 0x044f }, /* Cyrillic_ya я CYRILLIC SMALL LETTER YA */ - { 0x06d2, 0x0440 }, /* Cyrillic_er р CYRILLIC SMALL LETTER ER */ - { 0x06d3, 0x0441 }, /* Cyrillic_es с CYRILLIC SMALL LETTER ES */ - { 0x06d4, 0x0442 }, /* Cyrillic_te т CYRILLIC SMALL LETTER TE */ - { 0x06d5, 0x0443 }, /* Cyrillic_u у CYRILLIC SMALL LETTER U */ - { 0x06d6, 0x0436 }, /* Cyrillic_zhe ж CYRILLIC SMALL LETTER ZHE */ - { 0x06d7, 0x0432 }, /* Cyrillic_ve в CYRILLIC SMALL LETTER VE */ - { 0x06d8, 0x044c }, /* Cyrillic_softsign ь CYRILLIC SMALL LETTER SOFT SIGN */ - { 0x06d9, 0x044b }, /* Cyrillic_yeru ы CYRILLIC SMALL LETTER YERU */ - { 0x06da, 0x0437 }, /* Cyrillic_ze з CYRILLIC SMALL LETTER ZE */ - { 0x06db, 0x0448 }, /* Cyrillic_sha ш CYRILLIC SMALL LETTER SHA */ - { 0x06dc, 0x044d }, /* Cyrillic_e э CYRILLIC SMALL LETTER E */ - { 0x06dd, 0x0449 }, /* Cyrillic_shcha щ CYRILLIC SMALL LETTER SHCHA */ - { 0x06de, 0x0447 }, /* Cyrillic_che ч CYRILLIC SMALL LETTER CHE */ - { 0x06df, 0x044a }, /* Cyrillic_hardsign ъ CYRILLIC SMALL LETTER HARD SIGN */ - { 0x06e0, 0x042e }, /* Cyrillic_YU Ю CYRILLIC CAPITAL LETTER YU */ - { 0x06e1, 0x0410 }, /* Cyrillic_A А CYRILLIC CAPITAL LETTER A */ - { 0x06e2, 0x0411 }, /* Cyrillic_BE Б CYRILLIC CAPITAL LETTER BE */ - { 0x06e3, 0x0426 }, /* Cyrillic_TSE Ц CYRILLIC CAPITAL LETTER TSE */ - { 0x06e4, 0x0414 }, /* Cyrillic_DE Д CYRILLIC CAPITAL LETTER DE */ - { 0x06e5, 0x0415 }, /* Cyrillic_IE Е CYRILLIC CAPITAL LETTER IE */ - { 0x06e6, 0x0424 }, /* Cyrillic_EF Ф CYRILLIC CAPITAL LETTER EF */ - { 0x06e7, 0x0413 }, /* Cyrillic_GHE Г CYRILLIC CAPITAL LETTER GHE */ - { 0x06e8, 0x0425 }, /* Cyrillic_HA Х CYRILLIC CAPITAL LETTER HA */ - { 0x06e9, 0x0418 }, /* Cyrillic_I И CYRILLIC CAPITAL LETTER I */ - { 0x06ea, 0x0419 }, /* Cyrillic_SHORTI Й CYRILLIC CAPITAL LETTER SHORT I */ - { 0x06eb, 0x041a }, /* Cyrillic_KA К CYRILLIC CAPITAL LETTER KA */ - { 0x06ec, 0x041b }, /* Cyrillic_EL Л CYRILLIC CAPITAL LETTER EL */ - { 0x06ed, 0x041c }, /* Cyrillic_EM М CYRILLIC CAPITAL LETTER EM */ - { 0x06ee, 0x041d }, /* Cyrillic_EN Н CYRILLIC CAPITAL LETTER EN */ - { 0x06ef, 0x041e }, /* Cyrillic_O О CYRILLIC CAPITAL LETTER O */ - { 0x06f0, 0x041f }, /* Cyrillic_PE П CYRILLIC CAPITAL LETTER PE */ - { 0x06f1, 0x042f }, /* Cyrillic_YA Я CYRILLIC CAPITAL LETTER YA */ - { 0x06f2, 0x0420 }, /* Cyrillic_ER Р CYRILLIC CAPITAL LETTER ER */ - { 0x06f3, 0x0421 }, /* Cyrillic_ES С CYRILLIC CAPITAL LETTER ES */ - { 0x06f4, 0x0422 }, /* Cyrillic_TE Т CYRILLIC CAPITAL LETTER TE */ - { 0x06f5, 0x0423 }, /* Cyrillic_U У CYRILLIC CAPITAL LETTER U */ - { 0x06f6, 0x0416 }, /* Cyrillic_ZHE Ж CYRILLIC CAPITAL LETTER ZHE */ - { 0x06f7, 0x0412 }, /* Cyrillic_VE В CYRILLIC CAPITAL LETTER VE */ - { 0x06f8, 0x042c }, /* Cyrillic_SOFTSIGN Ь CYRILLIC CAPITAL LETTER SOFT SIGN */ - { 0x06f9, 0x042b }, /* Cyrillic_YERU Ы CYRILLIC CAPITAL LETTER YERU */ - { 0x06fa, 0x0417 }, /* Cyrillic_ZE З CYRILLIC CAPITAL LETTER ZE */ - { 0x06fb, 0x0428 }, /* Cyrillic_SHA Ш CYRILLIC CAPITAL LETTER SHA */ - { 0x06fc, 0x042d }, /* Cyrillic_E Э CYRILLIC CAPITAL LETTER E */ - { 0x06fd, 0x0429 }, /* Cyrillic_SHCHA Щ CYRILLIC CAPITAL LETTER SHCHA */ - { 0x06fe, 0x0427 }, /* Cyrillic_CHE Ч CYRILLIC CAPITAL LETTER CHE */ - { 0x06ff, 0x042a }, /* Cyrillic_HARDSIGN Ъ CYRILLIC CAPITAL LETTER HARD SIGN */ - { 0x07a1, 0x0386 }, /* Greek_ALPHAaccent Ά GREEK CAPITAL LETTER ALPHA WITH TONOS */ - { 0x07a2, 0x0388 }, /* Greek_EPSILONaccent Έ GREEK CAPITAL LETTER EPSILON WITH TONOS */ - { 0x07a3, 0x0389 }, /* Greek_ETAaccent Ή GREEK CAPITAL LETTER ETA WITH TONOS */ - { 0x07a4, 0x038a }, /* Greek_IOTAaccent Ί GREEK CAPITAL LETTER IOTA WITH TONOS */ - { 0x07a5, 0x03aa }, /* Greek_IOTAdiaeresis Ϊ GREEK CAPITAL LETTER IOTA WITH DIALYTIKA */ - { 0x07a7, 0x038c }, /* Greek_OMICRONaccent Ό GREEK CAPITAL LETTER OMICRON WITH TONOS */ - { 0x07a8, 0x038e }, /* Greek_UPSILONaccent Ύ GREEK CAPITAL LETTER UPSILON WITH TONOS */ - { 0x07a9, 0x03ab }, /* Greek_UPSILONdieresis Ϋ GREEK CAPITAL LETTER UPSILON WITH DIALYTIKA */ - { 0x07ab, 0x038f }, /* Greek_OMEGAaccent Ώ GREEK CAPITAL LETTER OMEGA WITH TONOS */ - { 0x07ae, 0x0385 }, /* Greek_accentdieresis ΅ GREEK DIALYTIKA TONOS */ - { 0x07af, 0x2015 }, /* Greek_horizbar ― HORIZONTAL BAR */ - { 0x07b1, 0x03ac }, /* Greek_alphaaccent ά GREEK SMALL LETTER ALPHA WITH TONOS */ - { 0x07b2, 0x03ad }, /* Greek_epsilonaccent έ GREEK SMALL LETTER EPSILON WITH TONOS */ - { 0x07b3, 0x03ae }, /* Greek_etaaccent ή GREEK SMALL LETTER ETA WITH TONOS */ - { 0x07b4, 0x03af }, /* Greek_iotaaccent ί GREEK SMALL LETTER IOTA WITH TONOS */ - { 0x07b5, 0x03ca }, /* Greek_iotadieresis ϊ GREEK SMALL LETTER IOTA WITH DIALYTIKA */ - { 0x07b6, 0x0390 }, /* Greek_iotaaccentdieresis ΐ GREEK SMALL LETTER IOTA WITH DIALYTIKA AND TONOS */ - { 0x07b7, 0x03cc }, /* Greek_omicronaccent ό GREEK SMALL LETTER OMICRON WITH TONOS */ - { 0x07b8, 0x03cd }, /* Greek_upsilonaccent ύ GREEK SMALL LETTER UPSILON WITH TONOS */ - { 0x07b9, 0x03cb }, /* Greek_upsilondieresis ϋ GREEK SMALL LETTER UPSILON WITH DIALYTIKA */ - { 0x07ba, 0x03b0 }, /* Greek_upsilonaccentdieresis ΰ GREEK SMALL LETTER UPSILON WITH DIALYTIKA AND TONOS */ - { 0x07bb, 0x03ce }, /* Greek_omegaaccent ώ GREEK SMALL LETTER OMEGA WITH TONOS */ - { 0x07c1, 0x0391 }, /* Greek_ALPHA Α GREEK CAPITAL LETTER ALPHA */ - { 0x07c2, 0x0392 }, /* Greek_BETA Β GREEK CAPITAL LETTER BETA */ - { 0x07c3, 0x0393 }, /* Greek_GAMMA Γ GREEK CAPITAL LETTER GAMMA */ - { 0x07c4, 0x0394 }, /* Greek_DELTA Δ GREEK CAPITAL LETTER DELTA */ - { 0x07c5, 0x0395 }, /* Greek_EPSILON Ε GREEK CAPITAL LETTER EPSILON */ - { 0x07c6, 0x0396 }, /* Greek_ZETA Ζ GREEK CAPITAL LETTER ZETA */ - { 0x07c7, 0x0397 }, /* Greek_ETA Η GREEK CAPITAL LETTER ETA */ - { 0x07c8, 0x0398 }, /* Greek_THETA Θ GREEK CAPITAL LETTER THETA */ - { 0x07c9, 0x0399 }, /* Greek_IOTA Ι GREEK CAPITAL LETTER IOTA */ - { 0x07ca, 0x039a }, /* Greek_KAPPA Κ GREEK CAPITAL LETTER KAPPA */ - { 0x07cb, 0x039b }, /* Greek_LAMBDA Λ GREEK CAPITAL LETTER LAMDA */ - { 0x07cc, 0x039c }, /* Greek_MU Μ GREEK CAPITAL LETTER MU */ - { 0x07cd, 0x039d }, /* Greek_NU Ν GREEK CAPITAL LETTER NU */ - { 0x07ce, 0x039e }, /* Greek_XI Ξ GREEK CAPITAL LETTER XI */ - { 0x07cf, 0x039f }, /* Greek_OMICRON Ο GREEK CAPITAL LETTER OMICRON */ - { 0x07d0, 0x03a0 }, /* Greek_PI Π GREEK CAPITAL LETTER PI */ - { 0x07d1, 0x03a1 }, /* Greek_RHO Ρ GREEK CAPITAL LETTER RHO */ - { 0x07d2, 0x03a3 }, /* Greek_SIGMA Σ GREEK CAPITAL LETTER SIGMA */ - { 0x07d4, 0x03a4 }, /* Greek_TAU Τ GREEK CAPITAL LETTER TAU */ - { 0x07d5, 0x03a5 }, /* Greek_UPSILON Υ GREEK CAPITAL LETTER UPSILON */ - { 0x07d6, 0x03a6 }, /* Greek_PHI Φ GREEK CAPITAL LETTER PHI */ - { 0x07d7, 0x03a7 }, /* Greek_CHI Χ GREEK CAPITAL LETTER CHI */ - { 0x07d8, 0x03a8 }, /* Greek_PSI Ψ GREEK CAPITAL LETTER PSI */ - { 0x07d9, 0x03a9 }, /* Greek_OMEGA Ω GREEK CAPITAL LETTER OMEGA */ - { 0x07e1, 0x03b1 }, /* Greek_alpha α GREEK SMALL LETTER ALPHA */ - { 0x07e2, 0x03b2 }, /* Greek_beta β GREEK SMALL LETTER BETA */ - { 0x07e3, 0x03b3 }, /* Greek_gamma γ GREEK SMALL LETTER GAMMA */ - { 0x07e4, 0x03b4 }, /* Greek_delta δ GREEK SMALL LETTER DELTA */ - { 0x07e5, 0x03b5 }, /* Greek_epsilon ε GREEK SMALL LETTER EPSILON */ - { 0x07e6, 0x03b6 }, /* Greek_zeta ζ GREEK SMALL LETTER ZETA */ - { 0x07e7, 0x03b7 }, /* Greek_eta η GREEK SMALL LETTER ETA */ - { 0x07e8, 0x03b8 }, /* Greek_theta θ GREEK SMALL LETTER THETA */ - { 0x07e9, 0x03b9 }, /* Greek_iota ι GREEK SMALL LETTER IOTA */ - { 0x07ea, 0x03ba }, /* Greek_kappa κ GREEK SMALL LETTER KAPPA */ - { 0x07eb, 0x03bb }, /* Greek_lambda λ GREEK SMALL LETTER LAMDA */ - { 0x07ec, 0x03bc }, /* Greek_mu μ GREEK SMALL LETTER MU */ - { 0x07ed, 0x03bd }, /* Greek_nu ν GREEK SMALL LETTER NU */ - { 0x07ee, 0x03be }, /* Greek_xi ξ GREEK SMALL LETTER XI */ - { 0x07ef, 0x03bf }, /* Greek_omicron ο GREEK SMALL LETTER OMICRON */ - { 0x07f0, 0x03c0 }, /* Greek_pi π GREEK SMALL LETTER PI */ - { 0x07f1, 0x03c1 }, /* Greek_rho ρ GREEK SMALL LETTER RHO */ - { 0x07f2, 0x03c3 }, /* Greek_sigma σ GREEK SMALL LETTER SIGMA */ - { 0x07f3, 0x03c2 }, /* Greek_finalsmallsigma ς GREEK SMALL LETTER FINAL SIGMA */ - { 0x07f4, 0x03c4 }, /* Greek_tau τ GREEK SMALL LETTER TAU */ - { 0x07f5, 0x03c5 }, /* Greek_upsilon υ GREEK SMALL LETTER UPSILON */ - { 0x07f6, 0x03c6 }, /* Greek_phi φ GREEK SMALL LETTER PHI */ - { 0x07f7, 0x03c7 }, /* Greek_chi χ GREEK SMALL LETTER CHI */ - { 0x07f8, 0x03c8 }, /* Greek_psi ψ GREEK SMALL LETTER PSI */ - { 0x07f9, 0x03c9 }, /* Greek_omega ω GREEK SMALL LETTER OMEGA */ - { 0x08a1, 0x23b7 }, /* leftradical ⎷ RADICAL SYMBOL BOTTOM */ - { 0x08a2, 0x250c }, /* topleftradical ┌ BOX DRAWINGS LIGHT DOWN AND RIGHT */ - { 0x08a3, 0x2500 }, /* horizconnector ─ BOX DRAWINGS LIGHT HORIZONTAL */ - { 0x08a4, 0x2320 }, /* topintegral ⌠ TOP HALF INTEGRAL */ - { 0x08a5, 0x2321 }, /* botintegral ⌡ BOTTOM HALF INTEGRAL */ - { 0x08a6, 0x2502 }, /* vertconnector │ BOX DRAWINGS LIGHT VERTICAL */ - { 0x08a7, 0x23a1 }, /* topleftsqbracket ⎡ LEFT SQUARE BRACKET UPPER CORNER */ - { 0x08a8, 0x23a3 }, /* botleftsqbracket ⎣ LEFT SQUARE BRACKET LOWER CORNER */ - { 0x08a9, 0x23a4 }, /* toprightsqbracket ⎤ RIGHT SQUARE BRACKET UPPER CORNER */ - { 0x08aa, 0x23a6 }, /* botrightsqbracket ⎦ RIGHT SQUARE BRACKET LOWER CORNER */ - { 0x08ab, 0x239b }, /* topleftparens ⎛ LEFT PARENTHESIS UPPER HOOK */ - { 0x08ac, 0x239d }, /* botleftparens ⎝ LEFT PARENTHESIS LOWER HOOK */ - { 0x08ad, 0x239e }, /* toprightparens ⎞ RIGHT PARENTHESIS UPPER HOOK */ - { 0x08ae, 0x23a0 }, /* botrightparens ⎠ RIGHT PARENTHESIS LOWER HOOK */ - { 0x08af, 0x23a8 }, /* leftmiddlecurlybrace ⎨ LEFT CURLY BRACKET MIDDLE PIECE */ - { 0x08b0, 0x23ac }, /* rightmiddlecurlybrace ⎬ RIGHT CURLY BRACKET MIDDLE PIECE */ - /* 0x08b1 topleftsummation ? ??? */ - /* 0x08b2 botleftsummation ? ??? */ - /* 0x08b3 topvertsummationconnector ? ??? */ - /* 0x08b4 botvertsummationconnector ? ??? */ - /* 0x08b5 toprightsummation ? ??? */ - /* 0x08b6 botrightsummation ? ??? */ - /* 0x08b7 rightmiddlesummation ? ??? */ - { 0x08bc, 0x2264 }, /* lessthanequal ≤ LESS-THAN OR EQUAL TO */ - { 0x08bd, 0x2260 }, /* notequal ≠ NOT EQUAL TO */ - { 0x08be, 0x2265 }, /* greaterthanequal ≥ GREATER-THAN OR EQUAL TO */ - { 0x08bf, 0x222b }, /* integral ∫ INTEGRAL */ - { 0x08c0, 0x2234 }, /* therefore ∴ THEREFORE */ - { 0x08c1, 0x221d }, /* variation ∝ PROPORTIONAL TO */ - { 0x08c2, 0x221e }, /* infinity ∞ INFINITY */ - { 0x08c5, 0x2207 }, /* nabla ∇ NABLA */ - { 0x08c8, 0x223c }, /* approximate ∼ TILDE OPERATOR */ - { 0x08c9, 0x2243 }, /* similarequal ≃ ASYMPTOTICALLY EQUAL TO */ - { 0x08cd, 0x21d4 }, /* ifonlyif ⇔ LEFT RIGHT DOUBLE ARROW */ - { 0x08ce, 0x21d2 }, /* implies ⇒ RIGHTWARDS DOUBLE ARROW */ - { 0x08cf, 0x2261 }, /* identical ≡ IDENTICAL TO */ - { 0x08d6, 0x221a }, /* radical √ SQUARE ROOT */ - { 0x08da, 0x2282 }, /* includedin ⊂ SUBSET OF */ - { 0x08db, 0x2283 }, /* includes ⊃ SUPERSET OF */ - { 0x08dc, 0x2229 }, /* intersection ∩ INTERSECTION */ - { 0x08dd, 0x222a }, /* union ∪ UNION */ - { 0x08de, 0x2227 }, /* logicaland ∧ LOGICAL AND */ - { 0x08df, 0x2228 }, /* logicalor ∨ LOGICAL OR */ - { 0x08ef, 0x2202 }, /* partialderivative ∂ PARTIAL DIFFERENTIAL */ - { 0x08f6, 0x0192 }, /* function ƒ LATIN SMALL LETTER F WITH HOOK */ - { 0x08fb, 0x2190 }, /* leftarrow ← LEFTWARDS ARROW */ - { 0x08fc, 0x2191 }, /* uparrow ↑ UPWARDS ARROW */ - { 0x08fd, 0x2192 }, /* rightarrow → RIGHTWARDS ARROW */ - { 0x08fe, 0x2193 }, /* downarrow ↓ DOWNWARDS ARROW */ - { 0x09df, 0x2422 }, /* blank ␢ BLANK SYMBOL */ - { 0x09e0, 0x25c6 }, /* soliddiamond ◆ BLACK DIAMOND */ - { 0x09e1, 0x2592 }, /* checkerboard ▒ MEDIUM SHADE */ - { 0x09e2, 0x2409 }, /* ht ␉ SYMBOL FOR HORIZONTAL TABULATION */ - { 0x09e3, 0x240c }, /* ff ␌ SYMBOL FOR FORM FEED */ - { 0x09e4, 0x240d }, /* cr ␍ SYMBOL FOR CARRIAGE RETURN */ - { 0x09e5, 0x240a }, /* lf ␊ SYMBOL FOR LINE FEED */ - { 0x09e8, 0x2424 }, /* nl ␤ SYMBOL FOR NEWLINE */ - { 0x09e9, 0x240b }, /* vt ␋ SYMBOL FOR VERTICAL TABULATION */ - { 0x09ea, 0x2518 }, /* lowrightcorner ┘ BOX DRAWINGS LIGHT UP AND LEFT */ - { 0x09eb, 0x2510 }, /* uprightcorner ┐ BOX DRAWINGS LIGHT DOWN AND LEFT */ - { 0x09ec, 0x250c }, /* upleftcorner ┌ BOX DRAWINGS LIGHT DOWN AND RIGHT */ - { 0x09ed, 0x2514 }, /* lowleftcorner └ BOX DRAWINGS LIGHT UP AND RIGHT */ - { 0x09ee, 0x253c }, /* crossinglines ┼ BOX DRAWINGS LIGHT VERTICAL AND HORIZONTAL */ - { 0x09ef, 0x23ba }, /* horizlinescan1 ⎺ HORIZONTAL SCAN LINE-1 */ - { 0x09f0, 0x23bb }, /* horizlinescan3 ⎻ HORIZONTAL SCAN LINE-3 */ - { 0x09f1, 0x2500 }, /* horizlinescan5 ─ BOX DRAWINGS LIGHT HORIZONTAL */ - { 0x09f2, 0x23bc }, /* horizlinescan7 ⎼ HORIZONTAL SCAN LINE-7 */ - { 0x09f3, 0x23bd }, /* horizlinescan9 ⎽ HORIZONTAL SCAN LINE-9 */ - { 0x09f4, 0x251c }, /* leftt ├ BOX DRAWINGS LIGHT VERTICAL AND RIGHT */ - { 0x09f5, 0x2524 }, /* rightt ┤ BOX DRAWINGS LIGHT VERTICAL AND LEFT */ - { 0x09f6, 0x2534 }, /* bott ┴ BOX DRAWINGS LIGHT UP AND HORIZONTAL */ - { 0x09f7, 0x252c }, /* topt ┬ BOX DRAWINGS LIGHT DOWN AND HORIZONTAL */ - { 0x09f8, 0x2502 }, /* vertbar │ BOX DRAWINGS LIGHT VERTICAL */ - { 0x0aa1, 0x2003 }, /* emspace   EM SPACE */ - { 0x0aa2, 0x2002 }, /* enspace   EN SPACE */ - { 0x0aa3, 0x2004 }, /* em3space   THREE-PER-EM SPACE */ - { 0x0aa4, 0x2005 }, /* em4space   FOUR-PER-EM SPACE */ - { 0x0aa5, 0x2007 }, /* digitspace   FIGURE SPACE */ - { 0x0aa6, 0x2008 }, /* punctspace   PUNCTUATION SPACE */ - { 0x0aa7, 0x2009 }, /* thinspace   THIN SPACE */ - { 0x0aa8, 0x200a }, /* hairspace   HAIR SPACE */ - { 0x0aa9, 0x2014 }, /* emdash — EM DASH */ - { 0x0aaa, 0x2013 }, /* endash – EN DASH */ - { 0x0aac, 0x2423 }, /* signifblank ␣ OPEN BOX */ - { 0x0aae, 0x2026 }, /* ellipsis … HORIZONTAL ELLIPSIS */ - { 0x0aaf, 0x2025 }, /* doubbaselinedot ‥ TWO DOT LEADER */ - { 0x0ab0, 0x2153 }, /* onethird ⅓ VULGAR FRACTION ONE THIRD */ - { 0x0ab1, 0x2154 }, /* twothirds ⅔ VULGAR FRACTION TWO THIRDS */ - { 0x0ab2, 0x2155 }, /* onefifth ⅕ VULGAR FRACTION ONE FIFTH */ - { 0x0ab3, 0x2156 }, /* twofifths ⅖ VULGAR FRACTION TWO FIFTHS */ - { 0x0ab4, 0x2157 }, /* threefifths ⅗ VULGAR FRACTION THREE FIFTHS */ - { 0x0ab5, 0x2158 }, /* fourfifths ⅘ VULGAR FRACTION FOUR FIFTHS */ - { 0x0ab6, 0x2159 }, /* onesixth ⅙ VULGAR FRACTION ONE SIXTH */ - { 0x0ab7, 0x215a }, /* fivesixths ⅚ VULGAR FRACTION FIVE SIXTHS */ - { 0x0ab8, 0x2105 }, /* careof ℅ CARE OF */ - { 0x0abb, 0x2012 }, /* figdash ‒ FIGURE DASH */ - { 0x0abc, 0x2329 }, /* leftanglebracket 〈 LEFT-POINTING ANGLE BRACKET */ - { 0x0abd, 0x002e }, /* decimalpoint . FULL STOP */ - { 0x0abe, 0x232a }, /* rightanglebracket 〉 RIGHT-POINTING ANGLE BRACKET */ - /* 0x0abf marker ? ??? */ - { 0x0ac3, 0x215b }, /* oneeighth ⅛ VULGAR FRACTION ONE EIGHTH */ - { 0x0ac4, 0x215c }, /* threeeighths ⅜ VULGAR FRACTION THREE EIGHTHS */ - { 0x0ac5, 0x215d }, /* fiveeighths ⅝ VULGAR FRACTION FIVE EIGHTHS */ - { 0x0ac6, 0x215e }, /* seveneighths ⅞ VULGAR FRACTION SEVEN EIGHTHS */ - { 0x0ac9, 0x2122 }, /* trademark ™ TRADE MARK SIGN */ - { 0x0aca, 0x2613 }, /* signaturemark ☓ SALTIRE */ - /* 0x0acb trademarkincircle ? ??? */ - { 0x0acc, 0x25c1 }, /* leftopentriangle ◁ WHITE LEFT-POINTING TRIANGLE */ - { 0x0acd, 0x25b7 }, /* rightopentriangle ▷ WHITE RIGHT-POINTING TRIANGLE */ - { 0x0ace, 0x25cb }, /* emopencircle ○ WHITE CIRCLE */ - { 0x0acf, 0x25af }, /* emopenrectangle ▯ WHITE VERTICAL RECTANGLE */ - { 0x0ad0, 0x2018 }, /* leftsinglequotemark ‘ LEFT SINGLE QUOTATION MARK */ - { 0x0ad1, 0x2019 }, /* rightsinglequotemark ’ RIGHT SINGLE QUOTATION MARK */ - { 0x0ad2, 0x201c }, /* leftdoublequotemark “ LEFT DOUBLE QUOTATION MARK */ - { 0x0ad3, 0x201d }, /* rightdoublequotemark ” RIGHT DOUBLE QUOTATION MARK */ - { 0x0ad4, 0x211e }, /* prescription ℞ PRESCRIPTION TAKE */ - /* 0x0ad5 permille ? ??? */ - { 0x0ad6, 0x2032 }, /* minutes ′ PRIME */ - { 0x0ad7, 0x2033 }, /* seconds ″ DOUBLE PRIME */ - { 0x0ad9, 0x271d }, /* latincross ✝ LATIN CROSS */ - /* 0x0ada hexagram ? ??? */ - { 0x0adb, 0x25ac }, /* filledrectbullet ▬ BLACK RECTANGLE */ - { 0x0adc, 0x25c0 }, /* filledlefttribullet ◀ BLACK LEFT-POINTING TRIANGLE */ - { 0x0add, 0x25b6 }, /* filledrighttribullet ▶ BLACK RIGHT-POINTING TRIANGLE */ - { 0x0ade, 0x25cf }, /* emfilledcircle ● BLACK CIRCLE */ - { 0x0adf, 0x25ae }, /* emfilledrect ▮ BLACK VERTICAL RECTANGLE */ - { 0x0ae0, 0x25e6 }, /* enopencircbullet ◦ WHITE BULLET */ - { 0x0ae1, 0x25ab }, /* enopensquarebullet ▫ WHITE SMALL SQUARE */ - { 0x0ae2, 0x25ad }, /* openrectbullet ▭ WHITE RECTANGLE */ - { 0x0ae3, 0x25b3 }, /* opentribulletup △ WHITE UP-POINTING TRIANGLE */ - { 0x0ae4, 0x25bd }, /* opentribulletdown ▽ WHITE DOWN-POINTING TRIANGLE */ - { 0x0ae5, 0x2606 }, /* openstar ☆ WHITE STAR */ - { 0x0ae6, 0x2022 }, /* enfilledcircbullet • BULLET */ - { 0x0ae7, 0x25aa }, /* enfilledsqbullet ▪ BLACK SMALL SQUARE */ - { 0x0ae8, 0x25b2 }, /* filledtribulletup ▲ BLACK UP-POINTING TRIANGLE */ - { 0x0ae9, 0x25bc }, /* filledtribulletdown ▼ BLACK DOWN-POINTING TRIANGLE */ - { 0x0aea, 0x261c }, /* leftpointer ☜ WHITE LEFT POINTING INDEX */ - { 0x0aeb, 0x261e }, /* rightpointer ☞ WHITE RIGHT POINTING INDEX */ - { 0x0aec, 0x2663 }, /* club ♣ BLACK CLUB SUIT */ - { 0x0aed, 0x2666 }, /* diamond ♦ BLACK DIAMOND SUIT */ - { 0x0aee, 0x2665 }, /* heart ♥ BLACK HEART SUIT */ - { 0x0af0, 0x2720 }, /* maltesecross ✠ MALTESE CROSS */ - { 0x0af1, 0x2020 }, /* dagger † DAGGER */ - { 0x0af2, 0x2021 }, /* doubledagger ‡ DOUBLE DAGGER */ - { 0x0af3, 0x2713 }, /* checkmark ✓ CHECK MARK */ - { 0x0af4, 0x2717 }, /* ballotcross ✗ BALLOT X */ - { 0x0af5, 0x266f }, /* musicalsharp ♯ MUSIC SHARP SIGN */ - { 0x0af6, 0x266d }, /* musicalflat ♭ MUSIC FLAT SIGN */ - { 0x0af7, 0x2642 }, /* malesymbol ♂ MALE SIGN */ - { 0x0af8, 0x2640 }, /* femalesymbol ♀ FEMALE SIGN */ - { 0x0af9, 0x260e }, /* telephone ☎ BLACK TELEPHONE */ - { 0x0afa, 0x2315 }, /* telephonerecorder ⌕ TELEPHONE RECORDER */ - { 0x0afb, 0x2117 }, /* phonographcopyright ℗ SOUND RECORDING COPYRIGHT */ - { 0x0afc, 0x2038 }, /* caret ‸ CARET */ - { 0x0afd, 0x201a }, /* singlelowquotemark ‚ SINGLE LOW-9 QUOTATION MARK */ - { 0x0afe, 0x201e }, /* doublelowquotemark „ DOUBLE LOW-9 QUOTATION MARK */ - /* 0x0aff cursor ? ??? */ - { 0x0ba3, 0x003c }, /* leftcaret < LESS-THAN SIGN */ - { 0x0ba6, 0x003e }, /* rightcaret > GREATER-THAN SIGN */ - { 0x0ba8, 0x2228 }, /* downcaret ∨ LOGICAL OR */ - { 0x0ba9, 0x2227 }, /* upcaret ∧ LOGICAL AND */ - { 0x0bc0, 0x00af }, /* overbar ¯ MACRON */ - { 0x0bc2, 0x22a5 }, /* downtack ⊥ UP TACK */ - { 0x0bc3, 0x2229 }, /* upshoe ∩ INTERSECTION */ - { 0x0bc4, 0x230a }, /* downstile ⌊ LEFT FLOOR */ - { 0x0bc6, 0x005f }, /* underbar _ LOW LINE */ - { 0x0bca, 0x2218 }, /* jot ∘ RING OPERATOR */ - { 0x0bcc, 0x2395 }, /* quad ⎕ APL FUNCTIONAL SYMBOL QUAD */ - { 0x0bce, 0x22a4 }, /* uptack ⊤ DOWN TACK */ - { 0x0bcf, 0x25cb }, /* circle ○ WHITE CIRCLE */ - { 0x0bd3, 0x2308 }, /* upstile ⌈ LEFT CEILING */ - { 0x0bd6, 0x222a }, /* downshoe ∪ UNION */ - { 0x0bd8, 0x2283 }, /* rightshoe ⊃ SUPERSET OF */ - { 0x0bda, 0x2282 }, /* leftshoe ⊂ SUBSET OF */ - { 0x0bdc, 0x22a2 }, /* lefttack ⊢ RIGHT TACK */ - { 0x0bfc, 0x22a3 }, /* righttack ⊣ LEFT TACK */ - { 0x0cdf, 0x2017 }, /* hebrew_doublelowline ‗ DOUBLE LOW LINE */ - { 0x0ce0, 0x05d0 }, /* hebrew_aleph א HEBREW LETTER ALEF */ - { 0x0ce1, 0x05d1 }, /* hebrew_bet ב HEBREW LETTER BET */ - { 0x0ce2, 0x05d2 }, /* hebrew_gimel ג HEBREW LETTER GIMEL */ - { 0x0ce3, 0x05d3 }, /* hebrew_dalet ד HEBREW LETTER DALET */ - { 0x0ce4, 0x05d4 }, /* hebrew_he ה HEBREW LETTER HE */ - { 0x0ce5, 0x05d5 }, /* hebrew_waw ו HEBREW LETTER VAV */ - { 0x0ce6, 0x05d6 }, /* hebrew_zain ז HEBREW LETTER ZAYIN */ - { 0x0ce7, 0x05d7 }, /* hebrew_chet ח HEBREW LETTER HET */ - { 0x0ce8, 0x05d8 }, /* hebrew_tet ט HEBREW LETTER TET */ - { 0x0ce9, 0x05d9 }, /* hebrew_yod י HEBREW LETTER YOD */ - { 0x0cea, 0x05da }, /* hebrew_finalkaph ך HEBREW LETTER FINAL KAF */ - { 0x0ceb, 0x05db }, /* hebrew_kaph כ HEBREW LETTER KAF */ - { 0x0cec, 0x05dc }, /* hebrew_lamed ל HEBREW LETTER LAMED */ - { 0x0ced, 0x05dd }, /* hebrew_finalmem ם HEBREW LETTER FINAL MEM */ - { 0x0cee, 0x05de }, /* hebrew_mem מ HEBREW LETTER MEM */ - { 0x0cef, 0x05df }, /* hebrew_finalnun ן HEBREW LETTER FINAL NUN */ - { 0x0cf0, 0x05e0 }, /* hebrew_nun נ HEBREW LETTER NUN */ - { 0x0cf1, 0x05e1 }, /* hebrew_samech ס HEBREW LETTER SAMEKH */ - { 0x0cf2, 0x05e2 }, /* hebrew_ayin ע HEBREW LETTER AYIN */ - { 0x0cf3, 0x05e3 }, /* hebrew_finalpe ף HEBREW LETTER FINAL PE */ - { 0x0cf4, 0x05e4 }, /* hebrew_pe פ HEBREW LETTER PE */ - { 0x0cf5, 0x05e5 }, /* hebrew_finalzade ץ HEBREW LETTER FINAL TSADI */ - { 0x0cf6, 0x05e6 }, /* hebrew_zade צ HEBREW LETTER TSADI */ - { 0x0cf7, 0x05e7 }, /* hebrew_qoph ק HEBREW LETTER QOF */ - { 0x0cf8, 0x05e8 }, /* hebrew_resh ר HEBREW LETTER RESH */ - { 0x0cf9, 0x05e9 }, /* hebrew_shin ש HEBREW LETTER SHIN */ - { 0x0cfa, 0x05ea }, /* hebrew_taw ת HEBREW LETTER TAV */ - { 0x0da1, 0x0e01 }, /* Thai_kokai ก THAI CHARACTER KO KAI */ - { 0x0da2, 0x0e02 }, /* Thai_khokhai ข THAI CHARACTER KHO KHAI */ - { 0x0da3, 0x0e03 }, /* Thai_khokhuat ฃ THAI CHARACTER KHO KHUAT */ - { 0x0da4, 0x0e04 }, /* Thai_khokhwai ค THAI CHARACTER KHO KHWAI */ - { 0x0da5, 0x0e05 }, /* Thai_khokhon ฅ THAI CHARACTER KHO KHON */ - { 0x0da6, 0x0e06 }, /* Thai_khorakhang ฆ THAI CHARACTER KHO RAKHANG */ - { 0x0da7, 0x0e07 }, /* Thai_ngongu ง THAI CHARACTER NGO NGU */ - { 0x0da8, 0x0e08 }, /* Thai_chochan จ THAI CHARACTER CHO CHAN */ - { 0x0da9, 0x0e09 }, /* Thai_choching ฉ THAI CHARACTER CHO CHING */ - { 0x0daa, 0x0e0a }, /* Thai_chochang ช THAI CHARACTER CHO CHANG */ - { 0x0dab, 0x0e0b }, /* Thai_soso ซ THAI CHARACTER SO SO */ - { 0x0dac, 0x0e0c }, /* Thai_chochoe ฌ THAI CHARACTER CHO CHOE */ - { 0x0dad, 0x0e0d }, /* Thai_yoying ญ THAI CHARACTER YO YING */ - { 0x0dae, 0x0e0e }, /* Thai_dochada ฎ THAI CHARACTER DO CHADA */ - { 0x0daf, 0x0e0f }, /* Thai_topatak ฏ THAI CHARACTER TO PATAK */ - { 0x0db0, 0x0e10 }, /* Thai_thothan ฐ THAI CHARACTER THO THAN */ - { 0x0db1, 0x0e11 }, /* Thai_thonangmontho ฑ THAI CHARACTER THO NANGMONTHO */ - { 0x0db2, 0x0e12 }, /* Thai_thophuthao ฒ THAI CHARACTER THO PHUTHAO */ - { 0x0db3, 0x0e13 }, /* Thai_nonen ณ THAI CHARACTER NO NEN */ - { 0x0db4, 0x0e14 }, /* Thai_dodek ด THAI CHARACTER DO DEK */ - { 0x0db5, 0x0e15 }, /* Thai_totao ต THAI CHARACTER TO TAO */ - { 0x0db6, 0x0e16 }, /* Thai_thothung ถ THAI CHARACTER THO THUNG */ - { 0x0db7, 0x0e17 }, /* Thai_thothahan ท THAI CHARACTER THO THAHAN */ - { 0x0db8, 0x0e18 }, /* Thai_thothong ธ THAI CHARACTER THO THONG */ - { 0x0db9, 0x0e19 }, /* Thai_nonu น THAI CHARACTER NO NU */ - { 0x0dba, 0x0e1a }, /* Thai_bobaimai บ THAI CHARACTER BO BAIMAI */ - { 0x0dbb, 0x0e1b }, /* Thai_popla ป THAI CHARACTER PO PLA */ - { 0x0dbc, 0x0e1c }, /* Thai_phophung ผ THAI CHARACTER PHO PHUNG */ - { 0x0dbd, 0x0e1d }, /* Thai_fofa ฝ THAI CHARACTER FO FA */ - { 0x0dbe, 0x0e1e }, /* Thai_phophan พ THAI CHARACTER PHO PHAN */ - { 0x0dbf, 0x0e1f }, /* Thai_fofan ฟ THAI CHARACTER FO FAN */ - { 0x0dc0, 0x0e20 }, /* Thai_phosamphao ภ THAI CHARACTER PHO SAMPHAO */ - { 0x0dc1, 0x0e21 }, /* Thai_moma ม THAI CHARACTER MO MA */ - { 0x0dc2, 0x0e22 }, /* Thai_yoyak ย THAI CHARACTER YO YAK */ - { 0x0dc3, 0x0e23 }, /* Thai_rorua ร THAI CHARACTER RO RUA */ - { 0x0dc4, 0x0e24 }, /* Thai_ru ฤ THAI CHARACTER RU */ - { 0x0dc5, 0x0e25 }, /* Thai_loling ล THAI CHARACTER LO LING */ - { 0x0dc6, 0x0e26 }, /* Thai_lu ฦ THAI CHARACTER LU */ - { 0x0dc7, 0x0e27 }, /* Thai_wowaen ว THAI CHARACTER WO WAEN */ - { 0x0dc8, 0x0e28 }, /* Thai_sosala ศ THAI CHARACTER SO SALA */ - { 0x0dc9, 0x0e29 }, /* Thai_sorusi ษ THAI CHARACTER SO RUSI */ - { 0x0dca, 0x0e2a }, /* Thai_sosua ส THAI CHARACTER SO SUA */ - { 0x0dcb, 0x0e2b }, /* Thai_hohip ห THAI CHARACTER HO HIP */ - { 0x0dcc, 0x0e2c }, /* Thai_lochula ฬ THAI CHARACTER LO CHULA */ - { 0x0dcd, 0x0e2d }, /* Thai_oang อ THAI CHARACTER O ANG */ - { 0x0dce, 0x0e2e }, /* Thai_honokhuk ฮ THAI CHARACTER HO NOKHUK */ - { 0x0dcf, 0x0e2f }, /* Thai_paiyannoi ฯ THAI CHARACTER PAIYANNOI */ - { 0x0dd0, 0x0e30 }, /* Thai_saraa ะ THAI CHARACTER SARA A */ - { 0x0dd1, 0x0e31 }, /* Thai_maihanakat ั THAI CHARACTER MAI HAN-AKAT */ - { 0x0dd2, 0x0e32 }, /* Thai_saraaa า THAI CHARACTER SARA AA */ - { 0x0dd3, 0x0e33 }, /* Thai_saraam ำ THAI CHARACTER SARA AM */ - { 0x0dd4, 0x0e34 }, /* Thai_sarai ิ THAI CHARACTER SARA I */ - { 0x0dd5, 0x0e35 }, /* Thai_saraii ี THAI CHARACTER SARA II */ - { 0x0dd6, 0x0e36 }, /* Thai_saraue ึ THAI CHARACTER SARA UE */ - { 0x0dd7, 0x0e37 }, /* Thai_sarauee ื THAI CHARACTER SARA UEE */ - { 0x0dd8, 0x0e38 }, /* Thai_sarau ุ THAI CHARACTER SARA U */ - { 0x0dd9, 0x0e39 }, /* Thai_sarauu ู THAI CHARACTER SARA UU */ - { 0x0dda, 0x0e3a }, /* Thai_phinthu ฺ THAI CHARACTER PHINTHU */ - { 0x0dde, 0x0e3e }, /* Thai_maihanakat_maitho ฾ ??? */ - { 0x0ddf, 0x0e3f }, /* Thai_baht ฿ THAI CURRENCY SYMBOL BAHT */ - { 0x0de0, 0x0e40 }, /* Thai_sarae เ THAI CHARACTER SARA E */ - { 0x0de1, 0x0e41 }, /* Thai_saraae แ THAI CHARACTER SARA AE */ - { 0x0de2, 0x0e42 }, /* Thai_sarao โ THAI CHARACTER SARA O */ - { 0x0de3, 0x0e43 }, /* Thai_saraaimaimuan ใ THAI CHARACTER SARA AI MAIMUAN */ - { 0x0de4, 0x0e44 }, /* Thai_saraaimaimalai ไ THAI CHARACTER SARA AI MAIMALAI */ - { 0x0de5, 0x0e45 }, /* Thai_lakkhangyao ๅ THAI CHARACTER LAKKHANGYAO */ - { 0x0de6, 0x0e46 }, /* Thai_maiyamok ๆ THAI CHARACTER MAIYAMOK */ - { 0x0de7, 0x0e47 }, /* Thai_maitaikhu ็ THAI CHARACTER MAITAIKHU */ - { 0x0de8, 0x0e48 }, /* Thai_maiek ่ THAI CHARACTER MAI EK */ - { 0x0de9, 0x0e49 }, /* Thai_maitho ้ THAI CHARACTER MAI THO */ - { 0x0dea, 0x0e4a }, /* Thai_maitri ๊ THAI CHARACTER MAI TRI */ - { 0x0deb, 0x0e4b }, /* Thai_maichattawa ๋ THAI CHARACTER MAI CHATTAWA */ - { 0x0dec, 0x0e4c }, /* Thai_thanthakhat ์ THAI CHARACTER THANTHAKHAT */ - { 0x0ded, 0x0e4d }, /* Thai_nikhahit ํ THAI CHARACTER NIKHAHIT */ - { 0x0df0, 0x0e50 }, /* Thai_leksun ๐ THAI DIGIT ZERO */ - { 0x0df1, 0x0e51 }, /* Thai_leknung ๑ THAI DIGIT ONE */ - { 0x0df2, 0x0e52 }, /* Thai_leksong ๒ THAI DIGIT TWO */ - { 0x0df3, 0x0e53 }, /* Thai_leksam ๓ THAI DIGIT THREE */ - { 0x0df4, 0x0e54 }, /* Thai_leksi ๔ THAI DIGIT FOUR */ - { 0x0df5, 0x0e55 }, /* Thai_lekha ๕ THAI DIGIT FIVE */ - { 0x0df6, 0x0e56 }, /* Thai_lekhok ๖ THAI DIGIT SIX */ - { 0x0df7, 0x0e57 }, /* Thai_lekchet ๗ THAI DIGIT SEVEN */ - { 0x0df8, 0x0e58 }, /* Thai_lekpaet ๘ THAI DIGIT EIGHT */ - { 0x0df9, 0x0e59 }, /* Thai_lekkao ๙ THAI DIGIT NINE */ - { 0x0ea1, 0x3131 }, /* Hangul_Kiyeog ㄱ HANGUL LETTER KIYEOK */ - { 0x0ea2, 0x3132 }, /* Hangul_SsangKiyeog ㄲ HANGUL LETTER SSANGKIYEOK */ - { 0x0ea3, 0x3133 }, /* Hangul_KiyeogSios ㄳ HANGUL LETTER KIYEOK-SIOS */ - { 0x0ea4, 0x3134 }, /* Hangul_Nieun ㄴ HANGUL LETTER NIEUN */ - { 0x0ea5, 0x3135 }, /* Hangul_NieunJieuj ㄵ HANGUL LETTER NIEUN-CIEUC */ - { 0x0ea6, 0x3136 }, /* Hangul_NieunHieuh ㄶ HANGUL LETTER NIEUN-HIEUH */ - { 0x0ea7, 0x3137 }, /* Hangul_Dikeud ㄷ HANGUL LETTER TIKEUT */ - { 0x0ea8, 0x3138 }, /* Hangul_SsangDikeud ㄸ HANGUL LETTER SSANGTIKEUT */ - { 0x0ea9, 0x3139 }, /* Hangul_Rieul ㄹ HANGUL LETTER RIEUL */ - { 0x0eaa, 0x313a }, /* Hangul_RieulKiyeog ㄺ HANGUL LETTER RIEUL-KIYEOK */ - { 0x0eab, 0x313b }, /* Hangul_RieulMieum ㄻ HANGUL LETTER RIEUL-MIEUM */ - { 0x0eac, 0x313c }, /* Hangul_RieulPieub ㄼ HANGUL LETTER RIEUL-PIEUP */ - { 0x0ead, 0x313d }, /* Hangul_RieulSios ㄽ HANGUL LETTER RIEUL-SIOS */ - { 0x0eae, 0x313e }, /* Hangul_RieulTieut ㄾ HANGUL LETTER RIEUL-THIEUTH */ - { 0x0eaf, 0x313f }, /* Hangul_RieulPhieuf ㄿ HANGUL LETTER RIEUL-PHIEUPH */ - { 0x0eb0, 0x3140 }, /* Hangul_RieulHieuh ㅀ HANGUL LETTER RIEUL-HIEUH */ - { 0x0eb1, 0x3141 }, /* Hangul_Mieum ㅁ HANGUL LETTER MIEUM */ - { 0x0eb2, 0x3142 }, /* Hangul_Pieub ㅂ HANGUL LETTER PIEUP */ - { 0x0eb3, 0x3143 }, /* Hangul_SsangPieub ㅃ HANGUL LETTER SSANGPIEUP */ - { 0x0eb4, 0x3144 }, /* Hangul_PieubSios ㅄ HANGUL LETTER PIEUP-SIOS */ - { 0x0eb5, 0x3145 }, /* Hangul_Sios ㅅ HANGUL LETTER SIOS */ - { 0x0eb6, 0x3146 }, /* Hangul_SsangSios ㅆ HANGUL LETTER SSANGSIOS */ - { 0x0eb7, 0x3147 }, /* Hangul_Ieung ㅇ HANGUL LETTER IEUNG */ - { 0x0eb8, 0x3148 }, /* Hangul_Jieuj ㅈ HANGUL LETTER CIEUC */ - { 0x0eb9, 0x3149 }, /* Hangul_SsangJieuj ㅉ HANGUL LETTER SSANGCIEUC */ - { 0x0eba, 0x314a }, /* Hangul_Cieuc ㅊ HANGUL LETTER CHIEUCH */ - { 0x0ebb, 0x314b }, /* Hangul_Khieuq ㅋ HANGUL LETTER KHIEUKH */ - { 0x0ebc, 0x314c }, /* Hangul_Tieut ㅌ HANGUL LETTER THIEUTH */ - { 0x0ebd, 0x314d }, /* Hangul_Phieuf ㅍ HANGUL LETTER PHIEUPH */ - { 0x0ebe, 0x314e }, /* Hangul_Hieuh ㅎ HANGUL LETTER HIEUH */ - { 0x0ebf, 0x314f }, /* Hangul_A ㅏ HANGUL LETTER A */ - { 0x0ec0, 0x3150 }, /* Hangul_AE ㅐ HANGUL LETTER AE */ - { 0x0ec1, 0x3151 }, /* Hangul_YA ㅑ HANGUL LETTER YA */ - { 0x0ec2, 0x3152 }, /* Hangul_YAE ㅒ HANGUL LETTER YAE */ - { 0x0ec3, 0x3153 }, /* Hangul_EO ㅓ HANGUL LETTER EO */ - { 0x0ec4, 0x3154 }, /* Hangul_E ㅔ HANGUL LETTER E */ - { 0x0ec5, 0x3155 }, /* Hangul_YEO ㅕ HANGUL LETTER YEO */ - { 0x0ec6, 0x3156 }, /* Hangul_YE ㅖ HANGUL LETTER YE */ - { 0x0ec7, 0x3157 }, /* Hangul_O ㅗ HANGUL LETTER O */ - { 0x0ec8, 0x3158 }, /* Hangul_WA ㅘ HANGUL LETTER WA */ - { 0x0ec9, 0x3159 }, /* Hangul_WAE ㅙ HANGUL LETTER WAE */ - { 0x0eca, 0x315a }, /* Hangul_OE ㅚ HANGUL LETTER OE */ - { 0x0ecb, 0x315b }, /* Hangul_YO ㅛ HANGUL LETTER YO */ - { 0x0ecc, 0x315c }, /* Hangul_U ㅜ HANGUL LETTER U */ - { 0x0ecd, 0x315d }, /* Hangul_WEO ㅝ HANGUL LETTER WEO */ - { 0x0ece, 0x315e }, /* Hangul_WE ㅞ HANGUL LETTER WE */ - { 0x0ecf, 0x315f }, /* Hangul_WI ㅟ HANGUL LETTER WI */ - { 0x0ed0, 0x3160 }, /* Hangul_YU ㅠ HANGUL LETTER YU */ - { 0x0ed1, 0x3161 }, /* Hangul_EU ㅡ HANGUL LETTER EU */ - { 0x0ed2, 0x3162 }, /* Hangul_YI ㅢ HANGUL LETTER YI */ - { 0x0ed3, 0x3163 }, /* Hangul_I ㅣ HANGUL LETTER I */ - { 0x0ed4, 0x11a8 }, /* Hangul_J_Kiyeog ᆨ HANGUL JONGSEONG KIYEOK */ - { 0x0ed5, 0x11a9 }, /* Hangul_J_SsangKiyeog ᆩ HANGUL JONGSEONG SSANGKIYEOK */ - { 0x0ed6, 0x11aa }, /* Hangul_J_KiyeogSios ᆪ HANGUL JONGSEONG KIYEOK-SIOS */ - { 0x0ed7, 0x11ab }, /* Hangul_J_Nieun ᆫ HANGUL JONGSEONG NIEUN */ - { 0x0ed8, 0x11ac }, /* Hangul_J_NieunJieuj ᆬ HANGUL JONGSEONG NIEUN-CIEUC */ - { 0x0ed9, 0x11ad }, /* Hangul_J_NieunHieuh ᆭ HANGUL JONGSEONG NIEUN-HIEUH */ - { 0x0eda, 0x11ae }, /* Hangul_J_Dikeud ᆮ HANGUL JONGSEONG TIKEUT */ - { 0x0edb, 0x11af }, /* Hangul_J_Rieul ᆯ HANGUL JONGSEONG RIEUL */ - { 0x0edc, 0x11b0 }, /* Hangul_J_RieulKiyeog ᆰ HANGUL JONGSEONG RIEUL-KIYEOK */ - { 0x0edd, 0x11b1 }, /* Hangul_J_RieulMieum ᆱ HANGUL JONGSEONG RIEUL-MIEUM */ - { 0x0ede, 0x11b2 }, /* Hangul_J_RieulPieub ᆲ HANGUL JONGSEONG RIEUL-PIEUP */ - { 0x0edf, 0x11b3 }, /* Hangul_J_RieulSios ᆳ HANGUL JONGSEONG RIEUL-SIOS */ - { 0x0ee0, 0x11b4 }, /* Hangul_J_RieulTieut ᆴ HANGUL JONGSEONG RIEUL-THIEUTH */ - { 0x0ee1, 0x11b5 }, /* Hangul_J_RieulPhieuf ᆵ HANGUL JONGSEONG RIEUL-PHIEUPH */ - { 0x0ee2, 0x11b6 }, /* Hangul_J_RieulHieuh ᆶ HANGUL JONGSEONG RIEUL-HIEUH */ - { 0x0ee3, 0x11b7 }, /* Hangul_J_Mieum ᆷ HANGUL JONGSEONG MIEUM */ - { 0x0ee4, 0x11b8 }, /* Hangul_J_Pieub ᆸ HANGUL JONGSEONG PIEUP */ - { 0x0ee5, 0x11b9 }, /* Hangul_J_PieubSios ᆹ HANGUL JONGSEONG PIEUP-SIOS */ - { 0x0ee6, 0x11ba }, /* Hangul_J_Sios ᆺ HANGUL JONGSEONG SIOS */ - { 0x0ee7, 0x11bb }, /* Hangul_J_SsangSios ᆻ HANGUL JONGSEONG SSANGSIOS */ - { 0x0ee8, 0x11bc }, /* Hangul_J_Ieung ᆼ HANGUL JONGSEONG IEUNG */ - { 0x0ee9, 0x11bd }, /* Hangul_J_Jieuj ᆽ HANGUL JONGSEONG CIEUC */ - { 0x0eea, 0x11be }, /* Hangul_J_Cieuc ᆾ HANGUL JONGSEONG CHIEUCH */ - { 0x0eeb, 0x11bf }, /* Hangul_J_Khieuq ᆿ HANGUL JONGSEONG KHIEUKH */ - { 0x0eec, 0x11c0 }, /* Hangul_J_Tieut ᇀ HANGUL JONGSEONG THIEUTH */ - { 0x0eed, 0x11c1 }, /* Hangul_J_Phieuf ᇁ HANGUL JONGSEONG PHIEUPH */ - { 0x0eee, 0x11c2 }, /* Hangul_J_Hieuh ᇂ HANGUL JONGSEONG HIEUH */ - { 0x0eef, 0x316d }, /* Hangul_RieulYeorinHieuh ㅭ HANGUL LETTER RIEUL-YEORINHIEUH */ - { 0x0ef0, 0x3171 }, /* Hangul_SunkyeongeumMieum ㅱ HANGUL LETTER KAPYEOUNMIEUM */ - { 0x0ef1, 0x3178 }, /* Hangul_SunkyeongeumPieub ㅸ HANGUL LETTER KAPYEOUNPIEUP */ - { 0x0ef2, 0x317f }, /* Hangul_PanSios ㅿ HANGUL LETTER PANSIOS */ - { 0x0ef3, 0x3181 }, /* Hangul_KkogjiDalrinIeung ㆁ HANGUL LETTER YESIEUNG */ - { 0x0ef4, 0x3184 }, /* Hangul_SunkyeongeumPhieuf ㆄ HANGUL LETTER KAPYEOUNPHIEUPH */ - { 0x0ef5, 0x3186 }, /* Hangul_YeorinHieuh ㆆ HANGUL LETTER YEORINHIEUH */ - { 0x0ef6, 0x318d }, /* Hangul_AraeA ㆍ HANGUL LETTER ARAEA */ - { 0x0ef7, 0x318e }, /* Hangul_AraeAE ㆎ HANGUL LETTER ARAEAE */ - { 0x0ef8, 0x11eb }, /* Hangul_J_PanSios ᇫ HANGUL JONGSEONG PANSIOS */ - { 0x0ef9, 0x11f0 }, /* Hangul_J_KkogjiDalrinIeung ᇰ HANGUL JONGSEONG YESIEUNG */ - { 0x0efa, 0x11f9 }, /* Hangul_J_YeorinHieuh ᇹ HANGUL JONGSEONG YEORINHIEUH */ - { 0x0eff, 0x20a9 }, /* Korean_Won ₩ WON SIGN */ - { 0x13a4, 0x20ac }, /* Euro € EURO SIGN */ - { 0x13bc, 0x0152 }, /* OE Œ LATIN CAPITAL LIGATURE OE */ - { 0x13bd, 0x0153 }, /* oe œ LATIN SMALL LIGATURE OE */ - { 0x13be, 0x0178 }, /* Ydiaeresis Ÿ LATIN CAPITAL LETTER Y WITH DIAERESIS */ - { 0x20ac, 0x20ac }, /* EuroSign € EURO SIGN */ - - /* Combining symbols */ - { 0xfe50, 0x0300 }, /* dead_grave */ - { 0xfe51, 0x0301 }, /* dead_acute" */ - { 0xfe52, 0x0302 }, /* dead_circumflex" */ - { 0xfe53, 0x0303 }, /* dead_tilde" */ - { 0xfe54, 0x0304 }, /* dead_macron" */ - { 0xfe55, 0x0306 }, /* dead_breve" */ - { 0xfe56, 0x0307 }, /* dead_abovedot" */ - { 0xfe57, 0x0308 }, /* dead_diaeresis" */ - { 0xfe58, 0x030A }, /* dead_abovering" */ - { 0xfe59, 0x030B }, /* dead_doubleacute" */ - { 0xfe5a, 0x030C }, /* dead_caron" */ - { 0xfe5b, 0x0327 }, /* dead_cedilla" */ - { 0xfe5c, 0x0328 }, /* dead_ogonek" */ - { 0xfe60, 0x0323 }, /* dead_belowdot */ - - /* Special function keys. */ - - { 0xff08, 0x0008 }, /* XK_BackSpace */ - { 0xff09, 0x0009 }, /* XK_Tab */ - { 0xff0a, 0x000a }, /* XK_Linefeed */ - { 0xff0d, 0x000d }, /* XK_Return */ - { 0xff13, 0x0013 }, /* XK_Pause */ - { 0xff1b, 0x001b }, /* XK_Escape */ - { 0xff50, 0x0001 }, /* XK_Home */ - { 0xff51, 0x001c }, /* XK_Left */ - { 0xff52, 0x001e }, /* XK_Up */ - { 0xff53, 0x001d }, /* XK_Right */ - { 0xff54, 0x001f }, /* XK_Down */ - { 0xff55, 0x000b }, /* XK_Prior */ - { 0xff56, 0x000c }, /* XK_Next */ - { 0xff57, 0x0004 }, /* XK_End */ - { 0xff6a, 0x0005 }, /* XK_Help */ - { 0xffff, 0x007f }, /* XK_Delete */ -}; - -long keysym2ucs(KeySym keysym) -{ - int min = 0; - int max = sizeof(keysymtab) / sizeof(struct codepair) - 1; - int mid; - - /* first check for Latin-1 characters (1:1 mapping) */ - if ((keysym >= 0x0020 && keysym <= 0x007e) || - (keysym >= 0x00a0 && keysym <= 0x00ff)) { - return keysym; - } - - /* also check for directly encoded 24-bit UCS characters */ - if ((keysym & 0xff000000) == 0x01000000) { - return keysym & 0x00ffffff; - } - - /* binary search in table */ - while (max >= min) { - mid = (min + max) / 2; - if (keysymtab[mid].keysym < keysym) { - min = mid + 1; - } else if (keysymtab[mid].keysym > keysym) { - max = mid - 1; - } else { - /* found it */ - return keysymtab[mid].ucs; - } - } - - /* no matching Unicode value found */ - return -1; -} diff --git a/kcms/keyboard/preview/keysymbols.h b/kcms/keyboard/preview/keysymbols.h deleted file mode 100644 --- a/kcms/keyboard/preview/keysymbols.h +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright (C) 2012 Shivam Makkar (amourphious1992@gmail.com) - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - - -#ifndef KEYSYMBOLS_H -#define KEYSYMBOLS_H - -#include -#include -class KeySymbols -{ -public: - KeySymbols(); - - QString keyname; - QList symbols; - - void setKey(const QString &opton); -}; - -#endif // KEYSYMBOLS_H diff --git a/kcms/keyboard/preview/keysymbols.cpp b/kcms/keyboard/preview/keysymbols.cpp deleted file mode 100644 --- a/kcms/keyboard/preview/keysymbols.cpp +++ /dev/null @@ -1,59 +0,0 @@ -/* - * Copyright (C) 2012 Shivam Makkar (amourphious1992@gmail.com) - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - - -#include "keysymbols.h" - -#include - - -static const int MAX_GROUPS_SUPPORTED = 4; - -KeySymbols::KeySymbols() -{ -} - -void KeySymbols::setKey(const QString &a) -{ - int i = a.indexOf("<"); - i++; - keyname = a.mid(i, 4); - keyname.remove(" "); - i = a.indexOf("["); - i++; - - QString str = a.mid(i); - i = str.indexOf("]"); - - QString st = str.left(i); - st.remove(" "); - //QStringList klst; - symbols = st.split(","); - - if (symbols.size() > MAX_GROUPS_SUPPORTED) { - symbols = symbols.mid(0, MAX_GROUPS_SUPPORTED); - } - - for (int k = 0; k < symbols.size(); k++) { - QString du = symbols.at(k); - du.remove(" "); - du.remove("\t"); - du.remove("\n"); - symbols[k] = du; - } -} diff --git a/kcms/keyboard/preview/keysymhelper.h b/kcms/keyboard/preview/keysymhelper.h deleted file mode 100644 --- a/kcms/keyboard/preview/keysymhelper.h +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright (C) 2012 Shivam Makkar (amourphious1992@gmail.com) - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -#ifndef KEYSYMHELPER_H -#define KEYSYMHELPER_H - -#include -#include - -class KeySymHelper -{ -public: - KeySymHelper(); - - QString getKeySymbol(const QString &opton); - bool isFailed() const - { - return nill >= 120; - } - -private: - QMap keySymbolMap; - int nill; -}; - -#endif // KEYSYMHELPER_H diff --git a/kcms/keyboard/preview/keysymhelper.cpp b/kcms/keyboard/preview/keysymhelper.cpp deleted file mode 100644 --- a/kcms/keyboard/preview/keysymhelper.cpp +++ /dev/null @@ -1,83 +0,0 @@ -/* - * Copyright (C) 2012 Shivam Makkar (amourphious1992@gmail.com) - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -#include "keysymhelper.h" -#include "keysym2ucs.h" - -#include -#include -#include - -#include - - -KeySymHelper::KeySymHelper() -{ - nill = 0; -} - -QString KeySymHelper::getKeySymbol(const QString &opton) -{ - if (keySymbolMap.contains(opton)) { - return keySymbolMap[opton]; - } - - const char *str = opton.toLatin1().data(); - -#if 0 - //TODO: figure out how to use this so we don't need our own symkey2ucs mapping - int res = Xutf8LookupString(XIC ic, XKeyPressedEvent * event, char *buffer_return, int bytes_buffer, KeySym * keysym_return, Status * status_return); - -#else - - KeySym keysym = XStringToKeysym(str); - - //TODO: make it more generic -// if( keysym == 0xfe03 ) -// return "L3"; - - long ucs = keysym2ucs(keysym); - -// if( ucs == -1 && (keysym >= 0xFE50 && keysym <= 0xFE5F) ) { -// ucs = 0x0300 + (keysym & 0x000F); -// qWarning() << "Got dead symbol" << QString("0x%1").arg(keysym, 0, 16) << "named" << opton << "will use" << QString("0x%1").arg(ucs, 0, 16) << "as UCS"; -// } - - if (ucs == -1) { - nill++; - qWarning() << "No mapping from keysym:" << QStringLiteral("0x%1").arg(keysym, 0, 16) << "named:" << opton << "to UCS"; - } - - QString ucsStr = QString(QChar((int)ucs)); - - // Combining Diacritical Marks - if (ucs >= 0x0300 && ucs <= 0x036F) { - ucsStr = " " + ucsStr + QLatin1Char(' '); - } - -// qWarning() << "--" << opton << "keysym: " << keysym << QString("0x%1").arg(keysym, 0, 16) << "keysym2string" << XKeysymToString(keysym) -// << "---" << QString("0x%1").arg(ucs, 0, 16) << ucsStr; - - keySymbolMap[opton] = ucsStr; - - return ucsStr; - -#endif - -} - diff --git a/kcms/keyboard/preview/symbol_parser.h b/kcms/keyboard/preview/symbol_parser.h deleted file mode 100644 --- a/kcms/keyboard/preview/symbol_parser.h +++ /dev/null @@ -1,93 +0,0 @@ -/* - * Copyright (C) 2013 Shivam Makkar (amourphious1992@gmail.com) - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -#ifndef SYMBOL_PARSER_H -#define SYMBOL_PARSER_H - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#include "keyboardlayout.h" -#include "keyaliases.h" - - -namespace qi = boost::spirit::qi; -namespace ascii = boost::spirit::ascii; -namespace phx = boost::phoenix; -namespace iso = boost::spirit::iso8859_1; - - -namespace grammar -{ - -struct symbol_keywords : qi::symbols { - symbol_keywords(); -}; - -struct levels : qi::symbols { - levels(); -}; - -template -struct SymbolParser : qi::grammar { - - SymbolParser(); - - qi::rulestart; - qi::rulename; - qi::rulekeyName; - qi::rulesymbols; - qi::rulekey; - qi::ruletype; - qi::rulegroup; - qi::rulesymbol; - qi::rulecomments; - qi::ruleee; - qi::ruleinclude; - - KbLayout layout; - int keyIndex, newKey; - symbol_keywords symbolKeyword; - levels lvl; - Aliases alias; - - void getSymbol(std::string n); - void addKeyName(std::string n); - void getInclude(std::string n); - void addKey(); - void setName(std::string n); - void setLevel(int lvl); -}; - -KbLayout parseSymbols(const QString &layout, const QString &layoutVariant); -QString findSymbolBaseDir(); -} - -#endif //SYMBOL_PARSER_H diff --git a/kcms/keyboard/preview/symbol_parser.cpp b/kcms/keyboard/preview/symbol_parser.cpp deleted file mode 100644 --- a/kcms/keyboard/preview/symbol_parser.cpp +++ /dev/null @@ -1,288 +0,0 @@ -/* - * Copyright (C) 2013 Shivam Makkar (amourphious1992@gmail.com) - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -#include "symbol_parser.h" -#include "xkb_rules.h" - -#include -#include -#include -#include -#include - - -namespace grammar -{ - -symbol_keywords::symbol_keywords() -{ - add("key", 2)("include", 1)("//", 3)("*/", 4); -} - -levels::levels() -{ - add("ONE", 1)("TWO", 2)("THREE", 3)("FOUR", 4)("SIX", 6)("EIGHT", 8); -} - -template -SymbolParser::SymbolParser() : - SymbolParser::base_type(start) -{ - using qi::lexeme; - using qi::char_; - using qi::lit; - using qi::_1; - using qi::_val; - using qi::int_; - using qi::double_; - using qi::eol; - - newKey = 0; - - name %= '"' >> +(char_ - '"') >> '"'; - - group = lit("Group") >> int_; - - comments = lexeme[lit("//") >> *(char_ - eol || symbolKeyword - eol) >> eol - || lit("/*") >> *(char_ - lit("*/") || symbolKeyword - lit("*/")) - >> lit("*/")]; - - include = lit("include") - >> name[phx::bind(&SymbolParser::getInclude, this, _1)]; - - type = lit("type") >> '[' >> group >> lit(']') >> lit('=') >> lit("\"") - >> *(char_ - lvl) - >> *lvl[phx::bind(&SymbolParser::setLevel, this, _1)] - >> *(char_ - lvl - '"') >> lit("\""); - - symbol = +(char_ - ',' - ']'); - - symbols = *(lit("symbols") >> '[' >> group >> lit(']') >> lit('=')) >> '[' - >> symbol[phx::bind(&SymbolParser::getSymbol, this, _1)] - >> *(',' >> symbol[phx::bind(&SymbolParser::getSymbol, this, _1)]) - >> ']'; - - keyName = '<' >> *(char_ - '>') >> '>'; - - key = (lit("key") - >> keyName[phx::bind(&SymbolParser::addKeyName, this, _1)] >> '{' - >> *(type >> ',') >> symbols >> *(',' >> type) >> lit("};")) - || lit("key") >> lit(".") >> type >> lit(";"); - - ee = *(char_ - symbolKeyword - '{') >> '{' >> *(char_ - '}' - ';') - >> lit("};"); - - start = *(char_ - lit("xkb_symbols") || comments) >> lit("xkb_symbols") - >> name[phx::bind(&SymbolParser::setName, this, _1)] >> '{' - >> *(key[phx::bind(&SymbolParser::addKey, this)] || include || ee - || char_ - '}' - symbolKeyword || comments) >> lit("};") - >> *(comments || char_); -} - -template -void SymbolParser::getSymbol(std::string n) -{ - int index = layout.keyList[keyIndex].getSymbolCount(); - layout.keyList[keyIndex].addSymbol(QString::fromUtf8(n.data(), n.size()), - index); - //qCDebug(KEYBOARD_PREVIEW) << "adding symbol: " << QString::fromUtf8(n.data(), n.size()); - //qCDebug(KEYBOARD_PREVIEW) << "added symbol: " << layout.keyList[keyIndex].getSymbol(index) << " in " << keyIndex << " at " << index; -} - -template -void SymbolParser::addKeyName(std::string n) -{ - QString kname = QString::fromUtf8(n.data(), n.size()); - if (kname.startsWith(QLatin1String("Lat"))) { - kname = alias.getAlias(layout.country, kname); - } - keyIndex = layout.findKey(kname); - //qCDebug(KEYBOARD_PREVIEW) << layout.getKeyCount(); - if (keyIndex == -1) { - layout.keyList[layout.getKeyCount()].keyName = kname; - keyIndex = layout.getKeyCount(); - newKey = 1; - } - // qCDebug(KEYBOARD_PREVIEW) << "key at" << keyIndex; -} - -template -void SymbolParser::addKey() -{ - if (newKey == 1) { - layout.addKey(); - newKey = 0; - //qCDebug(KEYBOARD_PREVIEW) << "new key"; - } -} - -template -void SymbolParser::getInclude(std::string n) -{ - layout.addInclude(QString::fromUtf8(n.data(), n.size())); -} - -template -void SymbolParser::setName(std::string n) -{ - layout.setName(QString::fromUtf8(n.data(), n.size())); - //qCDebug(KEYBOARD_PREVIEW) << layout.getLayoutName(); -} - -template -void SymbolParser::setLevel(int lvl) -{ - if (lvl > layout.getLevel()) { - layout.setLevel(lvl); - qCDebug(KEYBOARD_PREVIEW) << lvl; - } -} - -QString findSymbolBaseDir() -{ - QString xkbDir = Rules::findXkbDir(); - return QStringLiteral("%1/symbols/").arg(xkbDir); -} - -QString findLayout(const QString &layout, const QString &layoutVariant) -{ - - QString symbolBaseDir = findSymbolBaseDir(); - QString symbolFile = symbolBaseDir.append(layout); - - QFile sfile(symbolFile); - if (!sfile.open(QIODevice::ReadOnly | QIODevice::Text)) { - //qCDebug(KEYBOARD_PREVIEW) << "unable to open the file"; - return QStringLiteral("I/O ERROR"); - } - - QString scontent = sfile.readAll(); - sfile.close(); - QStringList scontentList = scontent.split(QStringLiteral("xkb_symbols")); - - QString variant; - QString input; - - if (layoutVariant.isEmpty()) { - input = scontentList.at(1); - input.prepend("xkb_symbols"); - } - - else { - int current = 1; - - while (layoutVariant != variant && current < scontentList.size()) { - input = scontentList.at(current); - - QString symbolCont = scontentList.at(current); - - int index = symbolCont.indexOf(QLatin1String("\"")); - symbolCont = symbolCont.mid(index); - index = symbolCont.indexOf(QLatin1String("{")); - symbolCont.truncate(index); - symbolCont.remove(QStringLiteral(" ")); - variant = symbolCont.remove(QStringLiteral("\"")); - - input.prepend("xkb_symbols"); - current++; - } - } - - return input; -} - -KbLayout parseSymbols(const QString &layout, const QString &layoutVariant) -{ - - using boost::spirit::iso8859_1::space; - typedef std::string::const_iterator iterator_type; - typedef grammar::SymbolParser SymbolParser; - - SymbolParser symbolParser; - - symbolParser.layout.country = layout; - QString input = findLayout(layout, layoutVariant); - - if (input == QLatin1String("I/O ERROR")) { - symbolParser.layout.setParsedSymbol(false); - return symbolParser.layout; - } - - std::string parserInput = input.toUtf8().constData(); - - std::string::const_iterator iter = parserInput.begin(); - std::string::const_iterator end = parserInput.end(); - - bool success = phrase_parse(iter, end, symbolParser, space); - - if (success && iter == end) { - qCDebug(KEYBOARD_PREVIEW) << "Symbols Parsing succeeded"; - symbolParser.layout.setParsedSymbol(true); - - } else { - qWarning() << "Symbols Parsing failed\n" << input; - symbolParser.layout.setParsedSymbol(false); - } - - for (int currentInclude = 0; - currentInclude < symbolParser.layout.getIncludeCount(); - currentInclude++) { - QString include = symbolParser.layout.getInclude(currentInclude); - QStringList includeFile = include.split(QLatin1Char('(')); - if (includeFile.size() == 2) { - QString file = includeFile.at(0); - QString layout = includeFile.at(1); - layout.remove(QStringLiteral(")")); - input = findLayout(file, layout); - - } - - else { - QString a; - a.clear(); - input = findLayout(includeFile.at(0), a); - } - - parserInput = input.toUtf8().constData(); - - std::string::const_iterator iter = parserInput.begin(); - std::string::const_iterator end = parserInput.end(); - - success = phrase_parse(iter, end, symbolParser, space); - - if (success && iter == end) { - qCDebug(KEYBOARD_PREVIEW) << "Symbols Parsing succeeded"; - symbolParser.layout.setParsedSymbol(true); - - } else { - qCDebug(KEYBOARD_PREVIEW) << "Symbols Parsing failed\n"; - qCDebug(KEYBOARD_PREVIEW) << input; - symbolParser.layout.setParsedSymbol(false); - } - - } - - //s.layout.display(); - if (symbolParser.layout.getParsedSymbol()) { - return symbolParser.layout; - } else { - return parseSymbols(QStringLiteral("us"), QStringLiteral("basic")); - } -} - -} diff --git a/kcms/keyboard/tastenbrett.h b/kcms/keyboard/tastenbrett.h new file mode 100644 --- /dev/null +++ b/kcms/keyboard/tastenbrett.h @@ -0,0 +1,35 @@ +/* + Copyright 2019 Harald Sitter + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of + the License or (at your option) version 3 or any later version + accepted by the membership of KDE e.V. (or its successor approved + by the membership of KDE e.V.), which shall act as a proxy + defined in Section 14 of version 3 of the license. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#ifndef TASTENBRETT_H +#define TASTENBRETT_H + +#include + +class Tastenbrett +{ +public: + static QString path(); + static bool exists(); + static void launch(const QString &model, const QString &layout, const QString &variant, const QString &options, + const QString &title = QString()); +}; + +#endif // TASTENBRETT_H diff --git a/kcms/keyboard/tastenbrett.cpp b/kcms/keyboard/tastenbrett.cpp new file mode 100644 --- /dev/null +++ b/kcms/keyboard/tastenbrett.cpp @@ -0,0 +1,66 @@ +/* + Copyright 2019 Harald Sitter + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of + the License or (at your option) version 3 or any later version + accepted by the membership of KDE e.V. (or its successor approved + by the membership of KDE e.V.), which shall act as a proxy + defined in Section 14 of version 3 of the license. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#include "tastenbrett.h" + +#include +#include +#include +#include + +QString Tastenbrett::path() +{ + static QString path; + if (!path.isNull()) { + return path; + } + + // Find relative to KCM (when run from build dir) + path = QStandardPaths::findExecutable("tastenbrett", { qEnvironmentVariable("QT_PLUGIN_PATH"), + qApp->applicationDirPath() }); + if (!path.isNull()) { + return path; + } + + return QStandardPaths::findExecutable("tastenbrett"); +} + +bool Tastenbrett::exists() +{ + return !path().isNull(); +} + +void Tastenbrett::launch(const QString &model, const QString &layout, const QString &variant, const QString &options, const QString &title) +{ + if (!exists()) { + return; + } + + QProcess p; + p.setProgram(path()); + QStringList args { "--model", model, "--layout", layout, "--variant", variant, "--options", options }; + if (!title.isEmpty()) { + args << "-title" << title; + } + qDebug() << args; + p.setArguments(args); + p.setProcessChannelMode(QProcess::ForwardedChannels); + p.startDetached(); +} diff --git a/kcms/keyboard/tastenbrett/CMakeLists.txt b/kcms/keyboard/tastenbrett/CMakeLists.txt new file mode 100644 --- /dev/null +++ b/kcms/keyboard/tastenbrett/CMakeLists.txt @@ -0,0 +1,34 @@ +set(CMAKE_AUTORCC ON) + +pkg_check_modules(XKBCommon REQUIRED IMPORTED_TARGET xkbcommon) + +add_executable(tastenbrett + application.cpp + doodad.cpp + geometry.cpp + key.cpp + main.cpp + outline.cpp + qml.qrc + row.cpp + section.cpp + shape.cpp + xkbobject.cpp +) + +target_compile_definitions(tastenbrett + PRIVATE $<$,$>:QT_QML_DEBUG>) + +target_link_libraries(tastenbrett + PRIVATE + Qt5::Core + Qt5::Quick + Qt5::Gui + Qt5::X11Extras + XCB::XCB + PkgConfig::XKBCommon + ${X11_Xkbfile_LIB} + ${X11_LIBRARIES} +) + +install(TARGETS tastenbrett DESTINATION ${KDE_INSTALL_TARGETS_DEFAULT_ARGS}) diff --git a/kcms/keyboard/tastenbrett/README.md b/kcms/keyboard/tastenbrett/README.md new file mode 100644 --- /dev/null +++ b/kcms/keyboard/tastenbrett/README.md @@ -0,0 +1,8 @@ +Keyboard layout/model visualization. + +Use XKB geometry data to render a keyboard. +The geometry data is parsed by x11, this removes the need for a bespoke XKB language implementation. + +Requires Qt xcb platform plugin to run. + +https://www.x.org/releases/X11R7.6/doc/libX11/specs/XKB/xkblib.html#keyboard_geometry diff --git a/kcms/keyboard/tastenbrett/application.h b/kcms/keyboard/tastenbrett/application.h new file mode 100644 --- /dev/null +++ b/kcms/keyboard/tastenbrett/application.h @@ -0,0 +1,43 @@ +/* + Copyright 2019 Harald Sitter + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of + the License or (at your option) version 3 or any later version + accepted by the membership of KDE e.V. (or its successor approved + by the membership of KDE e.V.), which shall act as a proxy + defined in Section 14 of version 3 of the license. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#ifndef APPLICATION_H +#define APPLICATION_H + +#include + +class QKeyEvent; + +// Simple QGuiApp overlay to gobble up all key events for input-detection. +class Application final : public QGuiApplication +{ + Q_OBJECT +public: + using QGuiApplication::QGuiApplication; + + bool notify(QObject *receiver, QEvent *event) override; + + static Application *instance(); + +Q_SIGNALS: + void keyEvent(QKeyEvent *event); +}; + +#endif // APPLICATION_H diff --git a/kcms/keyboard/tastenbrett/application.cpp b/kcms/keyboard/tastenbrett/application.cpp new file mode 100644 --- /dev/null +++ b/kcms/keyboard/tastenbrett/application.cpp @@ -0,0 +1,36 @@ +/* + Copyright 2019 Harald Sitter + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of + the License or (at your option) version 3 or any later version + accepted by the membership of KDE e.V. (or its successor approved + by the membership of KDE e.V.), which shall act as a proxy + defined in Section 14 of version 3 of the license. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#include "application.h" + +#include + +bool Application::notify(QObject *receiver, QEvent *event) +{ + if (event->type() == QEvent::KeyPress || event->type() == QEvent::KeyRelease) { + emit keyEvent(dynamic_cast(event)); + } + return QGuiApplication::notify(receiver,event); +} + +Application *Application::instance() +{ + return qobject_cast(qGuiApp); +} diff --git a/kcms/keyboard/tastenbrett/doodad.h b/kcms/keyboard/tastenbrett/doodad.h new file mode 100644 --- /dev/null +++ b/kcms/keyboard/tastenbrett/doodad.h @@ -0,0 +1,156 @@ +/* + Copyright 2019 Harald Sitter + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of + the License or (at your option) version 3 or any later version + accepted by the membership of KDE e.V. (or its successor approved + by the membership of KDE e.V.), which shall act as a proxy + defined in Section 14 of version 3 of the license. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#ifndef DOODAD_H +#define DOODAD_H + +#include + +#include "xkbobject.h" + +class Shape; + +class Doodad : public XkbObject +{ + Q_OBJECT + +#define D_P(type, name) \ +private: \ + Q_PROPERTY(type name READ auto_prop_##name CONSTANT) \ +public: \ + type auto_prop_##name () const { return doodad->any. name ; } + + D_P(unsigned char, priority) + + static Doodad *factorize(XkbDoodadPtr doodad, XkbDescPtr xkb, QObject *parent); + + XkbDoodadPtr doodad = nullptr; + +protected: + Doodad(XkbDoodadPtr doodad_, XkbDescPtr xkb_, QObject *parent = nullptr); +}; + +class ShapeDoodad : public Doodad +{ + Q_OBJECT + +#define SD_P(type, name) \ +private: \ + Q_PROPERTY(type name READ auto_prop_##name CONSTANT) \ +public: \ + type auto_prop_##name () const { return doodad->shape. name ; } + + SD_P(short, top) + SD_P(short, left) + SD_P(short, angle) + + Q_PROPERTY(Shape *shape MEMBER shape CONSTANT) + Q_PROPERTY(QColor color MEMBER color CONSTANT) + // Whether this shape is an outline only. If it is not it's solid/filled. + Q_PROPERTY(bool outlineOnly MEMBER outlineOnly CONSTANT) + +public: + ShapeDoodad(XkbDoodadPtr doodad_, XkbDescPtr xkb_, QObject *parent = nullptr); + + Shape *shape = nullptr; + QColor color; + bool outlineOnly = false; +}; + +class TextDoodad : public Doodad +{ + Q_OBJECT + +#define TD_P(type, name) \ +private: \ + Q_PROPERTY(type name READ auto_prop_##name CONSTANT) \ +public: \ + type auto_prop_##name () const { return doodad->text. name ; } + + TD_P(short, top) + TD_P(short, left) + TD_P(short, angle) + TD_P(short, width) + TD_P(short, height) + TD_P(QString, text) + TD_P(QString, font) +public: + TextDoodad(XkbDoodadPtr doodad_, XkbDescPtr xkb_, QObject *parent = nullptr); + + Shape *shape = nullptr; +}; + +// NB: This is technically kind of like a shape doodad, but in reality +// only top/left/angle are actually equal across doodad.indicator. and doodad.shape. +// As such there is no benefit in modelling the classes like there is inheritance +// because there really isn't. The actual shape definition is abstracted by +// Shape objects in either case. +// On the GUI side this can still be rendered like a shape, since it has a Shape*, +// it's just not specifically a shape doodad. +class IndicatorDoodad : public Doodad +{ + Q_OBJECT + +#define ID_P(type, name) \ +private: \ + Q_PROPERTY(type name READ auto_prop_##name CONSTANT) \ +public: \ + type auto_prop_##name () const { return doodad->indicator. name ; } + + ID_P(short, top) + ID_P(short, left) + ID_P(short, angle) + + Q_PROPERTY(Shape *shape MEMBER shape CONSTANT) + Q_PROPERTY(bool on MEMBER on NOTIFY onChanged) +public: + IndicatorDoodad(XkbDoodadPtr doodad_, XkbDescPtr xkb_, QObject *parent = nullptr); + + Shape *shape = nullptr; + bool on = false; + +signals: + void onChanged(); + +private slots: + void refreshState(); +}; + +class LogoDoodad : public ShapeDoodad +{ + Q_OBJECT + +#define LD_P(type, name) \ +private: \ + Q_PROPERTY(type name READ auto_prop_##name CONSTANT) \ +public: \ + type auto_prop_##name () const { return doodad->logo. name ; } + + LD_P(short, top) + LD_P(short, left) + LD_P(short, angle) + LD_P(QString, logo_name) +public: + LogoDoodad(XkbDoodadPtr doodad_, XkbDescPtr xkb_, QObject *parent = nullptr); + + Shape *shape = nullptr; +}; + +#endif // DOODAD_H diff --git a/kcms/keyboard/tastenbrett/doodad.cpp b/kcms/keyboard/tastenbrett/doodad.cpp new file mode 100644 --- /dev/null +++ b/kcms/keyboard/tastenbrett/doodad.cpp @@ -0,0 +1,93 @@ +/* + Copyright 2019 Harald Sitter + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of + the License or (at your option) version 3 or any later version + accepted by the membership of KDE e.V. (or its successor approved + by the membership of KDE e.V.), which shall act as a proxy + defined in Section 14 of version 3 of the license. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#include "doodad.h" + +#include +#include + +#include "application.h" +#include "shape.h" + +Doodad *Doodad::factorize(XkbDoodadPtr doodad, XkbDescPtr xkb, QObject *parent) +{ + switch (doodad->any.type) { + case XkbOutlineDoodad: + case XkbSolidDoodad: + return new ShapeDoodad(doodad, xkb, parent); + case XkbTextDoodad: + return new TextDoodad(doodad, xkb, parent); + case XkbIndicatorDoodad: + return new IndicatorDoodad(doodad, xkb, parent); + case XkbLogoDoodad: + return new LogoDoodad(doodad, xkb, parent); + } + + Q_UNREACHABLE(); + return nullptr; +} + +Doodad::Doodad(XkbDoodadPtr doodad_, XkbDescPtr xkb_, QObject *parent) + : XkbObject(xkb_, parent) + , doodad(doodad_) +{ +} + +ShapeDoodad::ShapeDoodad(XkbDoodadPtr doodad_, XkbDescPtr xkb_, QObject *parent) + : Doodad(doodad_, xkb_, parent) + , shape(new Shape(xkb->geom->shapes + doodad_->shape.shape_ndx, xkb, this)) + , outlineOnly(doodad->any.type == XkbOutlineDoodad) +{ +} + +TextDoodad::TextDoodad(XkbDoodadPtr doodad_, XkbDescPtr xkb_, QObject *parent) + : Doodad(doodad_, xkb_, parent) +{ +} + +IndicatorDoodad::IndicatorDoodad(XkbDoodadPtr doodad_, XkbDescPtr xkb_, QObject *parent) + : Doodad(doodad_, xkb_, parent) + , shape(new Shape(xkb->geom->shapes + doodad_->indicator.shape_ndx, xkb, this)) +{ + connect(Application::instance(), &Application::keyEvent, + this, &IndicatorDoodad::refreshState); + refreshState(); +} + +void IndicatorDoodad::refreshState() +{ + int onInt = False; + if (!XkbGetNamedIndicator(QX11Info::display(), + doodad->indicator.name, + nullptr, + &onInt, + nullptr, + nullptr)) { + on = false; + } else { + on = onInt == True ? true : false; + } + emit onChanged(); +} + +LogoDoodad::LogoDoodad(XkbDoodadPtr doodad_, XkbDescPtr xkb_, QObject *parent) + : ShapeDoodad(doodad_, xkb_, parent) +{ +} diff --git a/kcms/keyboard/tastenbrett/geometry.h b/kcms/keyboard/tastenbrett/geometry.h new file mode 100644 --- /dev/null +++ b/kcms/keyboard/tastenbrett/geometry.h @@ -0,0 +1,45 @@ +/* + Copyright 2019 Harald Sitter + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of + the License or (at your option) version 3 or any later version + accepted by the membership of KDE e.V. (or its successor approved + by the membership of KDE e.V.), which shall act as a proxy + defined in Section 14 of version 3 of the license. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#ifndef GEOMETRY_H +#define GEOMETRY_H + +#include "xkbobject.h" + +class Geometry : public XkbObject +{ + Q_OBJECT + Q_PROPERTY(QList doodads MEMBER doodads CONSTANT) + Q_PROPERTY(QList sections MEMBER sections CONSTANT) + Q_PROPERTY(qreal widthMM MEMBER widthMM CONSTANT) + Q_PROPERTY(qreal heightMM MEMBER heightMM CONSTANT) +public: + Geometry(XkbGeometryPtr geom_, XkbDescPtr xkb_, QObject *parent = nullptr); + + XkbGeometryPtr geom = nullptr; + + QList doodads; + QList sections; + + qreal widthMM = -1; + qreal heightMM = -1; +}; + +#endif // GEOMETRY_H diff --git a/kcms/keyboard/tastenbrett/geometry.cpp b/kcms/keyboard/tastenbrett/geometry.cpp new file mode 100644 --- /dev/null +++ b/kcms/keyboard/tastenbrett/geometry.cpp @@ -0,0 +1,45 @@ +/* + Copyright 2019 Harald Sitter + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of + the License or (at your option) version 3 or any later version + accepted by the membership of KDE e.V. (or its successor approved + by the membership of KDE e.V.), which shall act as a proxy + defined in Section 14 of version 3 of the license. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#include "geometry.h" + +#include + +#include "doodad.h" +#include "section.h" + +Geometry::Geometry(XkbGeometryPtr geom_, XkbDescPtr xkb_, QObject *parent) + : XkbObject(xkb_, parent) + , geom(geom_) + , widthMM(geom->width_mm) + , heightMM(geom->height_mm) +{ + for (int i = 0; i < geom->num_doodads; ++i) { + Doodad *o = Doodad::factorize(geom->doodads + i, xkb, this); + if (!o) { + continue; + } + doodads.push_back(o); + } + + for (int i = 0; i < geom->num_sections; ++i) { + sections.push_back(new Section(geom->sections + i, xkb, this)); + } +} diff --git a/kcms/keyboard/tastenbrett/key.h b/kcms/keyboard/tastenbrett/key.h new file mode 100644 --- /dev/null +++ b/kcms/keyboard/tastenbrett/key.h @@ -0,0 +1,94 @@ +/* + Copyright 2019 Harald Sitter + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of + the License or (at your option) version 3 or any later version + accepted by the membership of KDE e.V. (or its successor approved + by the membership of KDE e.V.), which shall act as a proxy + defined in Section 14 of version 3 of the license. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#ifndef KEY_H +#define KEY_H + +#include "xkbobject.h" + +class Shape; + +// This is a fairly opinionated model of a key cap. We assume there won't +// be any more than 4 levels. +// This isn't necessarily the case since (e.g.) the NEO layout has 6 levels. +// Since that is super niche and poses some complication as for how to +// exactly render the levels we'll simply ignore this use case for now. +// In the end the keyboard model display only needs to act as simple indicator +// anyway. +class KeyCap : public QObject +{ + Q_OBJECT + Q_PROPERTY(QString topLeft MEMBER topLeft CONSTANT) + Q_PROPERTY(QString topRight MEMBER topRight CONSTANT) + Q_PROPERTY(QString bottomLeft MEMBER bottomLeft CONSTANT) + Q_PROPERTY(QString bottomRight MEMBER bottomRight CONSTANT) +public: + enum Level + { + TopLeft = 1, + TopRight = 3, + BottomLeft = 0, + BottomRight = 2 + }; + Q_ENUM(Level) + constexpr static int levelCount = 4; + + KeyCap(const QString symbols[KeyCap::levelCount], QObject *parent); + + QString topLeft; + QString topRight; + QString bottomLeft; + QString bottomRight; +}; + +class Key : public XkbObject +{ + Q_OBJECT +#define K_P(type, name) \ +private: \ + Q_PROPERTY(type name READ auto_prop_##name CONSTANT) \ +public: \ + type auto_prop_##name () const { return key-> name ; } + + K_P(short, gap) + + Q_PROPERTY(Shape *shape MEMBER shape CONSTANT) + Q_PROPERTY(KeyCap *cap MEMBER cap CONSTANT) + Q_PROPERTY(bool pressed MEMBER pressed NOTIFY pressedChanged) + + constexpr static uint INVALID_KEYCODE = static_cast(-1); + +public: + Key(XkbKeyPtr key_, XkbDescPtr xkb_, QObject *parent = nullptr); + uint nativeScanCodeFromName(const QByteArray &needle); + KeyCap *resolveCap(); + + XkbKeyPtr key = nullptr; + Shape *shape = nullptr; + QByteArray name; // Internal name in the geometry. + quint32 nativeScanCode = INVALID_KEYCODE; + KeyCap *cap = nullptr; + bool pressed = false; + +signals: + void pressedChanged(); +}; + +#endif // KEY_H diff --git a/kcms/keyboard/tastenbrett/key.cpp b/kcms/keyboard/tastenbrett/key.cpp new file mode 100644 --- /dev/null +++ b/kcms/keyboard/tastenbrett/key.cpp @@ -0,0 +1,257 @@ +/* + Copyright 2019 Harald Sitter + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of + the License or (at your option) version 3 or any later version + accepted by the membership of KDE e.V. (or its successor approved + by the membership of KDE e.V.), which shall act as a proxy + defined in Section 14 of version 3 of the license. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#include "key.h" + +#include +#include +#include + +#include +#include + +#include "application.h" +#include "shape.h" + +static QString xkbKeysymToName(xkb_keysym_t keysym) +{ + QVarLengthArray chars(32); + Q_ASSERT(chars.size() >= 0); // ensure cast to size_t + + const int size = xkb_keysym_get_name(keysym, chars.data(), static_cast(chars.size())); + if (Q_UNLIKELY(size > chars.size())) { + chars.resize(size); + xkb_keysym_get_name(keysym, chars.data(), static_cast(chars.size())); + } + + return QString::fromUtf8(chars.constData(), size); +} + +static QString xkbKeysymToUtf8(xkb_keysym_t keysym) +{ + QVarLengthArray chars(32); + Q_ASSERT(chars.size() >= 0); // ensure cast to size_t + + const int size = xkb_keysym_to_utf8(keysym, chars.data(), static_cast(chars.size())); + if (Q_UNLIKELY(size > chars.size())) { + chars.resize(size); + xkb_keysym_to_utf8(keysym, chars.data(), static_cast(chars.size())); + } + + return QString::fromUtf8(chars.constData(), size); +} + +static QString keySymToString(KeySym keysym) { + // Strangely enough xkbcommons's UTF map is incomplete with regards to + // dead keys. Extend it a bit. + static QHash deadMap { + { XK_dead_grave, 0x0060 }, + { XK_dead_acute, 0x00b4 }, + { XK_dead_circumflex, 0x02c6 }, + { XK_dead_tilde, 0x02dc }, + { XK_dead_macron, 0x00af }, + { XK_dead_breve, 0x02D8 }, + { XK_dead_abovedot, 0x02D9 }, + { XK_dead_diaeresis, 0x00A8 }, + { XK_dead_abovering, 0x02DA }, + { XK_dead_doubleacute, 0x02DD }, + { XK_dead_caron, 0x02C7 }, + { XK_dead_cedilla, 0x00B8 }, + { XK_dead_ogonek, 0x02DB }, + { XK_dead_iota, 0x0269 }, + { XK_dead_voiced_sound, 0x309B }, + { XK_dead_semivoiced_sound, 0x309A }, + { XK_dead_belowdot, 0x0323 }, + { XK_dead_hook, 0x0309 }, + { XK_dead_horn, 0x031b }, + { XK_dead_stroke, 0x0335 }, + { XK_dead_abovecomma, 0x0312 }, + { XK_dead_abovereversedcomma, 0x0314 }, + { XK_dead_doublegrave, 0x030f }, + { XK_dead_belowring, 0x0325 }, + { XK_dead_belowmacron, 0x0331 }, + { XK_dead_belowcircumflex, 0x032D }, + { XK_dead_belowtilde, 0x0330 }, + { XK_dead_belowbreve, 0x032e }, + { XK_dead_belowdiaeresis, 0x0324 }, + { XK_dead_invertedbreve, 0x0311 }, + { XK_dead_belowcomma, 0x0326 }, + { XK_dead_currency, 0x00A4 }, + { XK_dead_a, 0x0061 }, + { XK_dead_A, 0x0041 }, + { XK_dead_e, 0x0065 }, + { XK_dead_E, 0x0045 }, + { XK_dead_i, 0x0069 }, + { XK_dead_I, 0x0049 }, + { XK_dead_o, 0x006f }, + { XK_dead_O, 0x004f }, + { XK_dead_u, 0x0075 }, + { XK_dead_U, 0x0055 }, + { XK_dead_small_schwa, 0x0259 }, + { XK_dead_capital_schwa, 0x018F }, + }; + + // XKB has fairly OK unicode maps, unfortunately it is + // overzaelous and will for example return "U+001B" for + // Esc which is a non-printable control character and + // also not present in most fonts. As such it is + // worthless to use and we'll discard unicode strings that + // contain non-printable characters (ignore null). + // This will lead to one of the stringy name fallbacks to handle + // these cases and produce for example 'Escape' + + if (keysym == 0 /* NoSymbol */ || keysym == XK_VoidSymbol) { + return QString(); + } + + QString str; + + // Smartly xlib uses ulong and xkbcommon uses uint32 for syms, + // so we'd best make sure that we can even cast the symbol before + // tryint to do xkb mappings. Otherwise skip to fallbacks right away. + const xkb_keysym_t xkbKeysym = static_cast(keysym) ; + if (static_cast(xkbKeysym) == keysym) { + str = xkbKeysymToUtf8(xkbKeysym); + + for (const auto &c : str) { + if (!c.isPrint() && !c.isNull()) { + str = ""; + break; + } + } + + if (str.isEmpty()) { + str = xkbKeysymToName(xkbKeysym); + } + } + + if (str.isEmpty()) { + str = XKeysymToString(keysym); + // X11 keys can be of the form "Control_L". + // Split them so they are easier on the eyes. + str = str.replace('_', ' '); + } + + if (deadMap.contains(keysym)) { + str = QChar(deadMap[keysym]); + } + + return str.replace('_', ' '); +} + +KeyCap::KeyCap(const QString symbols[], QObject *parent) + : QObject(parent) + , topLeft(symbols[Level::TopLeft]) + , topRight(symbols[Level::TopRight]) + , bottomLeft(symbols[Level::BottomLeft]) + , bottomRight(symbols[Level::BottomRight]) +{ +} + +Key::Key(XkbKeyPtr key_, XkbDescPtr xkb_, QObject *parent) + : XkbObject(xkb_, parent) + , key(key_) + , shape(new Shape(xkb->geom->shapes + key->shape_ndx, xkb, this)) + , name(key_->name.name, XkbKeyNameLength) + , nativeScanCode(nativeScanCodeFromName(name)) + , cap(resolveCap()) + , pressed(false) +{ + qRegisterMetaType(); + + connect(Application::instance(), &Application::keyEvent, + this, [this](QKeyEvent *event) + { + Q_ASSERT(event); + if (event->nativeScanCode() == nativeScanCode) { + pressed = event->type() == QKeyEvent::KeyPress; + emit pressedChanged(); + } + }); +} + +uint Key::nativeScanCodeFromName(const QByteArray &needle) +{ + for (uint keycode = xkb->min_key_code; keycode <= xkb->max_key_code; ++keycode) { + XkbKeyNameRec key = xkb->names->keys[keycode]; + const QByteArray name(key.name, XkbKeyNameLength); + if (name == needle) { + return keycode; + } + } + + for (int i = 0; i < xkb->names->num_key_aliases; ++i) { + XkbKeyAliasRec alias = xkb->names->key_aliases[i]; + const QByteArray name(alias.alias, XkbKeyNameLength); + if (name == needle) { + return nativeScanCodeFromName(alias.real); + } + } + + return INVALID_KEYCODE; +} + +KeyCap *Key::resolveCap() +{ + // Documentation TLDR + // - Levels are accessed by a modifier switching the keyboard to different symbols + // such as hitting Shift and getting access to Shift+1=! + // - Groups are an additional system which considers the entire keyboard switched + // to a different symbol set. Such as the entire keyboard being Latin or Cyrillic. + // Within each group there may be N Levels. The keyboard therefor has N Groups with + // each having M levels. + // For the purposes of key cap resolution we'll only look at the first group and the + // first 4 levels within that group (top-left, top-right, bottom-left, bottom-right). + + const quint32 keycode = nativeScanCode; + QString symbols[KeyCap::levelCount]; + + if (keycode == INVALID_KEYCODE) { + return new KeyCap(symbols, this); + } + + const int group = 0; + // We iterate over the enum directly because it also represents + // preference. TopLeft is the preferred location for unique mapping + // such as 'F1' that can appear in all levels but we only want it shown + // once in the TopLeft position. + const auto levelEnum = QMetaEnum::fromType(); + QVector seen; + for (int i = 0; i < levelEnum.keyCount(); ++i) { + int level = levelEnum.value(i); + if (group >= XkbKeyNumGroups(xkb, keycode)) { + continue; // group doesn't exist, shouldn't happen because we use group0 + } + if (level >= XkbKeyGroupWidth(xkb, keycode, group)) { + continue; // level within group doesn't exist, can totally happen! + } + + KeySym keysym = XkbKeySymEntry(xkb, keycode, level, group); + const auto str = keySymToString(keysym); + if (seen.contains(str)) { + // Don't duplicate. e.g. 'F1' can appear in all levels + continue; + } + seen << str; + symbols[level] = str; + } + + return new KeyCap(symbols, this); +} diff --git a/kcms/keyboard/tastenbrett/main.cpp b/kcms/keyboard/tastenbrett/main.cpp new file mode 100644 --- /dev/null +++ b/kcms/keyboard/tastenbrett/main.cpp @@ -0,0 +1,151 @@ +/* + Copyright 2019 Harald Sitter + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of + the License or (at your option) version 3 or any later version + accepted by the membership of KDE e.V. (or its successor approved + by the membership of KDE e.V.), which shall act as a proxy + defined in Section 14 of version 3 of the license. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#include +#include +#include +#include +#include + +#include "application.h" +#include "config-workspace.h" +#include "doodad.h" +#include "geometry.h" + +// kind-of copy from xkb_rules.cpp (less complicated) +static QString getRulesName() +{ + XkbRF_VarDefsRec vd; + char *tmp = nullptr; + + if (XkbRF_GetNamesProp(QX11Info::display(), &tmp, &vd) && tmp != nullptr) { + const QString name(tmp); + XFree(tmp); + return name; + } + + return QStringLiteral("evdev"); // default to evdev +} + +static QString findXkbRulesFile() +{ + const QString rulesName = getRulesName(); + return QStringLiteral("%1/rules/%2").arg(XKBDIR, rulesName); +} + +int main(int argc, char *argv[]) +{ + setenv("QT_QPA_PLATFORM", "xcb", 1); + QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling); + Application app(argc, argv); + Q_ASSERT(app.platformName() == QStringLiteral("xcb")); + + QCommandLineParser parser; + parser.addHelpOption(); + parser.addVersionOption(); + QCommandLineOption modelOption(QStringList { "m", "model" }, {}, QStringLiteral("MODEL")); + parser.addOption(modelOption); + QCommandLineOption layoutOption(QStringList { "l", "layout" }, {}, QStringLiteral("LAYOUT")); + parser.addOption(layoutOption); + QCommandLineOption variantOption(QStringList { "a", "variant" }, {}, QStringLiteral("VARIANT")); + parser.addOption(variantOption); + QCommandLineOption optionsOption(QStringList { "o", "options" }, {}, QStringLiteral("OPTIONS")); + parser.addOption(optionsOption); + parser.process(app); + + XkbRF_VarDefsRec varDefs; + memset(&varDefs, 0, sizeof(XkbRF_VarDefsRec)); + + // Models worth testing for obvious mistakes: + // pc104, tm2020 (fancy), kinesis (fancy) + QString model = parser.value(modelOption); + const QString layout = parser.value(layoutOption); + const QString variant = parser.value(variantOption); + const QString options = parser.value(optionsOption); + + // Hold these so so we can pass data into xkb getter. + QByteArray modelArray = model.toUtf8(); + QByteArray layoutArray = layout.toUtf8(); + QByteArray variantArray = variant.toUtf8(); + QByteArray optionsArray = options.toUtf8(); + + varDefs.model = modelArray.data(); + varDefs.layout = layoutArray.data(); + varDefs.variant = variantArray.data(); + varDefs.options = optionsArray.data(); + + XkbRF_RulesPtr rules = XkbRF_Load(findXkbRulesFile().toUtf8().data(), // needs to be non-const! + qgetenv("LOCALE").data(), + True, + True); + Q_ASSERT(rules); + QSharedPointer rulesCleanup(rules, [](XkbRF_RulesPtr obj) { + XkbRF_Free(obj, True); + }); + + XkbComponentNamesRec componentNames; + memset(&componentNames, 0, sizeof(XkbComponentNamesRec)); + + XkbRF_GetComponents(rules, &varDefs, &componentNames); + + XkbDescPtr xkb = XkbGetKeyboardByName(QX11Info::display(), + XkbUseCoreKbd, + &componentNames, + 0, + XkbGBN_GeometryMask | + XkbGBN_KeyNamesMask | + XkbGBN_OtherNamesMask | + XkbGBN_ClientSymbolsMask | + XkbGBN_IndicatorMapMask, + false); + Q_ASSERT(xkb); + QSharedPointer xkbCleanup(xkb, [](XkbDescPtr obj) { + XkbFreeKeyboard(obj, 0, True); + }); + + Geometry geometry(xkb->geom, xkb); + + // Register the doodads so we can perform easy type checks with them + // and determine how to render the individual object. + const char uri[] = "org.kde.tastenbrett.private"; + qmlRegisterUncreatableType(uri, 1, 0, "TextDoodad", QString()); + qmlRegisterUncreatableType(uri, 1, 0, "LogoDoodad", QString()); + qmlRegisterUncreatableType(uri, 1, 0, "ShapeDoodad", QString()); + qmlRegisterUncreatableType(uri, 1, 0, "IndicatorDoodad", QString()); + + // The way this is currently written we need the engine after + // we have a geometry, lest geometry is dtor'd before the engine + // causing exhaustive error spam on shutdown. + // Also, the above stuff is blocking, but optimizing it is hardly + // worth the effort. The Xkb calls altogether take ~8ms (I am not + // certain putting xkb into a qfuture is thread-safe or even + // faster). Constructing our QObjects takes 1ms. + QQmlApplicationEngine engine; + const QUrl url(QStringLiteral("qrc:/qml/main.qml")); + QObject::connect(&engine, &QQmlApplicationEngine::objectCreated, + &app, [url](QObject *obj, const QUrl &objUrl) { + if (!obj && url == objUrl) + QCoreApplication::exit(-1); + }, Qt::QueuedConnection); + engine.rootContext()->setContextProperty("geometry", &geometry); + engine.load(url); + + return app.exec(); +} diff --git a/kcms/keyboard/tastenbrett/outline.h b/kcms/keyboard/tastenbrett/outline.h new file mode 100644 --- /dev/null +++ b/kcms/keyboard/tastenbrett/outline.h @@ -0,0 +1,46 @@ +/* + Copyright 2019 Harald Sitter + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of + the License or (at your option) version 3 or any later version + accepted by the membership of KDE e.V. (or its successor approved + by the membership of KDE e.V.), which shall act as a proxy + defined in Section 14 of version 3 of the license. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#ifndef OUTLINE_H +#define OUTLINE_H + +#include "xkbobject.h" + +class Outline : public XkbObject +{ + Q_OBJECT +#define P(type, name) \ +private: \ + Q_PROPERTY(type name READ auto_prop_##name CONSTANT) \ +public: \ + type auto_prop_##name () const { return outline-> name ; } + + P(unsigned short, corner_radius) + + Q_PROPERTY(QVariantList points MEMBER points CONSTANT) + +public: + Outline(XkbOutlinePtr outline_, XkbDescPtr xkb_, QObject *parent = nullptr); + + XkbOutlinePtr outline = nullptr; + QVariantList points; +}; + +#endif // OUTLINE_H diff --git a/kcms/keyboard/tastenbrett/outline.cpp b/kcms/keyboard/tastenbrett/outline.cpp new file mode 100644 --- /dev/null +++ b/kcms/keyboard/tastenbrett/outline.cpp @@ -0,0 +1,34 @@ +/* + Copyright 2019 Harald Sitter + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of + the License or (at your option) version 3 or any later version + accepted by the membership of KDE e.V. (or its successor approved + by the membership of KDE e.V.), which shall act as a proxy + defined in Section 14 of version 3 of the license. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#include "outline.h" + +#include +#include + +Outline::Outline(XkbOutlinePtr outline_, XkbDescPtr xkb_, QObject *parent) + : XkbObject(xkb_, parent) + , outline(outline_) +{ + for (int i = 0; i < outline->num_points; ++i) { + const auto p = outline->points + i; + points.push_back(QPoint(p->x, p->y)); + } +} diff --git a/kcms/keyboard/tastenbrett/qml.qrc b/kcms/keyboard/tastenbrett/qml.qrc new file mode 100644 --- /dev/null +++ b/kcms/keyboard/tastenbrett/qml.qrc @@ -0,0 +1,12 @@ + + + qml/main.qml + qml/ShapeCanvas.qml + qml/Key.qml + qml/KeyCapLabel.qml + qml/KeyCap.qml + qml/IndicatorDoodad.qml + qml/TextDoodad.qml + qml/ShapeDoodad.qml + + diff --git a/kcms/keyboard/tastenbrett/qml/IndicatorDoodad.qml b/kcms/keyboard/tastenbrett/qml/IndicatorDoodad.qml new file mode 100644 --- /dev/null +++ b/kcms/keyboard/tastenbrett/qml/IndicatorDoodad.qml @@ -0,0 +1,26 @@ +/* + Copyright 2019 Harald Sitter + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of + the License or (at your option) version 3 or any later version + accepted by the membership of KDE e.V. (or its successor approved + by the membership of KDE e.V.), which shall act as a proxy + defined in Section 14 of version 3 of the license. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +import QtQuick 2.12 + +ShapeDoodad { + lineWidth: 0 // indicators can be tiny. don't draw the stroke, it may overlap the fill + fillStyle: doodad.on ? activePalette.highlight : disabledPalette.light +} diff --git a/kcms/keyboard/tastenbrett/qml/Key.qml b/kcms/keyboard/tastenbrett/qml/Key.qml new file mode 100644 --- /dev/null +++ b/kcms/keyboard/tastenbrett/qml/Key.qml @@ -0,0 +1,85 @@ +/* + Copyright 2019 Harald Sitter + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of + the License or (at your option) version 3 or any later version + accepted by the membership of KDE e.V. (or its successor approved + by the membership of KDE e.V.), which shall act as a proxy + defined in Section 14 of version 3 of the license. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +import QtQuick 2.12 +import QtQuick.Controls 2.5 + +ShapeCanvas { + id: root + + property QtObject key + property variant keyColor: key.pressed ? activePalette.highlight : activePalette.button + property variant labelColor: key.pressed ? activePalette.highlightedText : activePalette.buttonText + + shape: key ? key.shape : null + strokeSyle: activePalette.shadow + fillStyle: keyColor + + onKeyColorChanged: requestPaint() + + KeyCap { + key: parent.key + + anchors.fill: parent + anchors.margins: 22 // arbitrary spacing to key outlines + } + + Component.onCompleted: { + if (!parent || !parent.row) { + // There's implicit layout logic below when used inside a row. + // Key may also be used standalone, so skip the layout bits. + return; + } + + if (parent.row.orientation === Qt.Horizontal) { + x = 0 + + for (var i in parent.children) { + // find the furthest sibling -> it is our nearst one + var sibling = parent.children[i] + if (sibling === this) { + continue + } + x = Math.max(x, sibling.x + sibling.width) + } + if (x > 0) { + x += key.gap // found a sibling, gap us from it + } + + y = shape.bounds.y + } else { + y = 0 + + for (var i in parent.children) { + // find the furthest sibling -> it is our nearst one + var sibling = parent.children[i] + if (sibling === this) { + continue + } + y = Math.max(y, sibling.y + sibling.height) + } + if (y > 0) { + y += key.gap // found a sibling, gap us from it + } + + x = shape.bounds.x + } + } +} diff --git a/kcms/keyboard/tastenbrett/qml/KeyCap.qml b/kcms/keyboard/tastenbrett/qml/KeyCap.qml new file mode 100644 --- /dev/null +++ b/kcms/keyboard/tastenbrett/qml/KeyCap.qml @@ -0,0 +1,63 @@ +/* + Copyright 2019 Harald Sitter + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of + the License or (at your option) version 3 or any later version + accepted by the membership of KDE e.V. (or its successor approved + by the membership of KDE e.V.), which shall act as a proxy + defined in Section 14 of version 3 of the license. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +import QtQuick 2.12 + +Item { + property QtObject key + + // NB: we scale hight only by a portion of the available space if + // some of the levels aren't there. Visually it looks weird when some + // labels are full center, so let's still bias them towards an edge, but + // increase the height ever so slightly + + KeyCapLabel { + id: topLeft + width: topRight.text == "" ? parent.width : parent.width / 2.0 + height: (bottomLeft.text == "" && bottomRight.text == "") ? parent.height / 1.7 : parent.height /2.0 + anchors.top: parent.top + anchors.left: parent.left + text: key.cap.topLeft + } + KeyCapLabel { + id: topRight + width: parent.width /2.0 + height: parent.height /2.0 + anchors.top: parent.top + anchors.right: parent.right + text: key.cap.topRight + } + KeyCapLabel { + id: bottomLeft + width: bottomRight.text == "" ? parent.width : parent.width / 2.0 + height: (topLeft.text == "" && topRight.text == "") ? parent.height / 1.7 : parent.height /2.0 + anchors.bottom: parent.bottom + anchors.left: parent.left + text: key.cap.bottomLeft + } + KeyCapLabel { + id: bottomRight + width: parent.width /2.0 + height: parent.height /2.0 + anchors.bottom: parent.bottom + anchors.right: parent.right + text: key.cap.bottomRight + } +} diff --git a/kcms/keyboard/tastenbrett/qml/KeyCapLabel.qml b/kcms/keyboard/tastenbrett/qml/KeyCapLabel.qml new file mode 100644 --- /dev/null +++ b/kcms/keyboard/tastenbrett/qml/KeyCapLabel.qml @@ -0,0 +1,31 @@ +/* + Copyright 2019 Harald Sitter + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of + the License or (at your option) version 3 or any later version + accepted by the membership of KDE e.V. (or its successor approved + by the membership of KDE e.V.), which shall act as a proxy + defined in Section 14 of version 3 of the license. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +import QtQuick 2.12 +import QtQuick.Controls 2.5 + +Label { + elide: Text.ElideRight + color: labelColor // from parent scope + + fontSizeMode: Text.Fit + minimumPixelSize: 6 + font.pixelSize: parent.height +} diff --git a/kcms/keyboard/tastenbrett/qml/ShapeCanvas.qml b/kcms/keyboard/tastenbrett/qml/ShapeCanvas.qml new file mode 100644 --- /dev/null +++ b/kcms/keyboard/tastenbrett/qml/ShapeCanvas.qml @@ -0,0 +1,110 @@ +/* + Copyright 2019 Harald Sitter + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of + the License or (at your option) version 3 or any later version + accepted by the membership of KDE e.V. (or its successor approved + by the membership of KDE e.V.), which shall act as a proxy + defined in Section 14 of version 3 of the license. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +import QtQuick 2.12 +import QtQuick.Controls 2.5 + +Canvas { + property QtObject shape + property variant strokeSyle: "yellow" + property variant fillStyle: "steelblue" + // Only draw one outline. Outlines are tricky because xkb has no + // concept of displaying text on top of the shapes. IOW: it + // only thinks about blank keys. This means we have no layout + // constraints for our text and as a result we'd have to figure out + // where to put text so it doesn't conflict with any of the drawn + // paths and is inside most/all of them. It's not worth the work... + property int maxOutline: 1 + // use a round number, we divide this by two to balance spacing + property real lineWidth: 4.0 + // scoot away from 0,0 to translation,translation + property real translation: lineWidth / 2.0 + // reduce the scale to account for the scoot of translation + property real scale: Math.min((width - lineWidth) / width, (height - lineWidth) / height) + + id: canvas + width: shape.bounds.width + height: shape.bounds.height + onStrokeSyleChanged: requestPaint() + onFillStyleChanged: requestPaint() + + onPaint: { + var ctx = getContext("2d") + ctx.reset() + ctx.lineWidth = lineWidth + ctx.strokeStyle = strokeSyle + ctx.fillStyle = fillStyle + // Transform the context a bunch. The way strokes work is that + // they extend to the left and right of the path, so with a + // lineWidth of 8 we'll need the entire scene scooted so + // 0,0 becomes 4,4. Since that also would screw up our absolute + // cordinates towards the right (e.g. our width bounds as reported + // by XKB) we also need to then adjust the scale so the entire + // coordinate system so the scene leaves sufficient space at all + // borders. + // i.e. we move the scene so the top and right strokes are fully + // visible and then shrink it so the left and bottom are fully visible. + ctx.translate(translation, translation) + ctx.scale(scale, scale) + + ctx.beginPath() + + for (var i in shape.outlines) { + if (maxOutline && i >= maxOutline) { + break; + } + + var outline = shape.outlines[i] + + if (outline.points.length === 1) { // rect from 0,0 to point + var point = outline.points[0] + + ctx.roundedRect(0, 0, + point.x, point.y, + outline.corner_radius, outline.corner_radius) + } else if (outline.points.length === 2) { // rect from p1 to p2 + var topLeftPoint = outline.points[0] + var bottomRightPoint = outline.points[1] + + ctx.roundedRect(topLeftPoint.x, topLeftPoint.y, + bottomRightPoint.x, bottomRightPoint.y, + outline.corner_radius, outline.corner_radius) + } else { // polygon point to point draw (used for doodads and non-rect keys such as Enter) + for (var j in outline.points) { + var anyPoint = outline.points[j] + if (j < 1) { // move to first point + ctx.moveTo(anyPoint.x, anyPoint.y) + } else { // from there we draw point to point + ctx.lineTo(anyPoint.x, anyPoint.y) + } + + // TODO: should probably draw short of target and then arcTo over the target so we get a round corner? + // Currently shapes are not rounded. + } + } + } + + ctx.closePath() + if (fillStyle) { + ctx.fill() + } + ctx.stroke() + } +} diff --git a/kcms/keyboard/tastenbrett/qml/ShapeDoodad.qml b/kcms/keyboard/tastenbrett/qml/ShapeDoodad.qml new file mode 100644 --- /dev/null +++ b/kcms/keyboard/tastenbrett/qml/ShapeDoodad.qml @@ -0,0 +1,39 @@ +/* + Copyright 2019 Harald Sitter + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of + the License or (at your option) version 3 or any later version + accepted by the membership of KDE e.V. (or its successor approved + by the membership of KDE e.V.), which shall act as a proxy + defined in Section 14 of version 3 of the license. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +import QtQuick 2.12 +import QtQuick.Controls 2.5 + +ShapeCanvas { + property QtObject doodad + + shape: doodad.shape + + x: doodad.left + y: doodad.top + z: doodad.priority + // Unlike sections we'll rotate doodads in whatever way desired. + // They do not contain anything that could be up-side-down + // "accidentally". + rotation: doodad.angle + + strokeSyle: disabledPalette.shadow + fillStyle: doodad.outlineOnly ? null : disabledPalette.button +} diff --git a/kcms/keyboard/tastenbrett/qml/TextDoodad.qml b/kcms/keyboard/tastenbrett/qml/TextDoodad.qml new file mode 100644 --- /dev/null +++ b/kcms/keyboard/tastenbrett/qml/TextDoodad.qml @@ -0,0 +1,41 @@ +/* + Copyright 2019 Harald Sitter + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of + the License or (at your option) version 3 or any later version + accepted by the membership of KDE e.V. (or its successor approved + by the membership of KDE e.V.), which shall act as a proxy + defined in Section 14 of version 3 of the license. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +import QtQuick 2.12 +import QtQuick.Controls 2.5 + +Label { + property QtObject doodad + + x: doodad.left + y: doodad.top + z: doodad.priority + // random note: the width is much larger than desired on pc geoms because + // the geom only defines left anchors and has a forced \n inside + width: doodad.width + height: doodad.height + rotation: doodad.angle + text: doodad.text + color: disabledPalette.buttonText + + fontSizeMode: Text.Fit + minimumPixelSize: 6 + font.pixelSize: height +} diff --git a/kcms/keyboard/tastenbrett/qml/main.qml b/kcms/keyboard/tastenbrett/qml/main.qml new file mode 100644 --- /dev/null +++ b/kcms/keyboard/tastenbrett/qml/main.qml @@ -0,0 +1,207 @@ +/* + Copyright 2019 Harald Sitter + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of + the License or (at your option) version 3 or any later version + accepted by the membership of KDE e.V. (or its successor approved + by the membership of KDE e.V.), which shall act as a proxy + defined in Section 14 of version 3 of the license. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +import QtQuick 2.12 +import QtQuick.Window 2.12 +import QtQuick.Controls 2.5 + +import org.kde.tastenbrett.private 1.0 as XKB + +Window { + id: window + visible: false + width: 1024 + height: 768 + + SystemPalette { id: activePalette; colorGroup: SystemPalette.Active } + SystemPalette { id: disabledPalette; colorGroup: SystemPalette.Disabled } + + function createDoodad(doodad, parent, properties) { + var component = null + if (doodad instanceof XKB.LogoDoodad) { + component = doodadLogoComponent + } else if (doodad instanceof XKB.IndicatorDoodad) { + component = doodadIndicatorComponent + } else if (doodad instanceof XKB.TextDoodad) { + component = doodadTextComponent + } else if (doodad instanceof XKB.ShapeDoodad) { + component = doodadShapeComponent + } + if (component) { + return component.createObject(parent, properties) + } + console.error("Unknown doodad type!", doodad) + return null + } + + Rectangle { + anchors.fill: parent + color: activePalette.window + } + + Item { + id: kbd + width: window.width + height: window.height + + // XKB geometries have a consistent coordinate system within a geometry + // all children follow that system instead of QML. To easily convert + // everything wholesale we'll employ a scale factor. + property real childWidth: childrenRect.x + childrenRect.width + property real childHeight: childrenRect.y + childrenRect.height + // We preserve the ratio and as a result will need to scall either + // with height or width, whichever has less space. + scale: Math.min(width / childWidth, height / childHeight) + transformOrigin: Item.TopLeft + } + + Component { + id: keyComponent + + // Interactable Key + Key { + id: root + + MouseArea { + id: hoverArea + anchors.fill: parent + hoverEnabled: true + } + + ToolTip { + visible: hoverArea.containsMouse + + contentItem: Item { + scale: kbd.scale * 3 // make keys easily redable at 2.5 times the regular size + + Key { + id: keyItem + key: root.key + } + } + + background: null + } + } + } + + Component { + id: doodadShapeComponent + ShapeDoodad {} + } + + Component { + id: doodadIndicatorComponent + IndicatorDoodad {} + } + + Component { + id: doodadTextComponent + TextDoodad {} + } + + Component { + id: doodadLogoComponent + ShapeDoodad { + KeyCapLabel { + anchors.centerIn: parent + color: disabledPalette.buttonText + text: doodad.logo_name + anchors.margins: 22 // arbitrary spacing to key outlines + } + } + } + + Component { + id: rowComponent + + Item { + property QtObject row: null + x: row.left + y: row.top + width: childrenRect.width+4 + height: childrenRect.height+4 + + Component.onCompleted: { + for (var i in row.keys) { + var key = row.keys[i] + keyComponent.createObject(this, { key: key }); + } + } + } + } + + Component { + id: sectionComponent + + Item { + property QtObject section + x: section.left + y: section.top + z: section.priority + // Dimension defintions can be a bit wonky for sections but overally should not + // cause problems even when they are (so long as we don't actually render the + // sections themself) + width: section.width + height: section.height + + // Fix rotation to mod90, we cannot spin around as that'd put the text upside down ;) + // Unclear if spinning around like that is in fact desired for anyting, if so I guess + // we need to counter rotate text or something. + rotation: section.angle != 0 ? section.angle % 90 : section.angle + transformOrigin: Item.TopLeft + + Component.onCompleted: { + for (var i in section.rows) { + var row = section.rows[i] + rowComponent.createObject(this, { row: row }); + } + + for (var i in section.doodads) { + var doodad = section.doodads[i] + createDoodad(doodad, kbd, { doodad: doodad }) + } + + } + } + } + + Component.onCompleted: { + // Based on the geometry aspect we scale either width or height to scale so + // the default size is fitting. NB: geom dimensions are mm! + if (geometry.widthMM >= geometry.heightMM) { + height = width * geometry.heightMM / geometry.widthMM + } else { + width = height * geometry.widthMM / geometry.heightMM + } + + for (var i in geometry.sections) { + var section = geometry.sections[i] + sectionComponent.createObject(kbd, { section: section }); + } + + for (var i in geometry.doodads) { + var doodad = geometry.doodads[i] + createDoodad(doodad, kbd, { doodad: doodad }) + } + + visible = true + } +} diff --git a/kcms/keyboard/tastenbrett/row.h b/kcms/keyboard/tastenbrett/row.h new file mode 100644 --- /dev/null +++ b/kcms/keyboard/tastenbrett/row.h @@ -0,0 +1,53 @@ +/* + Copyright 2019 Harald Sitter + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of + the License or (at your option) version 3 or any later version + accepted by the membership of KDE e.V. (or its successor approved + by the membership of KDE e.V.), which shall act as a proxy + defined in Section 14 of version 3 of the license. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#ifndef ROW_H +#define ROW_H + +#include + +#include "xkbobject.h" + +class Row : public XkbObject +{ + Q_OBJECT + +#define R_P(type, name) \ +private: \ + Q_PROPERTY(type name READ auto_prop_##name CONSTANT) \ +public: \ + type auto_prop_##name () const { return row-> name ; } + +R_P(short, top) +R_P(short, left) + +Q_PROPERTY(Qt::Orientation orientation MEMBER orientation CONSTANT) +Q_PROPERTY(QList keys MEMBER keys CONSTANT) +Q_PROPERTY(QRect bounds MEMBER bounds CONSTANT) +public: + Row(XkbRowPtr row_, XkbDescPtr xkb_, QObject *parent = nullptr); + + XkbRowPtr row = nullptr; + Qt::Orientation orientation = Qt::Horizontal; + QList keys; + QRect bounds; +}; + +#endif // ROW_H diff --git a/kcms/keyboard/tastenbrett/row.cpp b/kcms/keyboard/tastenbrett/row.cpp new file mode 100644 --- /dev/null +++ b/kcms/keyboard/tastenbrett/row.cpp @@ -0,0 +1,35 @@ +/* + Copyright 2019 Harald Sitter + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of + the License or (at your option) version 3 or any later version + accepted by the membership of KDE e.V. (or its successor approved + by the membership of KDE e.V.), which shall act as a proxy + defined in Section 14 of version 3 of the license. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#include "row.h" + +#include "key.h" + +Row::Row(XkbRowPtr row_, XkbDescPtr xkb_, QObject *parent) + : XkbObject(xkb_, parent) + , row(row_) + , orientation(row->vertical ? Qt::Vertical : Qt::Horizontal) + , bounds(QRect(row->bounds.x1, row->bounds.y1, + row->bounds.x2, row->bounds.y2)) +{ + for (int i = 0; i < row->num_keys; ++i) { + keys.push_back(new Key(row->keys + i, xkb, this)); + } +} diff --git a/kcms/keyboard/tastenbrett/section.h b/kcms/keyboard/tastenbrett/section.h new file mode 100644 --- /dev/null +++ b/kcms/keyboard/tastenbrett/section.h @@ -0,0 +1,53 @@ +/* + Copyright 2019 Harald Sitter + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of + the License or (at your option) version 3 or any later version + accepted by the membership of KDE e.V. (or its successor approved + by the membership of KDE e.V.), which shall act as a proxy + defined in Section 14 of version 3 of the license. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#ifndef SECTION_H +#define SECTION_H + +#include "xkbobject.h" + +class Section : public XkbObject +{ + Q_OBJECT + +#define S_P(type, name) \ +private: \ + Q_PROPERTY(type name READ auto_prop_##name CONSTANT) \ +public: \ + type auto_prop_##name () const { return section-> name ; } + + S_P(unsigned char, priority) + S_P(short, top) + S_P(short, left) + S_P(unsigned short, width) + S_P(unsigned short, height) + S_P(short, angle) + + Q_PROPERTY(QList rows MEMBER rows CONSTANT) + Q_PROPERTY(QList doodads MEMBER doodads CONSTANT) +public: + Section(XkbSectionPtr section_, XkbDescPtr xkb_, QObject *parent = nullptr); + + XkbSectionPtr section = nullptr; + QList rows; + QList doodads; +}; + +#endif // SECTION_H diff --git a/kcms/keyboard/tastenbrett/section.cpp b/kcms/keyboard/tastenbrett/section.cpp new file mode 100644 --- /dev/null +++ b/kcms/keyboard/tastenbrett/section.cpp @@ -0,0 +1,52 @@ +/* + Copyright 2019 Harald Sitter + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of + the License or (at your option) version 3 or any later version + accepted by the membership of KDE e.V. (or its successor approved + by the membership of KDE e.V.), which shall act as a proxy + defined in Section 14 of version 3 of the license. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#include "section.h" + +#include + +#include "doodad.h" +#include "row.h" + +Section::Section(XkbSectionPtr section_, XkbDescPtr xkb_, QObject *parent) + : XkbObject(xkb_, parent) + , section(section_) +{ + for (int i = 0; i < section->num_doodads; ++i) { + Doodad *o = Doodad::factorize(section->doodads + i, xkb, this); + if (!o) { + continue; + } + doodads.push_back(o); + } + + for (int i = 0; i < section->num_rows; ++i) { + rows.push_back(new Row(section->rows + i, xkb, this)); + } + + // Sections also contain overlays, that contain overlay rows, that contain + // overlay keys, that are comprised of an "under" name (internal name + // of our Key object) and an "over" name (the overlay to be used instead). + // The intention I presume is to label keys this way. Alas, this seems + // useless to us because that'd ignore key mapping. Our dynamic key cap + // resolution should be yielding more useful cap data than these overlays. + // Because of this we do not actually set our caps to the overlays and ignore + // them entirely. +} diff --git a/kcms/keyboard/tastenbrett/shape.h b/kcms/keyboard/tastenbrett/shape.h new file mode 100644 --- /dev/null +++ b/kcms/keyboard/tastenbrett/shape.h @@ -0,0 +1,42 @@ +/* + Copyright 2019 Harald Sitter + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of + the License or (at your option) version 3 or any later version + accepted by the membership of KDE e.V. (or its successor approved + by the membership of KDE e.V.), which shall act as a proxy + defined in Section 14 of version 3 of the license. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#ifndef SHAPE_H +#define SHAPE_H + +#include + +#include "xkbobject.h" + +class Shape : public XkbObject +{ + Q_OBJECT + + Q_PROPERTY(QList outlines MEMBER outlines CONSTANT) + Q_PROPERTY(QRect bounds MEMBER bounds CONSTANT) +public: + Shape(XkbShapePtr shape_, XkbDescPtr xkb_, QObject *parent = nullptr); + + XkbShapePtr shape = nullptr; + QList outlines; + QRect bounds; +}; + +#endif // SHAPE_H diff --git a/kcms/keyboard/tastenbrett/shape.cpp b/kcms/keyboard/tastenbrett/shape.cpp new file mode 100644 --- /dev/null +++ b/kcms/keyboard/tastenbrett/shape.cpp @@ -0,0 +1,46 @@ +/* + Copyright 2019 Harald Sitter + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of + the License or (at your option) version 3 or any later version + accepted by the membership of KDE e.V. (or its successor approved + by the membership of KDE e.V.), which shall act as a proxy + defined in Section 14 of version 3 of the license. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#include "shape.h" + +#include "outline.h" + +Shape::Shape(XkbShapePtr shape_, XkbDescPtr xkb_, QObject *parent) + : XkbObject(xkb_, parent) + , shape(shape_) + , bounds(QRect(shape->bounds.x1, shape->bounds.y1, + shape->bounds.x2, shape->bounds.y2)) +{ + // Awkward hack. We only ever render one outline because + // otherwise we wouldn't know where to stick labels so they + // don't overlap with any of the outlines. + // Also when primary is not set the first outline is the primary + // outline as per documentation, so effectively we unify behavior + // here by always ensuring the primary outline is the first outline + // and that will be the one that is rendered. + if (shape->primary) { + outlines.push_back(new Outline(shape->primary, xkb, this)); + return; + } + + for (int i = 0; i < shape->num_outlines; ++i) { + outlines.push_back(new Outline(shape->outlines + i, xkb, this)); + } +} diff --git a/kcms/keyboard/tastenbrett/xkbobject.h b/kcms/keyboard/tastenbrett/xkbobject.h new file mode 100644 --- /dev/null +++ b/kcms/keyboard/tastenbrett/xkbobject.h @@ -0,0 +1,52 @@ +/* + Copyright 2019 Harald Sitter + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of + the License or (at your option) version 3 or any later version + accepted by the membership of KDE e.V. (or its successor approved + by the membership of KDE e.V.), which shall act as a proxy + defined in Section 14 of version 3 of the license. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#ifndef XKBOBJECT_H +#define XKBOBJECT_H + +#include + +#include +#include +#include +#include + +// undef generic x stuff. should use kwindowsystem's fixx11h really +#undef Status +#undef None +#undef Bool +#undef CursorShape +#undef KeyPress +#undef KeyRelease +#undef FocusIn +#undef FocusOut +#undef FontChange +#undef Expose +#undef Unsorted + +class XkbObject : public QObject +{ +protected: + XkbObject(XkbDescPtr xkb_, QObject *parent = nullptr); + + XkbDescPtr xkb = nullptr; +}; + +#endif // XKBOBJECT_H diff --git a/kcms/keyboard/tastenbrett/xkbobject.cpp b/kcms/keyboard/tastenbrett/xkbobject.cpp new file mode 100644 --- /dev/null +++ b/kcms/keyboard/tastenbrett/xkbobject.cpp @@ -0,0 +1,28 @@ +/* + Copyright 2019 Harald Sitter + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of + the License or (at your option) version 3 or any later version + accepted by the membership of KDE e.V. (or its successor approved + by the membership of KDE e.V.), which shall act as a proxy + defined in Section 14 of version 3 of the license. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#include "xkbobject.h" + +XkbObject::XkbObject(XkbDescPtr xkb_, QObject *parent) + : QObject(parent) + , xkb(xkb_) +{ + Q_ASSERT(xkb); +} diff --git a/kcms/keyboard/tests/CMakeLists.txt b/kcms/keyboard/tests/CMakeLists.txt --- a/kcms/keyboard/tests/CMakeLists.txt +++ b/kcms/keyboard/tests/CMakeLists.txt @@ -16,42 +16,9 @@ ) endmacro(KEYBOARD_DAEMON_UNIT_TESTS) -macro(KEYBOARD_PREVIEW_UNIT_TESTS _testname) - include_directories("..") - set(test_SRCS ../preview/${_testname}.cpp ../preview/geometry_components.cpp ../xkb_rules.cpp ../debug.cpp) - add_executable(${_testname}_test ${_testname}_test.cpp ${test_SRCS}) - ecm_mark_nongui_executable(${_testname}_test) - ecm_mark_as_test(${_testname}_test) - add_test(NAME kcm-keyboard-${_testname} COMMAND ${_testname}_test) - target_link_libraries(${_testname}_test - Qt5::Concurrent - Qt5::Widgets - Qt5::X11Extras - Qt5::Xml - Qt5::Test - KF5::I18n - KF5::WindowSystem - ${X11_Xkbfile_LIB} - ${X11_LIBRARIES} - ) - set_source_files_properties(${test_SRCS} PROPERTIES COMPILE_FLAGS "-fexceptions") -endmacro(KEYBOARD_PREVIEW_UNIT_TESTS) - - keyboard_daemon_unit_tests(xkb_rules) keyboard_daemon_unit_tests(iso_codes) -find_package(Boost) - -if(Boost_FOUND) - keyboard_preview_unit_tests(geometry_parser) - if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang") - # the default maximum template expansion depth (256) is not enough - set_property(SOURCE ../preview/geometry_parser.cpp APPEND_STRING PROPERTY COMPILE_FLAGS " -ftemplate-depth=512") - endif() -# set_source_files_properties(${preview_SRCS} PROPERTIES COMPILE_FLAGS "-fexceptions") -endif(Boost_FOUND) - add_executable(flags_test flags_test.cpp ../flags.cpp ../x11_helper.cpp ../keyboard_config.cpp ../xkb_rules.cpp ../debug.cpp) ecm_mark_nongui_executable(flags_test) ecm_mark_as_test(flags_test) diff --git a/kcms/keyboard/tests/geometry_parser_test.cpp b/kcms/keyboard/tests/geometry_parser_test.cpp deleted file mode 100644 --- a/kcms/keyboard/tests/geometry_parser_test.cpp +++ /dev/null @@ -1,101 +0,0 @@ -/* - * Copyright (C) 2011 Andriy Rysin (rysin@kde.org) - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -#include - -#include "../preview/geometry_parser.h" - -class GeometryParserTest : public QObject -{ - Q_OBJECT - - -private Q_SLOTS: - void initTestCase() { - } - - void cleanupTestCase() { - } - - void testGeometryParser() { - QString model = QStringLiteral("pc104"); - Geometry geometry = grammar::parseGeometry(model); - - QCOMPARE(geometry.getName(), model); - - model = QStringLiteral("hpdv5"); - geometry = grammar::parseGeometry(model); - - QCOMPARE(geometry.getName(), QString("dv5")); - - model = QStringLiteral("microsoftelite"); - geometry = grammar::parseGeometry(model); - -// QCOMPARE(geometry.getFile(), QString("microsoft")); - QCOMPARE(geometry.getName(), QString("elite")); - -/* - QVERIFY( flags != NULL ); - - QVERIFY( ! flags->getTransparentPixmap().isNull() ); - - const QIcon iconUs(flags->getIcon("us")); - QVERIFY( ! iconUs.isNull() ); - QVERIFY( flags->getIcon("--").isNull() ); - - KeyboardConfig keyboardConfig; - LayoutUnit layoutUnit("us"); - LayoutUnit layoutUnit1("us", "intl"); - layoutUnit1.setDisplayName("usi"); - LayoutUnit layoutUnit2("us", "other"); - - keyboardConfig.indicatorType = KeyboardConfig::SHOW_FLAG; - const QIcon iconUsFlag = flags->getIconWithText(layoutUnit, keyboardConfig); - QVERIFY( ! iconUsFlag.isNull() ); - QCOMPARE( image(iconUsFlag), image(iconUs) ); - - keyboardConfig.indicatorType = KeyboardConfig::SHOW_LABEL; - const QIcon iconUsText = flags->getIconWithText(layoutUnit, keyboardConfig); - QVERIFY( ! iconUsText.isNull() ); - QVERIFY( image(iconUsText) != image(iconUs) ); - - keyboardConfig.layouts.append(layoutUnit1); - QCOMPARE( flags->getShortText(layoutUnit, keyboardConfig), QString("us") ); - QCOMPARE( flags->getShortText(layoutUnit1, keyboardConfig), QString("usi") ); - QCOMPARE( flags->getShortText(layoutUnit2, keyboardConfig), QString("us") ); - - const Rules* rules = Rules::readRules(Rules::NO_EXTRAS); - QCOMPARE( flags->getLongText(layoutUnit, rules), QString("English (US)") ); - QVERIFY( flags->getLongText(layoutUnit1, rules).startsWith("English (US, international with dead keys)") ); - QCOMPARE( flags->getLongText(layoutUnit2, rules), QString("other") ); - - rules = NULL; // when no rules found - QCOMPARE( flags->getLongText(layoutUnit1, rules), QString("us - intl") ); - - flags->clearCache(); -*/ - } - -}; - -// need kde libs for config-workspace.h used in xkb_rules.cpp -// need GUI for xkb protocol -QTEST_MAIN(GeometryParserTest) - -#include "geometry_parser_test.moc" - diff --git a/kcms/keyboard/xkb_rules.h b/kcms/keyboard/xkb_rules.h --- a/kcms/keyboard/xkb_rules.h +++ b/kcms/keyboard/xkb_rules.h @@ -116,30 +116,6 @@ static Rules* readRules(Rules* rules, const QString& filename, bool fromExtras); static QString getRulesName(); static QString findXkbDir(); - -#ifdef NEW_GEOMETRY - class GeometryId { - public: - QString fileName; - QString geoName; - - GeometryId(const GeometryId& other) { - operator=(other); - } - GeometryId(const QString& fileName_, const QString& geoName_): - fileName(fileName_), - geoName(geoName_) {} - - GeometryId& operator=(const GeometryId& geoId) { - fileName = geoId.fileName; - geoName = geoId.geoName; - return *this; - } - }; - - static GeometryId getGeometryId(const QString& model); -#endif - }; #endif /* XKB_RULES_H_ */ diff --git a/kcms/keyboard/xkb_rules.cpp b/kcms/keyboard/xkb_rules.cpp --- a/kcms/keyboard/xkb_rules.cpp +++ b/kcms/keyboard/xkb_rules.cpp @@ -409,86 +409,3 @@ return false; } - -#ifdef NEW_GEOMETRY - -Rules::GeometryId Rules::getGeometryId(const QString& model) { - QString xkbDir = Rules::findXkbDir(); - QString rulesName = Rules::getRulesName(); - QString ruleFileName = QStringLiteral("%1/rules/%2").arg(xkbDir, rulesName); - QFile ruleFile(ruleFileName); - - GeometryId defaultGeoId(QStringLiteral("pc"), QStringLiteral("pc104")); - - if ( ! ruleFile.open(QIODevice::ReadOnly | QIODevice::Text) ){ - qCCritical(KCM_KEYBOARD) << "Unable to open file" << ruleFileName; - return defaultGeoId; - } - - QString modelGeoId = model; - bool inTable = false; - QTextStream in(&ruleFile); - - while (!in.atEnd()) { - QString line = in.readLine().trimmed(); - - if( line.isEmpty() || QRegExp(QStringLiteral("^\\s*//")).indexIn(line) != -1 ) - continue; - - QRegExp modelGroupRegex(QStringLiteral("!\\s*(\\$[a-zA-Z0-9_]+)\\s*=(.*)")); - - if( modelGroupRegex.indexIn(line) != -1 ) { - QStringList parts = modelGroupRegex.capturedTexts(); - QString groupName = parts[1]; - QStringList models = parts[2].split(QRegExp(QStringLiteral("\\s+")), QString::SkipEmptyParts); - -// qCDebug(KCM_KEYBOARD) << "modelGroup definition" << groupName << ":" << models; - if( models.contains(model) ) { - modelGeoId = groupName; - } - continue; - } - - - if( inTable ) { - QRegExp modelTableEntry (QStringLiteral("\\s*(\\$?[a-zA-Z0-9_]+|\\*)\\s*=\\s*([a-zA-Z0-9_]+)\\(([a-zA-Z0-9_%]+)\\)")); - if( modelTableEntry.indexIn(line) == -1 ) { - if( QRegExp(QStringLiteral("^!\\s*")).indexIn(line) != -1 ) - break; - - qCWarning(KCM_KEYBOARD) << "could not parse geometry line" << line; - continue; - } - - QStringList parts = modelTableEntry.capturedTexts(); - QString modelName = parts[1]; - QString fileName = parts[2]; - QString geoName = parts[3]; - if( geoName == QLatin1String("%m") ) { - geoName = model; - } - if( modelName == QLatin1String("*") ) { - defaultGeoId = GeometryId(fileName, geoName); - } - -// qCDebug(KCM_KEYBOARD) << "geo entry" << modelName << fileName << geoName; - - if( modelName == model ) { - return GeometryId(fileName, geoName); - } - - continue; - } - - QRegExp modelTableHeader (QStringLiteral("!\\s+model\\s*=\\s*geometry")); - if( modelTableHeader.indexIn(line) != -1 ) { - inTable = true; - continue; - } - - } - - return defaultGeoId; -} - -#endif