diff --git a/applets/kimpanel/package/contents/ui/main.qml b/applets/kimpanel/package/contents/ui/CompactRepresentation.qml copy from applets/kimpanel/package/contents/ui/main.qml copy to applets/kimpanel/package/contents/ui/CompactRepresentation.qml --- a/applets/kimpanel/package/contents/ui/main.qml +++ b/applets/kimpanel/package/contents/ui/CompactRepresentation.qml @@ -28,14 +28,14 @@ property int visibleButtons: 0 property bool vertical: plasmoid.formFactor == PlasmaCore.Types.Vertical + property PlasmaCore.DataSource dataEngine LayoutMirroring.enabled: !vertical && Qt.application.layoutDirection === Qt.RightToLeft LayoutMirroring.childrenInherit: true Layout.minimumWidth: vertical ? units.iconSizes.small : items.implicitWidth Layout.minimumHeight: !vertical ? units.iconSizes.small : items.implicitHeight Layout.preferredHeight: Layout.minimumHeight - Plasmoid.preferredRepresentation: Plasmoid.fullRepresentation InputPanel { } @@ -49,6 +49,29 @@ property int iconSize: Math.min(units.iconSizeHints.panel, units.roundToIconSize(Math.min(width, height))) + Item { + width: items.iconSize + height: items.iconSize + StatusIcon { + id: firstStatusIcon + anchors.centerIn: parent + width: items.iconSize + height: items.iconSize + label: dataEngine.data["statusbar"]["CurrentTag"] + icon: dataEngine.data["statusbar"]["CurrentIconName"] + tip: "Currently Active Layout" + + onTriggered: { + if (button == Qt.LeftButton) { + plasmoid.expanded = !plasmoid.expanded; + } + else { + mainContextMenu.openRelative(); + } + } + } + } + Repeater { model: ListModel { id: list @@ -83,6 +106,20 @@ } } + Connections { + target: dataEngine + onDataChanged: { + showMenu(actionMenu, dataEngine.data["statusbar"]["Menu"]); + var data = dataEngine.data["statusbar"]["Properties"]; + if (!data) { + kimpanel.visibleButtons = 0; + return; + } + + timer.restart(); + } + } + function clickHandler(key) { var service = dataEngine.serviceForSource("statusbar"); var operation = service.operationDescription("TriggerProperty"); @@ -149,6 +186,14 @@ id: contextMenu } + MainContextMenu { + id: mainContextMenu + + onConfigureClicked: { + dataSource.data["statusbar"]["LayoutModels"].openConfigDialog(); + } + } + Timer { id: timer interval: 50 @@ -194,21 +239,5 @@ contextMenu.actionList = hiddenActions; } } - - PlasmaCore.DataSource { - id: dataEngine - engine: "kimpanel" - connectedSources: ["statusbar"] - onDataChanged: { - showMenu(actionMenu, dataEngine.data["statusbar"]["Menu"]); - var data = dataEngine.data["statusbar"]["Properties"]; - if (!data) { - kimpanel.visibleButtons = 0; - return; - } - - timer.restart(); - } - } } diff --git a/applets/kimpanel/package/contents/ui/MainContextMenu.qml b/applets/kimpanel/package/contents/ui/MainContextMenu.qml new file mode 100644 --- /dev/null +++ b/applets/kimpanel/package/contents/ui/MainContextMenu.qml @@ -0,0 +1,32 @@ +import QtQuick 2.0 +import org.kde.plasma.core 2.0 as PlasmaCore +import org.kde.plasma.components 2.0 as PlasmaComponents +import org.kde.plasma.plasmoid 2.0 + +PlasmaComponents.ContextMenu { + + signal configureClicked(); + + placement: { + if (plasmoid.location == PlasmaCore.Types.LeftEdge) { + return PlasmaCore.Types.RightPosedTopAlignedPopup; + } else if (plasmoid.location == PlasmaCore.Types.TopEdge) { + return PlasmaCore.Types.BottomPosedLeftAlignedPopup; + } else if (plasmoid.location == PlasmaCore.Types.RightEdge) { + return PlasmaCore.Types.LeftPosedTopAlignedPopup; + } else { + return PlasmaCore.Types.TopPosedLeftAlignedPopup; + } + } + + PlasmaComponents.MenuItem { + id: configureItem + text: i18n("Configure Keyboard..."); + icon: "configure" + + onClicked: { + configureClicked(); + } + } + +} diff --git a/applets/kimpanel/package/contents/ui/main.qml b/applets/kimpanel/package/contents/ui/main.qml --- a/applets/kimpanel/package/contents/ui/main.qml +++ b/applets/kimpanel/package/contents/ui/main.qml @@ -24,190 +24,96 @@ import org.kde.kquickcontrolsaddons 2.0 Item { - id: kimpanel - property int visibleButtons: 0 + id: root - property bool vertical: plasmoid.formFactor == PlasmaCore.Types.Vertical - - LayoutMirroring.enabled: !vertical && Qt.application.layoutDirection === Qt.RightToLeft - LayoutMirroring.childrenInherit: true - - Layout.minimumWidth: vertical ? units.iconSizes.small : items.implicitWidth - Layout.minimumHeight: !vertical ? units.iconSizes.small : items.implicitHeight - Layout.preferredHeight: Layout.minimumHeight - Plasmoid.preferredRepresentation: Plasmoid.fullRepresentation - - InputPanel { } + Text { + id: textMetric + visible: false + // translated but not used, we just need length/height + text: i18n("Arbitrary String Which Says Something") + } - Flow { - id: items - width: parent.width - height: parent.height - x: (parent.width - childrenRect.width) / 2 - y: (parent.height - childrenRect.height) / 2 - flow: kimpanel.vertical ? Flow.LeftToRight : Flow.TopToBottom + Plasmoid.fullRepresentation: Item { + id: dialogItem + Layout.minimumWidth: units.gridUnit * 12 + Layout.minimumHeight: units.gridUnit * 12 - property int iconSize: Math.min(units.iconSizeHints.panel, units.roundToIconSize(Math.min(width, height))) + ListView { + id: view + anchors.fill: parent + focus: true - Repeater { - model: ListModel { - id: list - dynamicRoles: true - } + model: dataSource.data["statusbar"]["LayoutList"] delegate: Item { - id: iconDelegate - width: items.iconSize - height: items.iconSize - StatusIcon { - id: statusIcon - anchors.centerIn: parent - width: items.iconSize - height: items.iconSize - label: model.label - tip: model.tip - icon: model.icon - hint: model.hint - onTriggered : { - if (button == Qt.LeftButton) { - clickHandler(model.key); - // clickHandler will trigger the menu, but we have to wait for - // the menu data. So we have to set the visual parent ahead. - actionMenu.visualParent = statusIcon; - } else { - contextMenu.open(statusIcon, {key: model.key, label: model.label}); - } - } + id: listdelegate + height: textMetric.paintedHeight * 2 + + anchors { + left: parent.left + right: parent.right } - } - } - } - function clickHandler(key) { - var service = dataEngine.serviceForSource("statusbar"); - var operation = service.operationDescription("TriggerProperty"); - operation.key = key; - service.startOperationCall(operation); - } + PlasmaCore.IconItem { + id: icon + source: "checkmark" + height: parent.height + width: height + visible: index == dataSource.data["statusbar"]["CurrentLayoutIndex"] + } - function action(key) { - var service = dataEngine.serviceForSource("statusbar"); - var operation = service.operationDescription(key); - service.startOperationCall(operation); - } + PlasmaComponents.Label { + text: model.description + anchors { + verticalCenter: parent.verticalCenter + left: icon.right + right: parent.right + leftMargin: 10 + rightMargin: 10 + } - function hideAction(key) { - // We must use assignment to change the configuration property, - // otherwise it won't get notified. - var hiddenList = plasmoid.configuration.hiddenList; - if (hiddenList.indexOf(key) === -1) { - hiddenList.push(key); - plasmoid.configuration.hiddenList = hiddenList; - } - timer.restart(); - } + verticalAlignment: Text.AlignVCenter + elide: Text.ElideRight + } - function showAction(key) { - // We must use assignment to change the configuration property, - // otherwise it won't get notified. - var hiddenList = plasmoid.configuration.hiddenList; - var index = hiddenList.indexOf(key); - if (index !== -1) { - hiddenList.splice(index, 1); - plasmoid.configuration.hiddenList = hiddenList; - } - timer.restart(); - } + MouseArea { + height: parent.height + 15 + anchors { left: parent.left; right: parent.right;} + hoverEnabled: true - function showMenu(menu, menuData) { - if (!menuData) { - return; - } + onClicked: { + dataSource.data["statusbar"]["LayoutModels"].switchLayout(index); + } - if (menuData["timestamp"] > menu.timestamp) { - menu.timestamp = menuData["timestamp"]; - var actionList = []; - for (var i = 0; i < menuData["props"].length; i++ ) { - actionList.push({"actionId": menuData["props"][i].key, "icon": menuData["props"][i].icon, "text": menuData["props"][i].label, hint: menuData["props"][i].hint}); + onEntered: { + view.currentIndex = index; + } + } } - if (actionList.length > 0) { - menu.actionList = actionList; - menu.open(); + + highlight: PlasmaComponents.Highlight { + hover: true } - } - } - ActionMenu { - property var timestamp: 0; - id: actionMenu - onActionClicked: { - clickHandler(actionId); + highlightMoveDuration: 250 + highlightMoveVelocity: 2 } } - ContextMenu { - id: contextMenu + Plasmoid.compactRepresentation: CompactRepresentation { + dataEngine: dataSource } - Timer { - id: timer - interval: 50 - onTriggered: { - var data = dataEngine.data["statusbar"]["Properties"]; - if (!data) { - return; - } - var count = list.count; - var c = 0, i; - var hiddenActions = []; - for (i = 0; i < data.length; i ++) { - if (plasmoid.configuration.hiddenList.indexOf(data[i].key) !== -1) { - hiddenActions.push({'key': data[i].key, - 'icon': data[i].icon, - 'label': data[i].label}); - } else { - c = c + 1; - } - } - if (c < count) { - list.remove(c, count - c); - } - kimpanel.visibleButtons = c; - - c = 0; - for (i = 0; i < data.length; i ++) { - if (plasmoid.configuration.hiddenList.indexOf(data[i].key) !== -1) { - continue; - } - var itemData = {'key': data[i].key, - 'icon': data[i].icon, - 'label': data[i].label, - 'tip': data[i].tip, - 'hint': data[i].hint }; - if (c < count) { - list.set(c, itemData); - } else { - list.append(itemData); - } - c = c + 1; - } - contextMenu.actionList = hiddenActions; - } - } + property int visibility: PlasmaCore.Types.HiddenStatus + Plasmoid.status: visibility PlasmaCore.DataSource { - id: dataEngine + id: dataSource engine: "kimpanel" connectedSources: ["statusbar"] onDataChanged: { - showMenu(actionMenu, dataEngine.data["statusbar"]["Menu"]); - var data = dataEngine.data["statusbar"]["Properties"]; - if (!data) { - kimpanel.visibleButtons = 0; - return; - } - - timer.restart(); + root.visibility = dataSource.data["statusbar"]["Visibility"]? + PlasmaCore.Types.ActiveStatus : PlasmaCore.Types.HiddenStatus; } } } diff --git a/dataengines/kimpanel/CMakeLists.txt b/dataengines/kimpanel/CMakeLists.txt --- a/dataengines/kimpanel/CMakeLists.txt +++ b/dataengines/kimpanel/CMakeLists.txt @@ -23,6 +23,7 @@ KF5::Plasma KF5::Service Qt5::DBus + kcm_keyboard_layoutmodel ) kcoreaddons_desktop_to_json(plasma_engine_kimpanel plasma-dataengine-kimpanel.desktop) diff --git a/dataengines/kimpanel/kimpanelagent.h b/dataengines/kimpanel/kimpanelagent.h --- a/dataengines/kimpanel/kimpanelagent.h +++ b/dataengines/kimpanel/kimpanelagent.h @@ -26,10 +26,12 @@ #include #include #include +#include class QDBusServiceWatcher; class Impanel2Adaptor; class ImpanelAdaptor; +class LayoutListModels; class PanelAgent: public QObject, protected QDBusContext { @@ -48,8 +50,8 @@ void lookupTablePageDown(); void movePreeditCaret(int pos); void triggerProperty(const QString& key); + LayoutListModels *models() const; -public: // PROPERTIES public Q_SLOTS: // METHODS void UpdateLookupTable(const QStringList &labels, const QStringList &candis, @@ -68,6 +70,9 @@ const QStringList &attrlists, bool hasPrev, bool hasNext, int cursor, int layout); void serviceUnregistered(const QString& service); + void updateShowStatus(); + void updateConfig(); + void updateCurrentLayoutIndex(); Q_SIGNALS: // signals that from kimpanel @@ -104,18 +109,24 @@ void showAux(bool to_show); void showLookupTable(bool to_show); void updateLookupTableCursor(int pos); + void showPlasmoid(bool to_show); + void currentLayoutChanged(QString const& label, QString const& iconName); private: bool m_show_aux; bool m_show_preedit; bool m_show_lookup_table; + bool m_show_layout_indicator; + bool m_show_single; int m_spot_x; int m_spot_y; QString m_currentService; QStringList cached_props; ImpanelAdaptor* adaptor; Impanel2Adaptor* adaptor2; QDBusServiceWatcher* watcher; + QDBusInterface* m_kdedIface; + LayoutListModels* m_models; }; #endif // KIMPANEL_AGENT_H diff --git a/dataengines/kimpanel/kimpanelagent.cpp b/dataengines/kimpanel/kimpanelagent.cpp --- a/dataengines/kimpanel/kimpanelagent.cpp +++ b/dataengines/kimpanel/kimpanelagent.cpp @@ -31,11 +31,25 @@ #include #include +#include "input_sources.h" +#include "layout_list_models.h" + +#include +#include + +#include "input_sources.h" +#include "layout_list_models.h" + +#include +#include + PanelAgent::PanelAgent(QObject *parent) : QObject(parent) ,adaptor(new ImpanelAdaptor(this)) ,adaptor2(new Impanel2Adaptor(this)) ,watcher(new QDBusServiceWatcher(this)) + ,m_kdedIface(new QDBusInterface("org.kde.keyboard", "/Layouts", "org.kde.KeyboardLayouts")) + ,m_models(new LayoutListModels(this)) { watcher->setConnection(QDBusConnection::sessionBus()); watcher->setWatchMode(QDBusServiceWatcher::WatchForUnregistration); @@ -78,6 +92,12 @@ QStringLiteral("ExecMenu"), this, SLOT(ExecMenu(QStringList))); connect(watcher, SIGNAL(serviceUnregistered(QString)), this, SLOT(serviceUnregistered(QString))); + connect(InputSources::self(), &InputSources::currentSourceChanged, this, &PanelAgent::updateShowStatus); + connect(m_kdedIface, SIGNAL(configChanged()), this, SLOT(updateConfig())); + connect(m_models, &LayoutListModels::currentLayoutIndexChanged, + this, &PanelAgent::updateCurrentLayoutIndex); + + updateConfig(); } PanelAgent::~PanelAgent() @@ -99,6 +119,57 @@ } } +void PanelAgent::updateShowStatus() +{ + bool show = false; + + if (InputSources::self()->currentSource() == InputSources::Sources::XkbSource) { + if (m_show_layout_indicator) { + if (m_models->configuredLayoutListModel()->rowCount() > 1 || m_show_single) { + show = true; + } + } + } + else { + show = true; + } + + emit showPlasmoid(show); +} + +void PanelAgent::updateConfig() +{ + m_models->loadConfig(); + + KConfigGroup config( + KSharedConfig::openConfig(QStringLiteral("kxkbrc"), KConfig::NoGlobals), + QStringLiteral("Layout")); + + m_show_layout_indicator = config.readEntry("ShowLayoutIndicator", true); + m_show_single = config.readEntry("ShowSingle", false); + + updateShowStatus(); +} + +void PanelAgent::updateCurrentLayoutIndex() +{ + int new_idx = m_models->currentLayoutIndex(); + + // TODO: make a "short name" role and use that + QString name = m_models->currentLayoutListModel()->data( + m_models->currentLayoutListModel()->index(new_idx, 0), + LayoutListModelBase::Roles::ShortNameRole).toString(); + + QString iconName = m_models->currentIconName(); + + emit currentLayoutChanged(name, iconName); +} + +LayoutListModels *PanelAgent::models() const +{ + return m_models; +} + void PanelAgent::configure() { emit Configure(); @@ -207,6 +278,8 @@ void PanelAgent::created() { + updateShowStatus(); + updateCurrentLayoutIndex(); emit PanelCreated(); emit PanelCreated2(); } diff --git a/dataengines/kimpanel/kimpaneldataengine.cpp b/dataengines/kimpanel/kimpaneldataengine.cpp --- a/dataengines/kimpanel/kimpaneldataengine.cpp +++ b/dataengines/kimpanel/kimpaneldataengine.cpp @@ -23,6 +23,7 @@ #include "kimpanelinputpanelcontainer.h" #include "kimpanelstatusbarcontainer.h" #include "config-kimpanel.h" +#include "layout_list_models.h" #include #include diff --git a/dataengines/kimpanel/kimpanelstatusbarcontainer.h b/dataengines/kimpanel/kimpanelstatusbarcontainer.h --- a/dataengines/kimpanel/kimpanelstatusbarcontainer.h +++ b/dataengines/kimpanel/kimpanelstatusbarcontainer.h @@ -39,6 +39,9 @@ void execDialog(const KimpanelProperty &prop); void execMenu(const QList &prop_list); + void showPlasmoid(bool visible); + void setCurrentLayout(QString const& tag, QString const& iconName); + private: PanelAgent* m_panelAgent; QList< KimpanelProperty > m_props; diff --git a/dataengines/kimpanel/kimpanelstatusbarcontainer.cpp b/dataengines/kimpanel/kimpanelstatusbarcontainer.cpp --- a/dataengines/kimpanel/kimpanelstatusbarcontainer.cpp +++ b/dataengines/kimpanel/kimpanelstatusbarcontainer.cpp @@ -21,6 +21,10 @@ #include "kimpanelservice.h" #include "kimpanelagent.h" #include "kimpaneldataengine.h" +#include "input_sources.h" +#include "layout_list_models.h" + +#include KimpanelStatusBarContainer::KimpanelStatusBarContainer(QObject* parent, PanelAgent* panelAgent): DataContainer(parent), @@ -30,6 +34,25 @@ connect(m_panelAgent, SIGNAL(registerProperties(QList)), this, SLOT(registerProperties(QList))); connect(m_panelAgent, SIGNAL(execMenu(QList)), this, SLOT(execMenu(QList))); connect(m_panelAgent, SIGNAL(execDialog(KimpanelProperty)), this, SLOT(execDialog(KimpanelProperty))); + connect(m_panelAgent, &PanelAgent::showPlasmoid, this, &KimpanelStatusBarContainer::showPlasmoid); + connect(m_panelAgent, &PanelAgent::currentLayoutChanged, this, &KimpanelStatusBarContainer::setCurrentLayout); + setData("LayoutList", QVariant::fromValue(panelAgent->models()->currentLayoutListModel())); + setData("LayoutModels", QVariant::fromValue(panelAgent->models())); +} + +void KimpanelStatusBarContainer::showPlasmoid(bool visible) +{ + setData("Visibility", visible); + checkForUpdate(); +} + +void KimpanelStatusBarContainer::setCurrentLayout(const QString &tag, const QString &iconName) +{ + qDebug() << tag << iconName; + setData("CurrentLayoutIndex", m_panelAgent->models()->currentLayoutIndex()); + setData("CurrentTag", tag); + setData("CurrentIconName", iconName); + checkForUpdate(); } Plasma::Service* KimpanelStatusBarContainer::service(QObject* parent) @@ -42,12 +65,14 @@ void KimpanelStatusBarContainer::updateProperty(const KimpanelProperty& property) { - int i = 0; - for (i = 0; i < m_props.size(); i ++) { + for (int i = 0; i < m_props.size(); i++) { if (m_props[i].key == property.key) { m_props[i] = property; QList varList; Q_FOREACH(const KimpanelProperty & prop, m_props) { + if (prop.key == "/Fcitx/logo" || prop.key == "/Fcitx/im") { + continue; + } varList << prop.toMap(); } setData(QStringLiteral("Properties"), varList); @@ -62,6 +87,9 @@ m_props = props; QList varList; Q_FOREACH(const KimpanelProperty & prop, m_props) { + if (prop.key == "/Fcitx/logo" || prop.key == "/Fcitx/im") { + continue; + } varList << prop.toMap(); } setData(QStringLiteral("Properties"), varList); diff --git a/kcms/keyboard/CMakeLists.txt b/kcms/keyboard/CMakeLists.txt --- a/kcms/keyboard/CMakeLists.txt +++ b/kcms/keyboard/CMakeLists.txt @@ -1,175 +1,3 @@ -add_definitions(-DTRANSLATION_DOMAIN=\"kcmkeyboard\") - -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) -elseif (UDEV_FOUND) - set(HAVE_UDEV ON) -else() - 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 - keyboard_daemon.cpp - layout_memory.cpp - layout_memory_persister.cpp - udev_helper.cpp - x11_helper.cpp - xinput_helper.cpp - xkb_helper.cpp - keyboard_config.cpp - keyboard_hardware.cpp - bindings.cpp -# next are temporary for sys tray UI - layout_tray_icon.cpp - layouts_menu.cpp - flags.cpp - xkb_rules.cpp -) - -ecm_qt_declare_logging_category(kded_keyboard_SRCS - HEADER debug.h - IDENTIFIER KCM_KEYBOARD - CATEGORY_NAME org.kde.kcm_keyboard - DEFAULT_SEVERITY Warning) - - -include_directories(${CMAKE_CURRENT_BINARY_DIR}) -add_library(kded_keyboard MODULE ${kded_keyboard_SRCS}) -set_target_properties(kded_keyboard PROPERTIES OUTPUT_NAME keyboard) -kcoreaddons_desktop_to_json(kded_keyboard keyboard.desktop SERVICE_TYPES kdedmodule.desktop) - -target_link_libraries(kded_keyboard - Qt5::Concurrent - Qt5::Widgets - Qt5::X11Extras - Qt5::Xml - KF5::ConfigCore - KF5::CoreAddons - KF5::DBusAddons - KF5::GlobalAccel - KF5::I18n - KF5::Notifications - KF5::Service - KF5::WindowSystem - KF5::Plasma - KF5::XmlGui - KF5::GuiAddons - KF5::IconThemes - XCB::XCB - XCB::XKB - ${X11_LIBRARIES} - ${X11_Xkbfile_LIB} - ) - -if (HAVE_XINPUT) - target_link_libraries(kded_keyboard ${X11_Xinput_LIB}) -endif() - -if (HAVE_UDEV) - target_link_libraries(kded_keyboard ${UDEV_LIBS}) -endif() - -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 - kcm_keyboard_widget.cpp - kcm_view_models.cpp - kcm_add_layout_dialog.cpp - keyboard_config.cpp - x11_helper.cpp - xkb_helper.cpp - xkb_rules.cpp - flags.cpp - iso_codes.cpp - kcmmisc.cpp - bindings.cpp - ${preview_SRCS} ) - -ecm_qt_declare_logging_category(kcm_keyboard_PART_SRCS - HEADER debug.h - IDENTIFIER KCM_KEYBOARD - CATEGORY_NAME org.kde.kcm_keyboard - DEFAULT_SEVERITY Warning) - -ki18n_wrap_ui(kcm_keyboard_PART_SRCS kcm_keyboard.ui kcm_add_layout_dialog.ui kcmmiscwidget.ui) - -add_library(kcm_keyboard MODULE ${kcm_keyboard_PART_SRCS}) - -target_link_libraries(kcm_keyboard - Qt5::Concurrent - Qt5::Widgets - Qt5::X11Extras - Qt5::Xml - KF5::KCMUtils - KF5::GlobalAccel - KF5::I18n - KF5::KIOCore - KF5::KIOWidgets - KF5::WindowSystem - KF5::Plasma - KF5::XmlGui - KF5::GuiAddons - KF5::IconThemes - XCB::XCB - XCB::XKB - ${X11_Xkbfile_LIB} - ${X11_LIBRARIES} - ${text_paint_LIB} -) - -install(TARGETS kcm_keyboard DESTINATION ${KDE_INSTALL_PLUGINDIR} ) - -install( FILES kcm_keyboard.desktop DESTINATION ${KDE_INSTALL_KSERVICES5DIR} ) - -# Images - -add_subdirectory( pics ) - -configure_file(config-keyboard.h.cmake ${CMAKE_CURRENT_BINARY_DIR}/config-keyboard.h) - -# Unit tests -if(BUILD_TESTING) - find_package(Qt5Test ${QT_MIN_VERSION} CONFIG REQUIRED) - add_subdirectory( tests ) -endif() +add_subdirectory(layoutmodel) +add_subdirectory(kcmui) +add_subdirectory(daemon) diff --git a/kcms/keyboard/Messages.sh b/kcms/keyboard/Messages.sh deleted file mode 100755 --- a/kcms/keyboard/Messages.sh +++ /dev/null @@ -1,4 +0,0 @@ -#! /usr/bin/env bash -$EXTRACTRC kcm*.ui >> rc.cpp -$XGETTEXT *.cpp -o $podir/kcmkeyboard.pot -rm -f rc.cpp diff --git a/kcms/keyboard/README b/kcms/keyboard/README deleted file mode 100644 --- a/kcms/keyboard/README +++ /dev/null @@ -1,44 +0,0 @@ -This is new project to replace keyboard (kcmmisc) and kxkb -to manage keyboard harware configuration and layouts. - -Components: - -kcm_init: -* no kcm_init - all initialization (including after keyboard hot-plug) is done by kded daemon - -Keyboard daemon: -* configures keyboard layouts on start -* provides DBUS API "org.kde.KXKB/kxkb" -* listens to window/desktop switching if layout switch mode is not global -* listens to new keyboard devices and reinitializes keyboard layouts and hardware settings -* listens to Global KDE Shortcut to switch layouts -* listens to Global Shortcut settings change -* listens to keyboard configuration changes -* provides systray icon for layout - -Keyboard applet: -* displays current layout with text and (optionally flag) -* allows to toggle layouts by click or set them with context menu - -Layout widget: -* displays current layout with text embedded in another widget (e.g. lock dialog) -* currently only short text (no flag or long text) -* dynamically loaded as a plugin - -KCM Module: -* allows to configure keyboard hardware, layouts and xkb options (advanced) - -Advantages (over old code): -* One UI module to configure keyboard layouts and hardware -* Allows to configure keyboard model/xkb options without configuring layouts -* Less cluttered layout configuration control (add layout is separate) -* Layout control/DBus interface is separate from the indicator -* Does not require libxklvier -* Takes language names from iso-codes project -* Takes country names/translations from xkeyboard-config project -* Information about current layouts is always taken from X server, so should be more robust -* Cleaner code (rewritten from scratch) -* Due to many points above should start faster (though no benchmarks performed) - -New features: -* Allow selection of keyboard layout by language diff --git a/kcms/keyboard/TODO b/kcms/keyboard/TODO deleted file mode 100644 --- a/kcms/keyboard/TODO +++ /dev/null @@ -1,37 +0,0 @@ -Tests: -* tests - -Core: -* better handling when layouts set manually and not present in config - -KCM UI: -* use listboxes instead of combos in add layout dialog -* allow multiple layouts to be added in same dialog? - -KCM UI cleanup: -* layouts, sizes, alignment etc in kcm - -plasma applet: - -kxkb part: -* tooltip (currently does not work in lockdlg for some reason) - -tray icon: - -Code cleanup: -* rules, iso_codes: - better error handling - -Improvement: -* remove XInput libs from plasma applet and layout widget (find a nicer way) -* optimize fetching groups and layouts (cache them) / fetch current group directly -* refactor/optimize/clean the code -* refactor client code for D-BUS API to use library instead? - -External improvements: -* Add KSharedConfig::configChanged() signal -* make iso-codes external package -* make flags external package - -Documentation: -* update documentation for keyboard module 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 @@ -6,4 +6,6 @@ #cmakedefine NEW_GEOMETRY +#cmakedefine FCITX4_FCITX_CONFIG_FOUND + #endif // CONFIG_KEYBOARD_H diff --git a/kcms/keyboard/daemon/CMakeLists.txt b/kcms/keyboard/daemon/CMakeLists.txt new file mode 100644 --- /dev/null +++ b/kcms/keyboard/daemon/CMakeLists.txt @@ -0,0 +1,73 @@ + +### kded daemon ### + +option(HAVE_XINPUT "X11 XInput" OFF) +option(NEW_GEOMETRY "Keyboard geometry preview" OFF) + +if (X11_Xinput_FOUND) + set(HAVE_XINPUT ON) +else() + message(STATUS "X11 XInput is not found, either is required to keep layouts with keyboard hotplugging") +endif() + +set( kded_keyboard_SRCS + keyboard_daemon.cpp + x11_helper.cpp + xinput_helper.cpp + xkb_helper.cpp + keyboard_hardware.cpp + bindings.cpp +) + +if ("${CMAKE_BUILD_TYPE}" MATCHES "Debug") + set(logging_severity Debug) +else() + set(logging_severity Warning) +endif() + +ecm_qt_declare_logging_category(kded_keyboard_SRCS + HEADER debug.h + IDENTIFIER KCM_KEYBOARD + CATEGORY_NAME org.kde.kcm_keyboard + DEFAULT_SEVERITY ${logging_severity}) + + +add_library(kded_keyboard MODULE ${kded_keyboard_SRCS}) +set_target_properties(kded_keyboard PROPERTIES OUTPUT_NAME keyboard) +kcoreaddons_desktop_to_json(kded_keyboard keyboard.desktop SERVICE_TYPES kdedmodule.desktop) + +target_include_directories(kded_keyboard PRIVATE + ${CMAKE_CURRENT_BINARY_DIR}) + +target_link_libraries(kded_keyboard + Qt5::Concurrent + Qt5::Widgets + Qt5::X11Extras + Qt5::Xml + KF5::ConfigCore + KF5::CoreAddons + KF5::DBusAddons + KF5::GlobalAccel + KF5::I18n + KF5::Notifications + KF5::Service + KF5::WindowSystem + KF5::Plasma + KF5::XmlGui + KF5::GuiAddons + KF5::IconThemes + + kcm_keyboard_layoutmodel + ) + +if (HAVE_XINPUT) + target_link_libraries(kded_keyboard ${X11_Xinput_LIB}) +endif() + +if (HAVE_UDEV) + target_link_libraries(kded_keyboard ${UDEV_LIBS}) +endif() + +install( TARGETS kded_keyboard DESTINATION ${KDE_INSTALL_PLUGINDIR}/kf5/kded ) + +configure_file(../config-keyboard.h.cmake ${CMAKE_CURRENT_BINARY_DIR}/config-keyboard.h) diff --git a/kcms/keyboard/bindings.h b/kcms/keyboard/daemon/bindings.h rename from kcms/keyboard/bindings.h rename to kcms/keyboard/daemon/bindings.h --- a/kcms/keyboard/bindings.h +++ b/kcms/keyboard/daemon/bindings.h @@ -22,7 +22,7 @@ #include -struct Rules; +struct XkbRules; struct LayoutUnit; template class QList; @@ -34,11 +34,11 @@ QAction* getToggleAction(); // KAction* getAction(const LayoutUnit& layoutUnit); - QAction* createLayoutShortcutActon(const LayoutUnit& layoutUnit, const Rules* rules, bool autoload); +// QAction* createLayoutShortcutActon(const LayoutUnit& layoutUnit, const XkbRules* rules, bool autoload); // KAction* setShortcut(LayoutUnit& layoutUnit, const QKeySequence& keySequence, const Rules* rules); - void setLayoutShortcuts(QList& layoutUnits, const Rules* rules); +// void setLayoutShortcuts(QList& layoutUnits, const XkbRules* rules); void setToggleShortcut(const QKeySequence& keySequence); - void loadLayoutShortcuts(QList& layoutUnits, const Rules* rules); +// void loadLayoutShortcuts(QList& layoutUnits, const XkbRules* rules); void resetLayoutShortcuts(); private: diff --git a/kcms/keyboard/bindings.cpp b/kcms/keyboard/daemon/bindings.cpp rename from kcms/keyboard/bindings.cpp rename to kcms/keyboard/daemon/bindings.cpp --- a/kcms/keyboard/bindings.cpp +++ b/kcms/keyboard/daemon/bindings.cpp @@ -27,7 +27,6 @@ #include #include "x11_helper.h" -#include "flags.h" static const char actionName[] = I18N_NOOP("Switch to Next Keyboard Layout"); @@ -57,10 +56,10 @@ { return action(0); } - -QAction* KeyboardLayoutActionCollection::createLayoutShortcutActon(const LayoutUnit& layoutUnit, const Rules* rules, bool autoload) +/* +QAction* KeyboardLayoutActionCollection::createLayoutShortcutActon(const LayoutUnit& layoutUnit, const XkbRules* rules, bool autoload) { - QString longLayoutName = Flags::getLongText( layoutUnit, rules ); + QString longLayoutName = getLongText(layoutUnit, rules); QString actionName = QStringLiteral("Switch keyboard layout to "); actionName += longLayoutName; QAction* action = addAction( actionName ); @@ -77,7 +76,7 @@ } return action; } - +*/ void KeyboardLayoutActionCollection::setToggleShortcut(const QKeySequence& keySequence) { KGlobalAccel::self()->setShortcut(getToggleAction(), QList() << keySequence, KGlobalAccel::NoAutoloading); @@ -99,8 +98,8 @@ //// } // return action; //} - -void KeyboardLayoutActionCollection::setLayoutShortcuts(QList& layoutUnits, const Rules* rules) +/* +void KeyboardLayoutActionCollection::setLayoutShortcuts(QList& layoutUnits, const XkbRules* rules) { for (QList::iterator i = layoutUnits.begin(); i != layoutUnits.end(); ++i) { LayoutUnit& layoutUnit = *i; @@ -110,8 +109,9 @@ } qCDebug(KCM_KEYBOARD) << "Cleaning component shortcuts on save" << KGlobalAccel::cleanComponent(COMPONENT_NAME); } - -void KeyboardLayoutActionCollection::loadLayoutShortcuts(QList& layoutUnits, const Rules* rules) +*/ +/* +void KeyboardLayoutActionCollection::loadLayoutShortcuts(QList& layoutUnits, const XkbRules* rules) { for (QList::iterator i = layoutUnits.begin(); i != layoutUnits.end(); ++i) { LayoutUnit& layoutUnit = *i; @@ -128,7 +128,7 @@ } qCDebug(KCM_KEYBOARD) << "Cleaning component shortcuts on load" << KGlobalAccel::cleanComponent(COMPONENT_NAME); } - +*/ //KAction* KeyboardLayoutActionCollection::getAction(const LayoutUnit& layoutUnit) //{ // for(int i=1; i #include +#include +#include -#include "layout_memory.h" -#include "keyboard_dbus.h" +#include "../keyboard_dbus.h" #include "bindings.h" +#include "layout_list_models.h" +#include "../fcitx/fcitxqtinputmethodproxy.h" + class XInputEventNotifier; -class LayoutTrayIcon; -class KeyboardConfig; -struct Rules; +struct XkbRules; -class Q_DECL_EXPORT KeyboardDaemon : public KDEDModule -{ +class Q_DECL_EXPORT KeyboardDaemon : public KDEDModule { Q_OBJECT Q_CLASSINFO("D-Bus Interface", "org.kde.KeyboardLayouts") - KeyboardConfig keyboardConfig; - KeyboardLayoutActionCollection *actionCollection; + LayoutListModels* m_layoutListModels; + int m_currentLayoutIndex; + + KeyboardLayoutActionCollection* actionCollection; XInputEventNotifier* xEventNotifier; - LayoutTrayIcon* layoutTrayIcon; - LayoutMemory layoutMemory; - LayoutUnit currentLayout; - const Rules* rules; + QTimer configureKeyboardTimer; + QTimer configureMouseTimer; + + bool isXEventRegistered; + + FcitxQtInputMethodProxy m_fcitxDBusProxy; + + QString updateCurrentLayout(int newLayoutIndex); void registerListeners(); void registerShortcut(); void unregisterListeners(); void unregisterShortcut(); - void setupTrayIcon(); private Q_SLOTS: - void switchToNextLayout(); + void switchToNextLayout(); void configureKeyboard(); void configureMouse(); void layoutChanged(); void layoutMapChanged(); - bool setLayout(QAction* action); + bool setLayout(QAction* action); public Q_SLOTS: - Q_SCRIPTABLE bool setLayout(const QString& layout); - Q_SCRIPTABLE QString getCurrentLayout(); - Q_SCRIPTABLE QStringList getLayoutsList(); - Q_SCRIPTABLE QString getLayoutDisplayName(const QString &layout); + Q_SCRIPTABLE bool setLayout(const QString& layout); + Q_SCRIPTABLE QString getCurrentLayout(); + Q_SCRIPTABLE QStringList getLayoutsList(); + Q_SCRIPTABLE QString getLayoutDisplayName(const QString& layout); Q_SIGNALS: - Q_SCRIPTABLE void currentLayoutChanged(QString layout); - Q_SCRIPTABLE void layoutListChanged(); + Q_SCRIPTABLE void currentLayoutChanged(QString layout); + Q_SCRIPTABLE void layoutListChanged(); + Q_SCRIPTABLE void configChanged(); public: - KeyboardDaemon(QObject *parent, const QList&); + KeyboardDaemon(QObject* parent, const QList&); ~KeyboardDaemon() override; }; diff --git a/kcms/keyboard/daemon/keyboard_daemon.cpp b/kcms/keyboard/daemon/keyboard_daemon.cpp new file mode 100644 --- /dev/null +++ b/kcms/keyboard/daemon/keyboard_daemon.cpp @@ -0,0 +1,370 @@ +/* + * 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. + */ + +#include "keyboard_daemon.h" +#include "debug.h" + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "input_sources.h" +#include "../keyboard_dbus.h" +#include "../xkb_rules.h" +#include "bindings.h" +#include "keyboard_hardware.h" +#include "x11_helper.h" +#include "xinput_helper.h" +#include "xkb_helper.h" + +// TODO: implement switching policy + +K_PLUGIN_FACTORY_WITH_JSON(KeyboardFactory, + "keyboard.json", + registerPlugin();) + +KeyboardDaemon::KeyboardDaemon(QObject* parent, const QList&) + : KDEDModule(parent) + , m_layoutListModels(new LayoutListModels(this)) + , m_currentLayoutIndex(0) + , actionCollection(nullptr) + , xEventNotifier(nullptr) + , m_fcitxDBusProxy("org.fcitx.Fcitx", "/inputmethod", QDBusConnection::sessionBus()) +{ + if (!X11Helper::xkbSupported(nullptr)) + return; //TODO: shut down the daemon? + + FcitxQtInputMethodItem::registerMetaType(); + + // Register DBus Service + QDBusConnection dbus = QDBusConnection::sessionBus(); + dbus.registerService(KEYBOARD_DBUS_SERVICE_NAME); + dbus.registerObject(KEYBOARD_DBUS_OBJECT_PATH, this, QDBusConnection::ExportScriptableSlots | QDBusConnection::ExportScriptableSignals); + dbus.connect(QString(), KEYBOARD_DBUS_OBJECT_PATH, KEYBOARD_DBUS_SERVICE_NAME, KEYBOARD_DBUS_CONFIG_RELOAD_MESSAGE, this, SLOT(configureKeyboard())); + dbus.connect(QString(), KEYBOARD_DBUS_OBJECT_PATH, KEYBOARD_DBUS_SERVICE_NAME, KEYBOARD_DBUS_CONFIG_RELOAD_MESSAGE, this, SIGNAL(configChanged())); + + // Setup timers for applying multiple events at once + configureKeyboardTimer.setSingleShot(true); + configureKeyboardTimer.setInterval(50); + connect(&configureKeyboardTimer, &QTimer::timeout, this, &KeyboardDaemon::configureKeyboard); + configureMouseTimer.setSingleShot(true); + configureMouseTimer.setInterval(50); + connect(&configureMouseTimer, &QTimer::timeout, this, &KeyboardDaemon::configureMouse); + + configureKeyboard(); + registerListeners(); + connect(InputSources::self(), &InputSources::currentSourceChanged, this, &KeyboardDaemon::registerListeners); + connect(InputSources::self(), &InputSources::currentSourceChanged, [this]() { configureMouseTimer.start(); }); + connect(InputSources::self(), &InputSources::currentSourceChanged, [this]() { configureKeyboardTimer.start(); }); +} + +KeyboardDaemon::~KeyboardDaemon() +{ + QDBusConnection dbus = QDBusConnection::sessionBus(); + dbus.disconnect(QString(), KEYBOARD_DBUS_OBJECT_PATH, KEYBOARD_DBUS_SERVICE_NAME, KEYBOARD_DBUS_CONFIG_RELOAD_MESSAGE, this, SLOT(configureKeyboard())); + dbus.unregisterObject(KEYBOARD_DBUS_OBJECT_PATH); + dbus.unregisterService(KEYBOARD_DBUS_SERVICE_NAME); + + unregisterListeners(); + unregisterShortcut(); + + delete xEventNotifier; +} + +QString KeyboardDaemon::updateCurrentLayout(int newLayoutIndex) +{ + m_currentLayoutIndex = newLayoutIndex; + + QString newLayoutSaveName = m_layoutListModels->currentLayoutListModel()->data( + m_layoutListModels->currentLayoutListModel()->index(m_currentLayoutIndex, 0), + LayoutListModelBase::Roles::SaveNameRole).toString(); + QString newLayoutName = m_layoutListModels->currentLayoutListModel()->data( + m_layoutListModels->currentLayoutListModel()->index(m_currentLayoutIndex, 0), + LayoutListModelBase::Roles::NameRole).toString(); + QString newLayoutDesc = m_layoutListModels->currentLayoutListModel()->data( + m_layoutListModels->currentLayoutListModel()->index(m_currentLayoutIndex, 0), + LayoutListModelBase::Roles::DescriptionRole).toString(); + + if (InputSources::self()->currentSource() == InputSources::Sources::FcitxSource) { + FcitxQtInputMethodItemList list = m_fcitxDBusProxy.iMList(); + bool isLatinModeEnabled = m_layoutListModels->currentLayoutListModel()->data( + m_layoutListModels->currentLayoutListModel()->index(m_currentLayoutIndex, 0), + LayoutListModelBase::Roles::IsLatinModeEnabledRole).toBool(); + QString latinModeLayout = m_layoutListModels->currentLayoutListModel()->data( + m_layoutListModels->currentLayoutListModel()->index(m_currentLayoutIndex, 0), + LayoutListModelBase::Roles::LatinModeLayoutRole).toString(); + + qDebug(KCM_KEYBOARD) << newLayoutName << isLatinModeEnabled << latinModeLayout; + + for (int i = 0; i < list.size(); ++i) { + list[i].setEnabled(false); + if (list[i].uniqueName() == newLayoutName) { + list[i].setEnabled(true); + if (isLatinModeEnabled) { + list.move(i, 1); + } else { + list.move(i, 0); + } + } + if (list[i].uniqueName() == latinModeLayout) { + list[i].setEnabled(true); + list.move(i, 0); + } + } + + m_fcitxDBusProxy.setIMList(list); + } + else if (InputSources::self()->currentSource() == InputSources::Sources::XkbSource) { + // Set xkb layouts and variants + QStringList setxkbmapCommandArguments; + QString layout; + QString variant = ""; + + int source = m_layoutListModels->currentLayoutListModel()->data( + m_layoutListModels->currentLayoutListModel()->index(m_currentLayoutIndex, 0), + LayoutListModelBase::Roles::SourceRole).toInt(); + if (source == InputSources::Sources::XkbSource) { + QStringList lv = newLayoutName.split('('); + layout = lv[0]; + if (lv.size() >= 2) { + variant = lv[1].left(lv[1].size() - 1); + } + } + + setxkbmapCommandArguments.append(QStringLiteral("-layout")); + setxkbmapCommandArguments.append(layout); + if (!variant.isEmpty()) { + setxkbmapCommandArguments.append(QStringLiteral("-variant")); + setxkbmapCommandArguments.append(variant); + } + XkbHelper::runConfigLayoutCommand(setxkbmapCommandArguments); + } + + qDebug() << "currentLayoutChanged emitted"; + emit currentLayoutChanged(newLayoutSaveName); + + return newLayoutDesc; +} + +void KeyboardDaemon::configureKeyboard() +{ + qCDebug(KCM_KEYBOARD) << "Configuring keyboard"; + + KConfigGroup config( + KSharedConfig::openConfig(QStringLiteral("kxkbrc"), KConfig::NoGlobals), + QStringLiteral("Layout")); + + m_layoutListModels->loadConfig(); + init_keyboard_hardware(); + + // Reset options + XkbHelper::runConfigLayoutCommand(QStringList() << "-option"); + + // Set keyboard model + QStringList setxkbmapCommandArguments; + QString keyboardModel = config.readEntry("Model", ""); + if (!keyboardModel.isEmpty()) { + setxkbmapCommandArguments.append(QStringLiteral("-model")); + setxkbmapCommandArguments.append(keyboardModel); + } + + // Set advanced options + QString options = config.readEntry("Options", ""); + setxkbmapCommandArguments.append(QStringLiteral("-option")); + setxkbmapCommandArguments.append(options); + + XkbHelper::runConfigLayoutCommand(setxkbmapCommandArguments); + + // Reset index + updateCurrentLayout(0); + + // Re-register shortcut keys + unregisterShortcut(); + registerShortcut(); +} + +void KeyboardDaemon::configureMouse() +{ + QStringList modules; + modules << QStringLiteral("mouse"); + QProcess::startDetached(QStringLiteral("kcminit"), modules); +} + +void KeyboardDaemon::registerShortcut() +{ + if (actionCollection == nullptr) { + actionCollection = new KeyboardLayoutActionCollection(this, false); + + QAction* toggleLayoutAction = actionCollection->getToggleAction(); + connect(toggleLayoutAction, &QAction::triggered, this, &KeyboardDaemon::switchToNextLayout); + qCDebug(KCM_KEYBOARD) << KGlobalAccel::self()->shortcut(toggleLayoutAction); + //actionCollection->loadLayoutShortcuts(keyboardConfig.layouts, rules.data()); + //connect(actionCollection, SIGNAL(actionTriggered(QAction*)), this, SLOT(setLayout(QAction*))); + } +} + +void KeyboardDaemon::unregisterShortcut() +{ + // register KDE keyboard shortcut for switching layouts + if (actionCollection != nullptr) { + disconnect(actionCollection, SIGNAL(actionTriggered(QAction*)), this, SLOT(setLayout(QAction*))); + disconnect(actionCollection->getToggleAction(), &QAction::triggered, this, &KeyboardDaemon::switchToNextLayout); + + delete actionCollection; + actionCollection = nullptr; + } +} + +void KeyboardDaemon::registerListeners() +{ + if (InputSources::self()->currentSource() == InputSources::Sources::XkbSource) { + if (!isXEventRegistered) { + if (xEventNotifier == nullptr) { + xEventNotifier = new XInputEventNotifier(); + } + connect(xEventNotifier, &XInputEventNotifier::newPointerDevice, [this]() { configureMouseTimer.start(); }); + connect(xEventNotifier, &XInputEventNotifier::newKeyboardDevice, [this]() { configureKeyboardTimer.start(); }); + connect(xEventNotifier, &XEventNotifier::layoutMapChanged, this, &KeyboardDaemon::layoutMapChanged); + connect(xEventNotifier, &XEventNotifier::layoutChanged, this, &KeyboardDaemon::layoutChanged); + xEventNotifier->start(); + isXEventRegistered = true; + } + } + else { + unregisterListeners(); + } +} + +void KeyboardDaemon::unregisterListeners() +{ + if (xEventNotifier != nullptr && isXEventRegistered) { + xEventNotifier->stop(); + disconnect(xEventNotifier, &XEventNotifier::layoutChanged, this, &KeyboardDaemon::layoutChanged); + disconnect(xEventNotifier, &XEventNotifier::layoutMapChanged, this, &KeyboardDaemon::layoutMapChanged); + } +} + +void KeyboardDaemon::layoutChanged() +{ + // TODO +} + +void KeyboardDaemon::layoutMapChanged() +{ + //configureKeyboard(); +} + +void KeyboardDaemon::switchToNextLayout() +{ + const int origIdx = m_currentLayoutIndex; + const int layoutCount = m_layoutListModels->currentLayoutListModel()->rowCount(); + if (layoutCount <= 1) { + qWarning(KCM_KEYBOARD) << "Cannot find next layout"; + return; + } + int newIdx = (origIdx + 1) % layoutCount; + + QString layoutName = updateCurrentLayout(newIdx); + + qCDebug(KCM_KEYBOARD) << "Toggling layout " << layoutName; + + // Show a box on the screen indicating the layout change + QDBusMessage msg = QDBusMessage::createMethodCall( + QStringLiteral("org.kde.plasmashell"), + QStringLiteral("/org/kde/osdService"), + QStringLiteral("org.kde.osdService"), + QStringLiteral("kbdLayoutChanged")); + + msg << layoutName; + + QDBusConnection::sessionBus().asyncCall(msg); +} + +bool KeyboardDaemon::setLayout(QAction* action) +{ + if (action == actionCollection->getToggleAction()) + return false; + + QString layoutName = action->data().toString(); + return setLayout(layoutName); +} + +bool KeyboardDaemon::setLayout(const QString& layout) +{ + qDebug() << layout; + const int layoutCount = m_layoutListModels->currentLayoutListModel()->rowCount(); + for (int i = 0; i < layoutCount; ++i) { + QString saveName = m_layoutListModels->currentLayoutListModel()->data( + m_layoutListModels->currentLayoutListModel()->index(i, 0), + LayoutListModelBase::Roles::SaveNameRole).toString(); + + if (saveName == layout) { + updateCurrentLayout(i); + return true; + } + } + return false; +} + +QString KeyboardDaemon::getCurrentLayout() +{ + return m_layoutListModels->currentLayoutListModel()->data( + m_layoutListModels->currentLayoutListModel()->index(m_currentLayoutIndex, 0), + LayoutListModelBase::Roles::SaveNameRole).toString(); +} + +QStringList KeyboardDaemon::getLayoutsList() +{ + QStringList list; + + for (int i = 0; i < m_layoutListModels->currentLayoutListModel()->rowCount(); ++i) { + QString layout = m_layoutListModels->currentLayoutListModel()->data( + m_layoutListModels->currentLayoutListModel()->index(i, 0), + LayoutListModelBase::Roles::SaveNameRole).toString(); + list << layout; + } + return list; +} + +QString KeyboardDaemon::getLayoutDisplayName(const QString &layout) +{ + const int layoutCount = m_layoutListModels->currentLayoutListModel()->rowCount(); + for (int i = 0; i < layoutCount; ++i) { + QString saveName = m_layoutListModels->currentLayoutListModel()->data( + m_layoutListModels->currentLayoutListModel()->index(i, 0), + LayoutListModelBase::Roles::SaveNameRole).toString(); + + if (saveName == layout) { + return m_layoutListModels->currentLayoutListModel()->data( + m_layoutListModels->currentLayoutListModel()->index(i, 0), + LayoutListModelBase::Roles::DescriptionRole).toString(); + } + } + return ""; +} + +#include "keyboard_daemon.moc" diff --git a/kcms/keyboard/keyboard_hardware.h b/kcms/keyboard/daemon/keyboard_hardware.h rename from kcms/keyboard/keyboard_hardware.h rename to kcms/keyboard/daemon/keyboard_hardware.h diff --git a/kcms/keyboard/daemon/keyboard_hardware.cpp b/kcms/keyboard/daemon/keyboard_hardware.cpp new file mode 100644 --- /dev/null +++ b/kcms/keyboard/daemon/keyboard_hardware.cpp @@ -0,0 +1,108 @@ +/* + * 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. + */ + +#include +#include +#include + +#include +#include + +#include + +#include "debug.h" +#include "x11_helper.h" + +#include +#include +#include + +// This code is taken from xset utility from XFree 4.3 (http://www.xfree86.org/) + +static void set_repeatrate(int delay, double rate) +{ + if (!X11Helper::xkbSupported(nullptr)) { + qCCritical(KCM_KEYBOARD) << "Failed to set keyboard repeat rate: xkb is not supported"; + return; + } + + XkbDescPtr xkb = XkbAllocKeyboard(); + if (xkb) { + Display* dpy = QX11Info::display(); + + XkbGetControls(dpy, XkbRepeatKeysMask, xkb); + xkb->ctrls->repeat_delay = static_cast(delay); + xkb->ctrls->repeat_interval = static_cast(floor(1000 / rate + 0.5)); + + XkbSetControls(dpy, XkbRepeatKeysMask, xkb); + XkbFreeKeyboard(xkb, 0, true); + return; + } +} + +enum class TriState { + STATE_ON = 0, + STATE_OFF = 1, + STATE_UNCHANGED = 2 +}; + +const int DEFAULT_REPEAT_DELAY = 600; +const double DEFAULT_REPEAT_RATE = 25.0; + +static int set_repeat_mode(TriState keyboardRepeatMode) +{ + XKeyboardState kbd; + XKeyboardControl kbdc; + + XGetKeyboardControl(QX11Info::display(), &kbd); + + unsigned long flags = 0; + if (keyboardRepeatMode != TriState::STATE_UNCHANGED) { + flags |= KBAutoRepeatMode; + kbdc.auto_repeat_mode = (keyboardRepeatMode == TriState::STATE_ON ? AutoRepeatModeOn : AutoRepeatModeOff); + } + + return XChangeKeyboardControl(QX11Info::display(), flags, &kbdc); +} + +void init_keyboard_hardware() +{ + KConfigGroup config(KSharedConfig::openConfig(QStringLiteral("kcminputrc")), "Keyboard"); + + QString keyRepeatStr = config.readEntry("KeyboardRepeating", "0"); + TriState keyRepeat = TriState::STATE_UNCHANGED; + if (keyRepeatStr == QLatin1String("true") || keyRepeatStr == "0") { + keyRepeat = TriState::STATE_ON; + } else if (keyRepeatStr == QLatin1String("false") || keyRepeatStr == "1") { + keyRepeat = TriState::STATE_OFF; + } + + if (keyRepeat == TriState::STATE_ON) { + int delay_ = config.readEntry("RepeatDelay", DEFAULT_REPEAT_DELAY); + double rate_ = config.readEntry("RepeatRate", DEFAULT_REPEAT_RATE); + set_repeatrate(delay_, rate_); + } + + set_repeat_mode(keyRepeat); + + TriState numlockState = TriState(config.readEntry("NumLock", int(TriState::STATE_UNCHANGED))); + if (numlockState != TriState::STATE_UNCHANGED) { + KModifierKeyInfo keyInfo; + keyInfo.setKeyLocked(Qt::Key_NumLock, numlockState == TriState::STATE_ON); + } +} diff --git a/kcms/keyboard/x11_helper.h b/kcms/keyboard/daemon/x11_helper.h rename from kcms/keyboard/x11_helper.h rename to kcms/keyboard/daemon/x11_helper.h --- a/kcms/keyboard/x11_helper.h +++ b/kcms/keyboard/daemon/x11_helper.h @@ -28,6 +28,7 @@ #include #include + //#include //union _xkb_event; @@ -111,8 +112,7 @@ void layoutMapChanged(); public: - XEventNotifier(); - virtual ~XEventNotifier() {} + XEventNotifier(); virtual void start(); virtual void stop(); @@ -126,106 +126,10 @@ private: int registerForXkbEvents(Display* display); bool isXkbEvent(xcb_generic_event_t* event); - bool isGroupSwitchEvent(_xkb_event* event); - bool isLayoutSwitchEvent(_xkb_event* event); - - int xkbOpcode; -}; - -struct XkbConfig { - QString keyboardModel; - QStringList layouts; - QStringList variants; - QStringList options; - - bool isValid() { return ! layouts.empty(); } -}; - + bool isGroupSwitchEvent(_xkb_event* event); + bool isLayoutSwitchEvent(_xkb_event* event); -struct LayoutUnit { - static const int MAX_LABEL_LENGTH; - - //TODO: move these to private? - QString layout; - QString variant; - - LayoutUnit() {} - explicit LayoutUnit(const QString& fullLayoutName); - LayoutUnit(const QString& layout_, const QString& variant_) { - layout = layout_; - variant = variant_; - } - /*explicit*/ LayoutUnit(const LayoutUnit& layoutUnit) { - layout = layoutUnit.layout; - variant = layoutUnit.variant; - displayName = layoutUnit.displayName; - shortcut = layoutUnit.shortcut; - } - - QString getRawDisplayName() const { return displayName; } - QString getDisplayName() const { return !displayName.isEmpty() ? displayName : layout; } - void setDisplayName(const QString& name) { displayName = name; } - - void setShortcut(const QKeySequence& shortcut) { this->shortcut = shortcut; } - QKeySequence getShortcut() const { return shortcut; } - - bool isEmpty() const { return layout.isEmpty(); } - bool isValid() const { return ! isEmpty(); } - bool operator==(const LayoutUnit& layoutItem) const { - return layout==layoutItem.layout && variant==layoutItem.variant; - } - bool operator!=(const LayoutUnit& layoutItem) const { - return ! (*this == layoutItem); - } - QString toString() const; - -private: - QString displayName; - QKeySequence shortcut; -}; - -struct LayoutSet { - QList layouts; - LayoutUnit currentLayout; - - LayoutSet() {} - - LayoutSet(const LayoutSet& currentLayouts) { - this->layouts = currentLayouts.layouts; - this->currentLayout = currentLayouts.currentLayout; - } - - bool isValid() const { - return currentLayout.isValid() && layouts.contains(currentLayout); - } - - bool operator == (const LayoutSet& currentLayouts) const { - return this->layouts == currentLayouts.layouts - && this->currentLayout == currentLayouts.currentLayout; - } - - LayoutSet& operator = (const LayoutSet& currentLayouts) { - this->layouts = currentLayouts.layouts; - this->currentLayout = currentLayouts.currentLayout; - return *this; - } - - QString toString() const { - QString str(currentLayout.toString()); - str += QLatin1String(": "); - foreach(const LayoutUnit& layoutUnit, layouts) { - str += layoutUnit.toString() + " "; - } - return str; - } - - static QString toString(const QList& layoutUnits) { - QString str; - foreach(const LayoutUnit& layoutUnit, layoutUnits) { - str += layoutUnit.toString() + ","; - } - return str; - } + int xkbOpcode; }; class X11Helper @@ -238,23 +142,6 @@ static const char RIGHT_VARIANT_STR[]; static bool xkbSupported(int* xkbOpcode); - - static void switchToNextLayout(); - static void scrollLayouts(int delta); - static bool isDefaultLayout(); - static bool setDefaultLayout(); - static bool setLayout(const LayoutUnit& layout); - static LayoutUnit getCurrentLayout(); - static LayoutSet getCurrentLayouts(); - static QList getLayoutsList(); - static QStringList getLayoutsListAsString(const QList& layoutsList); - - enum FetchType { ALL, LAYOUTS_ONLY, MODEL_ONLY }; - static bool getGroupNames(Display* dpy, XkbConfig* xkbConfig, FetchType fetchType); - -private: - static unsigned int getGroup(); - static bool setGroup(unsigned int group); }; #endif /* X11_HELPER_H_ */ diff --git a/kcms/keyboard/daemon/x11_helper.cpp b/kcms/keyboard/daemon/x11_helper.cpp new file mode 100644 --- /dev/null +++ b/kcms/keyboard/daemon/x11_helper.cpp @@ -0,0 +1,200 @@ +/* + * 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. + */ + +#include "x11_helper.h" +#include "debug.h" +#include "../xkb_rules.h" + +#define explicit explicit_is_keyword_in_cpp +#include +#undef explicit + +#include +#include +#include + +#include + +#include +#include +#include +#include +#include +#include +#include + +// more information about the limit https://bugs.freedesktop.org/show_bug.cgi?id=19501 +const int X11Helper::MAX_GROUP_COUNT = 4; +const int X11Helper::ARTIFICIAL_GROUP_LIMIT_COUNT = 8; + +const char X11Helper::LEFT_VARIANT_STR[] = "("; +const char X11Helper::RIGHT_VARIANT_STR[] = ")"; + +bool X11Helper::xkbSupported(int* xkbOpcode) +{ + if (!QX11Info::isPlatformX11()) { + return false; + } + // Verify the Xlib has matching XKB extension. + + int major = XkbMajorVersion; + int minor = XkbMinorVersion; + + if (!XkbLibraryVersion(&major, &minor)) + { + qCWarning(KCM_KEYBOARD) << "Xlib XKB extension " << major << '.' << minor << + " != " << XkbMajorVersion << '.' << XkbMinorVersion; + return false; + } + + // Verify the X server has matching XKB extension. + + int opcode_rtrn; + int error_rtrn; + int xkb_opcode; + if( ! XkbQueryExtension(QX11Info::display(), &opcode_rtrn, &xkb_opcode, &error_rtrn, &major, &minor)) { + qCWarning(KCM_KEYBOARD) << "X server XKB extension " << major << '.' << minor << + " != " << XkbMajorVersion << '.' << XkbMinorVersion; + return false; + } + + if( xkbOpcode != NULL ) { + *xkbOpcode = xkb_opcode; + } + + return true; +} + +XEventNotifier::XEventNotifier(): + xkbOpcode(-1) +{ + if( QCoreApplication::instance() == NULL ) { + qCWarning(KCM_KEYBOARD) << "Layout Widget won't work properly without QCoreApplication instance"; + } +} + +void XEventNotifier::start() +{ + qCDebug(KCM_KEYBOARD) << "qCoreApp" << QCoreApplication::instance(); + if( QCoreApplication::instance() != NULL && X11Helper::xkbSupported(&xkbOpcode) ) { + registerForXkbEvents(QX11Info::display()); + + // start the event loop + QCoreApplication::instance()->installNativeEventFilter(this); + } +} + +void XEventNotifier::stop() +{ + if( QCoreApplication::instance() != NULL ) { + //TODO: unregister + // XEventNotifier::unregisterForXkbEvents(QX11Info::display()); + + // stop the event loop + QCoreApplication::instance()->removeNativeEventFilter(this); + } +} + +bool XEventNotifier::isXkbEvent(xcb_generic_event_t* event) +{ +// qDebug() << "event response type:" << (event->response_type & ~0x80) << xkbOpcode << ((event->response_type & ~0x80) == xkbOpcode + XkbEventCode); + return (event->response_type & ~0x80) == xkbOpcode + XkbEventCode; +} + +bool XEventNotifier::processOtherEvents(xcb_generic_event_t* /*event*/) +{ + return true; +} + +bool XEventNotifier::processXkbEvents(xcb_generic_event_t* event) +{ + _xkb_event *xkbevt = reinterpret_cast<_xkb_event *>(event); + if( XEventNotifier::isGroupSwitchEvent(xkbevt) ) { +// qDebug() << "group switch event"; + emit(layoutChanged()); + } + else if( XEventNotifier::isLayoutSwitchEvent(xkbevt) ) { +// qDebug() << "layout switch event"; + emit(layoutMapChanged()); + } + return true; +} + +bool XEventNotifier::nativeEventFilter(const QByteArray &eventType, void *message, long *) +{ +// qDebug() << "event type:" << eventType; + if (eventType == "xcb_generic_event_t") { + xcb_generic_event_t* ev = static_cast(message); + if( isXkbEvent(ev) ) { + processXkbEvents(ev); + } + else { + processOtherEvents(ev); + } + } + return false; +} + +//bool XEventNotifier::x11Event(XEvent * event) +//{ +// // qApp->x11ProcessEvent ( event ); +// if( isXkbEvent(event) ) { +// processXkbEvents(event); +// } +// else { +// processOtherEvents(event); +// } +// return QWidget::x11Event(event); +//} + +bool XEventNotifier::isGroupSwitchEvent(_xkb_event* xkbEvent) +{ +// XkbEvent *xkbEvent = (XkbEvent*) event; +#define GROUP_CHANGE_MASK \ + ( XkbGroupStateMask | XkbGroupBaseMask | XkbGroupLatchMask | XkbGroupLockMask ) + + return xkbEvent->any.xkbType == XkbStateNotify && (xkbEvent->state_notify.changed & GROUP_CHANGE_MASK); +} + +bool XEventNotifier::isLayoutSwitchEvent(_xkb_event* xkbEvent) +{ +// XkbEvent *xkbEvent = (XkbEvent*) event; + + return //( (xkbEvent->any.xkb_type == XkbMapNotify) && (xkbEvent->map.changed & XkbKeySymsMask) ) || +/* || ( (xkbEvent->any.xkb_type == XkbNamesNotify) && (xkbEvent->names.changed & XkbGroupNamesMask) || )*/ + (xkbEvent->any.xkbType == XkbNewKeyboardNotify); +} + +int XEventNotifier::registerForXkbEvents(Display* display) +{ + int eventMask = XkbNewKeyboardNotifyMask | XkbStateNotifyMask; + if( ! XkbSelectEvents(display, XkbUseCoreKbd, eventMask, eventMask) ) { + qCWarning(KCM_KEYBOARD) << "Couldn't select desired XKB events"; + return false; + } + return true; +} + +QString getDisplayText(const QString& layout, const QString& variant, const XkbRules* rules) +{ + if( variant.isEmpty() ) + return layout; + if( rules == nullptr || rules->version == QLatin1String("1.0") ) + return i18nc("layout - variant", "%1 - %2", layout, variant); + return variant; +} diff --git a/kcms/keyboard/xinput_helper.h b/kcms/keyboard/daemon/xinput_helper.h rename from kcms/keyboard/xinput_helper.h rename to kcms/keyboard/daemon/xinput_helper.h diff --git a/kcms/keyboard/xinput_helper.cpp b/kcms/keyboard/daemon/xinput_helper.cpp rename from kcms/keyboard/xinput_helper.cpp rename to kcms/keyboard/daemon/xinput_helper.cpp --- a/kcms/keyboard/xinput_helper.cpp +++ b/kcms/keyboard/daemon/xinput_helper.cpp @@ -45,7 +45,6 @@ #endif #include "x11_helper.h" -#include "udev_helper.h" #include diff --git a/kcms/keyboard/xkb_helper.h b/kcms/keyboard/daemon/xkb_helper.h rename from kcms/keyboard/xkb_helper.h rename to kcms/keyboard/daemon/xkb_helper.h --- a/kcms/keyboard/xkb_helper.h +++ b/kcms/keyboard/daemon/xkb_helper.h @@ -27,8 +27,6 @@ class XkbHelper { public: - static bool initializeKeyboardLayouts(KeyboardConfig& config); - static bool initializeKeyboardLayouts(const QList& layouts); static bool runConfigLayoutCommand(const QStringList& setxkbmapCommandArguments); }; diff --git a/kcms/keyboard/xkb_helper.cpp b/kcms/keyboard/daemon/xkb_helper.cpp rename from kcms/keyboard/xkb_helper.cpp rename to kcms/keyboard/daemon/xkb_helper.cpp --- a/kcms/keyboard/xkb_helper.cpp +++ b/kcms/keyboard/daemon/xkb_helper.cpp @@ -30,9 +30,6 @@ #include -#include "keyboard_config.h" - - static const char SETXKBMAP_EXEC[] = "setxkbmap"; static const char XMODMAP_EXEC[] = "xmodmap"; @@ -97,7 +94,6 @@ executeXmodmap(configFileName); } -//TODO: make private bool XkbHelper::runConfigLayoutCommand(const QStringList& setxkbmapCommandArguments) { QTime timer; @@ -119,6 +115,7 @@ return false; } +/* bool XkbHelper::initializeKeyboardLayouts(const QList& layoutUnits) { QStringList layouts; @@ -138,8 +135,9 @@ return runConfigLayoutCommand(setxkbmapCommandArguments); } - -bool XkbHelper::initializeKeyboardLayouts(KeyboardConfig& config) +*/ +/* +bool XkbHelper::initializeKeyboardLayouts() { QStringList setxkbmapCommandArguments; if( ! config.keyboardModel.isEmpty() ) { @@ -153,10 +151,12 @@ if( config.configureLayouts ) { QStringList layouts; QStringList variants; - QList defaultLayouts = config.getDefaultLayouts(); + QList defaultLayouts = config.getLayouts(); foreach (const LayoutUnit& layoutUnit, defaultLayouts) { - layouts.append(layoutUnit.layout); - variants.append(layoutUnit.variant); + if (layoutUnit.technology == "xkb") { + layouts.append(layoutUnit.layout); + variants.append(layoutUnit.variant); + } } setxkbmapCommandArguments.append(QStringLiteral("-layout")); @@ -182,3 +182,4 @@ } return false; } +*/ diff --git a/kcms/keyboard/fcitx/fcitxqtdbusaddons_export.h b/kcms/keyboard/fcitx/fcitxqtdbusaddons_export.h new file mode 100644 --- /dev/null +++ b/kcms/keyboard/fcitx/fcitxqtdbusaddons_export.h @@ -0,0 +1,41 @@ + +#ifndef FCITXQTDBUSADDONS_EXPORT_H +#define FCITXQTDBUSADDONS_EXPORT_H + +#ifdef FCITXQTDBUSADDONS_STATIC_DEFINE +# define FCITXQTDBUSADDONS_EXPORT +# define FCITXQTDBUSADDONS_NO_EXPORT +#else +# ifndef FCITXQTDBUSADDONS_EXPORT +# ifdef FcitxQt5DBusAddons_EXPORTS + /* We are building this library */ +# define FCITXQTDBUSADDONS_EXPORT __attribute__((visibility("default"))) +# else + /* We are using this library */ +# define FCITXQTDBUSADDONS_EXPORT __attribute__((visibility("default"))) +# endif +# endif + +# ifndef FCITXQTDBUSADDONS_NO_EXPORT +# define FCITXQTDBUSADDONS_NO_EXPORT __attribute__((visibility("hidden"))) +# endif +#endif + +#ifndef FCITXQTDBUSADDONS_DEPRECATED +# define FCITXQTDBUSADDONS_DEPRECATED __attribute__ ((__deprecated__)) +#endif + +#ifndef FCITXQTDBUSADDONS_DEPRECATED_EXPORT +# define FCITXQTDBUSADDONS_DEPRECATED_EXPORT FCITXQTDBUSADDONS_EXPORT FCITXQTDBUSADDONS_DEPRECATED +#endif + +#ifndef FCITXQTDBUSADDONS_DEPRECATED_NO_EXPORT +# define FCITXQTDBUSADDONS_DEPRECATED_NO_EXPORT FCITXQTDBUSADDONS_NO_EXPORT FCITXQTDBUSADDONS_DEPRECATED +#endif + +#define DEFINE_NO_DEPRECATED 0 +#if DEFINE_NO_DEPRECATED +# define FCITXQTDBUSADDONS_NO_DEPRECATED +#endif + +#endif diff --git a/kcms/keyboard/fcitx/fcitxqtinputmethoditem.h b/kcms/keyboard/fcitx/fcitxqtinputmethoditem.h new file mode 100644 --- /dev/null +++ b/kcms/keyboard/fcitx/fcitxqtinputmethoditem.h @@ -0,0 +1,66 @@ +/*************************************************************************** + * Copyright (C) 2011~2012 by CSSlayer * + * * + * 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 St, Fifth Floor, Boston, MA 02110-1301, USA. * + ***************************************************************************/ + +#ifndef FCITX_QT_INPUT_METHOD_ITEM_H +#define FCITX_QT_INPUT_METHOD_ITEM_H + +#include "fcitxqtdbusaddons_export.h" + +// Qt +#include +#include +#include + +class FCITXQTDBUSADDONS_EXPORT FcitxQtInputMethodItem +{ +public: + const QString& name() const; + const QString& uniqueName() const; + const QString& langCode() const; + bool enabled() const; + + void setName(const QString& name); + void setUniqueName(const QString& name); + void setLangCode(const QString& name); + void setEnabled(bool name); + static void registerMetaType(); + + static QString saveName(QString uniqueName); + + inline bool operator < (const FcitxQtInputMethodItem& im) const { + if (m_enabled == true && im.m_enabled == false) + return true; + return false; + } +private: + QString m_name; + QString m_uniqueName; + QString m_langCode; + bool m_enabled; +}; + +typedef QList FcitxQtInputMethodItemList; + +QDBusArgument& operator<<(QDBusArgument& argument, const FcitxQtInputMethodItem& im); +const QDBusArgument& operator>>(const QDBusArgument& argument, FcitxQtInputMethodItem& im); + +Q_DECLARE_METATYPE(FcitxQtInputMethodItem) +Q_DECLARE_METATYPE(FcitxQtInputMethodItemList) + +#endif diff --git a/kcms/keyboard/fcitx/fcitxqtinputmethoditem.cpp b/kcms/keyboard/fcitx/fcitxqtinputmethoditem.cpp new file mode 100644 --- /dev/null +++ b/kcms/keyboard/fcitx/fcitxqtinputmethoditem.cpp @@ -0,0 +1,113 @@ +/*************************************************************************** + * Copyright (C) 2011~2012 by CSSlayer * + * * + * 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 St, Fifth Floor, Boston, MA 02110-1301, USA. * + ***************************************************************************/ + +// Qt +#include +#include + +// self +#include "fcitxqtinputmethoditem.h" + +bool FcitxQtInputMethodItem::enabled() const +{ + return m_enabled; +} + +QString FcitxQtInputMethodItem::saveName(QString uniqueName) +{ + QString prefix = "fcitx-keyboard-"; + if (uniqueName.startsWith(prefix)) { + QString layoutName = uniqueName.right(uniqueName.size() - prefix.size()); + QString layout = layoutName.section("-", 0, 0); + QString variant = layoutName.section("-", 1); + if (variant.isEmpty()) { + return layout; + } + else { + return QString("%1(%2)").arg(layout, variant); + } + } + return "fcitx:" + uniqueName; +} + +const QString& FcitxQtInputMethodItem::langCode() const +{ + return m_langCode; +} +const QString& FcitxQtInputMethodItem::name() const +{ + return m_name; +} +const QString& FcitxQtInputMethodItem::uniqueName() const +{ + return m_uniqueName; +} +void FcitxQtInputMethodItem::setEnabled(bool enable) +{ + m_enabled = enable; +} +void FcitxQtInputMethodItem::setLangCode(const QString& lang) +{ + m_langCode = lang; +} +void FcitxQtInputMethodItem::setName(const QString& name) +{ + m_name = name; +} +void FcitxQtInputMethodItem::setUniqueName(const QString& name) +{ + m_uniqueName = name; +} + +void FcitxQtInputMethodItem::registerMetaType() +{ + qRegisterMetaType("FcitxQtInputMethodItem"); + qDBusRegisterMetaType(); + qRegisterMetaType("FcitxQtInputMethodItemList"); + qDBusRegisterMetaType(); +} + +FCITXQTDBUSADDONS_EXPORT +QDBusArgument& operator<<(QDBusArgument& argument, const FcitxQtInputMethodItem& im) +{ + argument.beginStructure(); + argument << im.name(); + argument << im.uniqueName(); + argument << im.langCode(); + argument << im.enabled(); + argument.endStructure(); + return argument; +} + +FCITXQTDBUSADDONS_EXPORT +const QDBusArgument& operator>>(const QDBusArgument& argument, FcitxQtInputMethodItem& im) +{ + QString name; + QString uniqueName; + QString langCode; + bool enabled; + argument.beginStructure(); + argument >> name >> uniqueName >> langCode >> enabled; + argument.endStructure(); + im.setName(name); + im.setUniqueName(uniqueName); + im.setLangCode(langCode); + im.setEnabled(enabled); + return argument; +} diff --git a/kcms/keyboard/fcitx/fcitxqtinputmethodproxy.h b/kcms/keyboard/fcitx/fcitxqtinputmethodproxy.h new file mode 100644 --- /dev/null +++ b/kcms/keyboard/fcitx/fcitxqtinputmethodproxy.h @@ -0,0 +1,218 @@ +/* + * This file was generated by qdbusxml2cpp version 0.8 + * Command line was: qdbusxml2cpp -N -p fcitxqtinputmethodproxy -c FcitxQtInputMethodProxy org.fcitx.Fcitx.InputMethod.xml -i fcitxqtinputmethoditem.h -i fcitxqtdbusaddons_export.h + * + * qdbusxml2cpp is Copyright (C) 2017 The Qt Company Ltd. + * + * This is an auto-generated file. + * Do not edit! All changes made to it will be lost. + */ + +#ifndef FCITXQTINPUTMETHODPROXY_H +#define FCITXQTINPUTMETHODPROXY_H + +#include +#include +#include +#include +#include +#include +#include +#include +#include "fcitxqtinputmethoditem.h" +#include "fcitxqtdbusaddons_export.h" + +/* + * Proxy class for interface org.fcitx.Fcitx.InputMethod + */ +class FcitxQtInputMethodProxy: public QDBusAbstractInterface +{ + Q_OBJECT +public: + static inline const char *staticInterfaceName() + { return "org.fcitx.Fcitx.InputMethod"; } + +public: + FcitxQtInputMethodProxy(const QString &service, const QString &path, const QDBusConnection &connection, QObject *parent = nullptr); + + ~FcitxQtInputMethodProxy(); + + Q_PROPERTY(QString CurrentIM READ currentIM WRITE setCurrentIM) + inline QString currentIM() const + { return qvariant_cast< QString >(property("CurrentIM")); } + inline void setCurrentIM(const QString &value) + { setProperty("CurrentIM", QVariant::fromValue(value)); } + + Q_PROPERTY(FcitxQtInputMethodItemList IMList READ iMList WRITE setIMList) + inline FcitxQtInputMethodItemList iMList() const + { qDebug() << property("IMList"); + return qvariant_cast< FcitxQtInputMethodItemList >(property("IMList")); } + inline void setIMList(FcitxQtInputMethodItemList value) + { setProperty("IMList", QVariant::fromValue(value)); } + +public Q_SLOTS: // METHODS + inline QDBusPendingReply<> ActivateIM() + { + QList argumentList; + return asyncCallWithArgumentList(QStringLiteral("ActivateIM"), argumentList); + } + + inline QDBusPendingReply<> Configure() + { + QList argumentList; + return asyncCallWithArgumentList(QStringLiteral("Configure"), argumentList); + } + + inline QDBusPendingReply<> ConfigureAddon(const QString &addon) + { + QList argumentList; + argumentList << QVariant::fromValue(addon); + return asyncCallWithArgumentList(QStringLiteral("ConfigureAddon"), argumentList); + } + + inline QDBusPendingReply<> ConfigureIM(const QString &im) + { + QList argumentList; + argumentList << QVariant::fromValue(im); + return asyncCallWithArgumentList(QStringLiteral("ConfigureIM"), argumentList); + } + + inline QDBusPendingReply CreateIC() + { + QList argumentList; + return asyncCallWithArgumentList(QStringLiteral("CreateIC"), argumentList); + } + inline QDBusReply CreateIC(uint &keyval1, uint &state1, uint &keyval2, uint &state2) + { + QList argumentList; + QDBusMessage reply = callWithArgumentList(QDBus::Block, QStringLiteral("CreateIC"), argumentList); + if (reply.type() == QDBusMessage::ReplyMessage && reply.arguments().count() == 5) { + keyval1 = qdbus_cast(reply.arguments().at(1)); + state1 = qdbus_cast(reply.arguments().at(2)); + keyval2 = qdbus_cast(reply.arguments().at(3)); + state2 = qdbus_cast(reply.arguments().at(4)); + } + return reply; + } + + inline QDBusPendingReply CreateICv2(const QString &appname) + { + QList argumentList; + argumentList << QVariant::fromValue(appname); + return asyncCallWithArgumentList(QStringLiteral("CreateICv2"), argumentList); + } + inline QDBusReply CreateICv2(const QString &appname, bool &enable, uint &keyval1, uint &state1, uint &keyval2, uint &state2) + { + QList argumentList; + argumentList << QVariant::fromValue(appname); + QDBusMessage reply = callWithArgumentList(QDBus::Block, QStringLiteral("CreateICv2"), argumentList); + if (reply.type() == QDBusMessage::ReplyMessage && reply.arguments().count() == 6) { + enable = qdbus_cast(reply.arguments().at(1)); + keyval1 = qdbus_cast(reply.arguments().at(2)); + state1 = qdbus_cast(reply.arguments().at(3)); + keyval2 = qdbus_cast(reply.arguments().at(4)); + state2 = qdbus_cast(reply.arguments().at(5)); + } + return reply; + } + + inline QDBusPendingReply CreateICv3(const QString &appname, int pid) + { + QList argumentList; + argumentList << QVariant::fromValue(appname) << QVariant::fromValue(pid); + return asyncCallWithArgumentList(QStringLiteral("CreateICv3"), argumentList); + } + inline QDBusReply CreateICv3(const QString &appname, int pid, bool &enable, uint &keyval1, uint &state1, uint &keyval2, uint &state2) + { + QList argumentList; + argumentList << QVariant::fromValue(appname) << QVariant::fromValue(pid); + QDBusMessage reply = callWithArgumentList(QDBus::Block, QStringLiteral("CreateICv3"), argumentList); + if (reply.type() == QDBusMessage::ReplyMessage && reply.arguments().count() == 6) { + enable = qdbus_cast(reply.arguments().at(1)); + keyval1 = qdbus_cast(reply.arguments().at(2)); + state1 = qdbus_cast(reply.arguments().at(3)); + keyval2 = qdbus_cast(reply.arguments().at(4)); + state2 = qdbus_cast(reply.arguments().at(5)); + } + return reply; + } + + inline QDBusPendingReply<> Exit() + { + QList argumentList; + return asyncCallWithArgumentList(QStringLiteral("Exit"), argumentList); + } + + inline QDBusPendingReply GetCurrentIM() + { + QList argumentList; + return asyncCallWithArgumentList(QStringLiteral("GetCurrentIM"), argumentList); + } + + inline QDBusPendingReply GetCurrentState() + { + QList argumentList; + return asyncCallWithArgumentList(QStringLiteral("GetCurrentState"), argumentList); + } + + inline QDBusPendingReply GetCurrentUI() + { + QList argumentList; + return asyncCallWithArgumentList(QStringLiteral("GetCurrentUI"), argumentList); + } + + inline QDBusPendingReply GetIMAddon(const QString &im) + { + QList argumentList; + argumentList << QVariant::fromValue(im); + return asyncCallWithArgumentList(QStringLiteral("GetIMAddon"), argumentList); + } + + inline QDBusPendingReply<> InactivateIM() + { + QList argumentList; + return asyncCallWithArgumentList(QStringLiteral("InactivateIM"), argumentList); + } + + inline QDBusPendingReply<> ReloadAddonConfig(const QString &addon) + { + QList argumentList; + argumentList << QVariant::fromValue(addon); + return asyncCallWithArgumentList(QStringLiteral("ReloadAddonConfig"), argumentList); + } + + inline QDBusPendingReply<> ReloadConfig() + { + QList argumentList; + return asyncCallWithArgumentList(QStringLiteral("ReloadConfig"), argumentList); + } + + inline QDBusPendingReply<> ResetIMList() + { + QList argumentList; + return asyncCallWithArgumentList(QStringLiteral("ResetIMList"), argumentList); + } + + inline QDBusPendingReply<> Restart() + { + QList argumentList; + return asyncCallWithArgumentList(QStringLiteral("Restart"), argumentList); + } + + inline QDBusPendingReply<> SetCurrentIM(const QString &im) + { + QList argumentList; + argumentList << QVariant::fromValue(im); + return asyncCallWithArgumentList(QStringLiteral("SetCurrentIM"), argumentList); + } + + inline QDBusPendingReply<> ToggleIM() + { + QList argumentList; + return asyncCallWithArgumentList(QStringLiteral("ToggleIM"), argumentList); + } + +Q_SIGNALS: // SIGNALS +}; + +#endif diff --git a/kcms/keyboard/fcitx/fcitxqtinputmethodproxy.cpp b/kcms/keyboard/fcitx/fcitxqtinputmethodproxy.cpp new file mode 100644 --- /dev/null +++ b/kcms/keyboard/fcitx/fcitxqtinputmethodproxy.cpp @@ -0,0 +1,26 @@ +/* + * This file was generated by qdbusxml2cpp version 0.8 + * Command line was: qdbusxml2cpp -N -p fcitxqtinputmethodproxy -c FcitxQtInputMethodProxy org.fcitx.Fcitx.InputMethod.xml -i fcitxqtinputmethoditem.h -i fcitxqtdbusaddons_export.h + * + * qdbusxml2cpp is Copyright (C) 2017 The Qt Company Ltd. + * + * This is an auto-generated file. + * This file may have been hand-edited. Look for HAND-EDIT comments + * before re-generating it. + */ + +#include "fcitxqtinputmethodproxy.h" + +/* + * Implementation of interface class FcitxQtInputMethodProxy + */ + +FcitxQtInputMethodProxy::FcitxQtInputMethodProxy(const QString &service, const QString &path, const QDBusConnection &connection, QObject *parent) + : QDBusAbstractInterface(service, path, staticInterfaceName(), connection, parent) +{ +} + +FcitxQtInputMethodProxy::~FcitxQtInputMethodProxy() +{ +} + diff --git a/kcms/keyboard/fcitx/org.fcitx.Fcitx.InputMethod.xml b/kcms/keyboard/fcitx/org.fcitx.Fcitx.InputMethod.xml new file mode 100644 --- /dev/null +++ b/kcms/keyboard/fcitx/org.fcitx.Fcitx.InputMethod.xml @@ -0,0 +1,81 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/kcms/keyboard/flags.h b/kcms/keyboard/flags.h deleted file mode 100644 --- a/kcms/keyboard/flags.h +++ /dev/null @@ -1,72 +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. - */ - - -#ifndef FLAGS_H_ -#define FLAGS_H_ - -#include -#include -#include - -class QPixmap; -class QIcon; -struct LayoutUnit; -class KeyboardConfig; -struct Rules; -class QPainter; -namespace Plasma { - class Svg; -} - -class Flags : public QObject -{ - Q_OBJECT - -public: - Flags(); - ~Flags() override; - - const QIcon getIcon(const QString& layout); - const QIcon getIconWithText(const LayoutUnit& layoutUnit, const KeyboardConfig& keyboardConfig); - const QPixmap& getTransparentPixmap() const { return *transparentPixmap; } - - static QString getLongText(const LayoutUnit& layoutUnit, const Rules* rules); - static QString getShortText(const LayoutUnit& layoutUnit, const KeyboardConfig& keyboardConfig); - static QString getFullText(const LayoutUnit& layoutUnit, const KeyboardConfig& keyboardConfig, const Rules* rules); - -public Q_SLOTS: - void themeChanged(); - void clearCache(); - -Q_SIGNALS: - void pixmapChanged(); - -private: - QIcon createIcon(const QString& layout); - QString getCountryFromLayoutName(const QString& fullLayoutName) const; - void drawLabel(QPainter& painter, const QString& layoutText, bool flagShown); - Plasma::Svg* getSvg(); - - QMap iconMap; - QMap iconOrTextMap; - QPixmap* transparentPixmap; - Plasma::Svg* svg; -}; - -#endif /* FLAGS_H_ */ diff --git a/kcms/keyboard/flags.cpp b/kcms/keyboard/flags.cpp deleted file mode 100644 --- a/kcms/keyboard/flags.cpp +++ /dev/null @@ -1,297 +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. - */ - -#include "flags.h" - -#include -#include - -#include -#include -#include - -#include -#include -#include -#include -#include -#include - -#include - -#include "x11_helper.h" - -//for text handling -#include "keyboard_config.h" -#include "xkb_rules.h" - - -static const int FLAG_MAX_SIZE = 22; -static const char flagTemplate[] = "kf5/locale/countries/%1/flag.png"; - -int iconSize(int s) -{ - if (s < 16) { - return 16; - } else if (s < 22) { - return 22; - } else if (s < 32) { - return 32; - } else if (s < 48) { - return 48; - } else if (s < 64) { - return 64; - } else { - return 128; - } -} - -Flags::Flags(): - svg(NULL) -{ - transparentPixmap = new QPixmap(FLAG_MAX_SIZE, FLAG_MAX_SIZE); - transparentPixmap->fill(Qt::transparent); -} - -Flags::~Flags() -{ - if( svg != NULL ) { - disconnect(svg, &Plasma::Svg::repaintNeeded, this, &Flags::themeChanged); - delete svg; - } - delete transparentPixmap; -} - -const QIcon Flags::getIcon(const QString& layout) -{ - if( ! iconMap.contains(layout) ) { - iconMap[ layout ] = createIcon(layout); - } - return iconMap[ layout ]; -} - -QIcon Flags::createIcon(const QString& layout) -{ - QIcon icon; - if( ! layout.isEmpty() ) { - QString file; - if( layout == QLatin1String("epo") ) { - file = QStandardPaths::locate(QStandardPaths::GenericDataLocation, QStringLiteral("kcmkeyboard/pics/epo.png")); - } - else { - QString countryCode = getCountryFromLayoutName( layout ); - if( ! countryCode.isEmpty() ) { - file = QStandardPaths::locate(QStandardPaths::GenericDataLocation, QString(flagTemplate).arg(countryCode)); - // qCDebug(KCM_KEYBOARD, ) << "Creating icon for" << layout << "with" << file; - } - } - - if (!file.isEmpty()) { - QImage flagImg; - flagImg.load(file); - const int size = iconSize(qMax(flagImg.width(), flagImg.height())); - QPixmap iconPix(size, size); - iconPix.fill(Qt::transparent); - QRect dest(flagImg.rect()); - dest.moveCenter(iconPix.rect().center()); - - QPainter painter(&iconPix); - painter.drawImage(dest, flagImg); - painter.end(); - - icon.addPixmap(iconPix); - } - } - return icon; -} - - -//static -//const QStringList NON_COUNTRY_LAYOUTS = QString("ara,brai,epo,latam,mao").split(","); - -QString Flags::getCountryFromLayoutName(const QString& layout) const -{ - QString countryCode = layout; - - if( countryCode == QLatin1String("nec_vndr/jp") ) - return QStringLiteral("jp"); - -// if( NON_COUNTRY_LAYOUTS.contain(layout) ) - if( countryCode.length() > 2 ) - return QLatin1String(""); - - return countryCode; -} - -//TODO: move this to some other class? - -QString Flags::getShortText(const LayoutUnit& layoutUnit, const KeyboardConfig& keyboardConfig) -{ - if( layoutUnit.isEmpty() ) - return QStringLiteral("--"); - - QString layoutText = layoutUnit.layout; - - foreach(const LayoutUnit& lu, keyboardConfig.layouts) { - if( layoutUnit.layout == lu.layout && layoutUnit.variant == lu.variant ) { - layoutText = lu.getDisplayName(); - break; - } - } - -//TODO: good autolabel -// if( layoutText == layoutUnit.layout && layoutUnit.getDisplayName() != layoutUnit.layout ) { -// layoutText = layoutUnit.getDisplayName(); -// } - - return layoutText; -} - -QString Flags::getFullText(const LayoutUnit& layoutUnit, const KeyboardConfig& keyboardConfig, const Rules* rules) -{ - QString shortText = Flags::getShortText(layoutUnit, keyboardConfig); - QString longText = Flags::getLongText(layoutUnit, rules); - return i18nc("short layout label - full layout name", "%1 - %2", shortText, longText); -} - -static QString getDisplayText(const QString& layout, const QString& variant, const Rules* rules) -{ - if( variant.isEmpty() ) - return layout; - if( rules == NULL || rules->version == QLatin1String("1.0") ) - return i18nc("layout - variant", "%1 - %2", layout, variant); - return variant; -} - -QString Flags::getLongText(const LayoutUnit& layoutUnit, const Rules* rules) -{ - if( rules == NULL ) { - return getDisplayText(layoutUnit.layout, layoutUnit.variant, rules); - } - - QString layoutText = layoutUnit.layout; - const LayoutInfo* layoutInfo = rules->getLayoutInfo(layoutUnit.layout); - if( layoutInfo != NULL ) { - layoutText = layoutInfo->description; - - if( ! layoutUnit.variant.isEmpty() ) { - const VariantInfo* variantInfo = layoutInfo->getVariantInfo(layoutUnit.variant); - QString variantText = variantInfo != NULL ? variantInfo->description : layoutUnit.variant; - - layoutText = getDisplayText(layoutText, variantText, rules); - } - } - - return layoutText; -} - -static -QString getPixmapKey(const KeyboardConfig& keyboardConfig) -{ - switch(keyboardConfig.indicatorType) { - case KeyboardConfig::SHOW_FLAG: - return QStringLiteral("_fl"); - case KeyboardConfig::SHOW_LABEL_ON_FLAG: - return QStringLiteral("_bt"); - case KeyboardConfig::SHOW_LABEL: - return QStringLiteral("_lb"); - } - return QStringLiteral("_"); // should not happen -} - -void Flags::drawLabel(QPainter& painter, const QString& layoutText, bool flagShown) -{ - QFont font = painter.font(); - QRect rect = painter.window(); - - font.setPointSize(KFontUtils::adaptFontSize(painter, layoutText, rect.size(), rect.height())); - - // we init svg so that we get notification about theme change - getSvg(); - - const QColor textColor = flagShown ? Qt::black : Plasma::Theme().color(Plasma::Theme::TextColor); - - painter.setPen(textColor); - painter.setFont(font); - painter.drawText(rect, Qt::AlignCenter, layoutText); -} - -const QIcon Flags::getIconWithText(const LayoutUnit& layoutUnit, const KeyboardConfig& keyboardConfig) -{ - const QString keySuffix(getPixmapKey(keyboardConfig)); - const QString key(layoutUnit.toString() + keySuffix); - if( iconOrTextMap.contains(key) ) { - return iconOrTextMap[ key ]; - } - - if( keyboardConfig.indicatorType == KeyboardConfig::SHOW_FLAG ) { - QIcon icon = getIcon(layoutUnit.layout); - if( ! icon.isNull() ) { - iconOrTextMap[ key ] = icon; - return icon; - } - } - - QString layoutText = Flags::getShortText(layoutUnit, keyboardConfig); - - const QSize TRAY_ICON_SIZE(128, 128); - QPixmap pixmap = QPixmap(TRAY_ICON_SIZE); - pixmap.fill(Qt::transparent); - - QPainter painter(&pixmap); - painter.setRenderHint(QPainter::SmoothPixmapTransform); -// p.setRenderHint(QPainter::Antialiasing); - - if( keyboardConfig.indicatorType == KeyboardConfig::SHOW_LABEL_ON_FLAG ) { - QIcon iconf = createIcon(layoutUnit.layout); - painter.drawPixmap(pixmap.rect(), iconf.pixmap(TRAY_ICON_SIZE)); - } - - drawLabel(painter, layoutText, keyboardConfig.isFlagShown()); - - painter.end(); - - QIcon icon(pixmap); - iconOrTextMap[ key ] = icon; - - return icon; -} - -Plasma::Svg* Flags::getSvg() -{ - if( svg == NULL ) { - svg = new Plasma::Svg; - svg->setImagePath(QStringLiteral("widgets/labeltexture")); - svg->setContainsMultipleImages(true); - connect(svg, &Plasma::Svg::repaintNeeded, this, &Flags::themeChanged); - } - return svg; -} - -void Flags::themeChanged() -{ -// qCDebug(KCM_KEYBOARD, ) << "Theme changed, new text color" << Plasma::Theme::defaultTheme()->color(Plasma::Theme::TextColor); - clearCache(); - emit pixmapChanged(); -} - -void Flags::clearCache() -{ -// qCDebug(KCM_KEYBOARD, ) << "Clearing flag pixmap cache"; - iconOrTextMap.clear(); -} diff --git a/kcms/keyboard/iso_codes.h b/kcms/keyboard/iso_codes.h deleted file mode 100644 --- a/kcms/keyboard/iso_codes.h +++ /dev/null @@ -1,71 +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. - */ - - -#ifndef ISO_CODES_H_ -#define ISO_CODES_H_ - -#include -#include -#include - -/** - * Represents an item for iso-* standards which consists of attributes and their values - */ -struct IsoCodeEntry: public QMap -{ -}; - -class IsoCodesPrivate; - -/** - * Represents a set of codes for iso-* standards. - * Uses iso-codes project to read and localize the values. - */ -class IsoCodes -{ -public: -// static const char* iso_639; - static const char iso_639_3[]; - - static const char attr_name[]; -// static const char* attr_iso_639_2B_code; -// static const char* attr_iso_639_2T_code; -// static const char* attr_iso_639_1_code; - static const char attr_iso_639_3_id[]; - - /** - * @param isoCode Code for iso standard, i.e. "639", for convenience there's iso_* constants defined - */ - explicit IsoCodes(const QString& isoCode, const QString& isoCodesXmlDir=QStringLiteral("/usr/share/xml/iso-codes")); - ~IsoCodes(); - - /** - * @return Returns the list of items for this iso-* standard - */ - QList getEntryList(); - /** - * @return Returns the item for which given attribute has specified value - */ - const IsoCodeEntry* getEntry(const QString& attributeName, const QString& attributeValue); - -private: - IsoCodesPrivate* const d; -}; - -#endif /* ISO_CODES_H_ */ diff --git a/kcms/keyboard/iso_codes.cpp b/kcms/keyboard/iso_codes.cpp deleted file mode 100644 --- a/kcms/keyboard/iso_codes.cpp +++ /dev/null @@ -1,138 +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. - */ - -#include "iso_codes.h" -#include "debug.h" - -#include - -#include - - -class IsoCodesPrivate { -public: - IsoCodesPrivate(const QString& isoCode_, const QString& isoCodesXmlDir_): - isoCode(isoCode_), - isoCodesXmlDir(isoCodesXmlDir_), - loaded(false) - {} - void buildIsoEntryList(); - - const QString isoCode; - const QString isoCodesXmlDir; - QList isoEntryList; - bool loaded; -}; - -class XmlHandler : public QXmlDefaultHandler -{ -public: - XmlHandler(const QString& isoCode_, QList& isoEntryList_): - isoCode(isoCode_), - qName("iso_"+isoCode+"_entry"), - isoEntryList(isoEntryList_) {} - - bool startElement(const QString &namespaceURI, const QString &localName, - const QString &qName, const QXmlAttributes &attributes) override; -// bool fatalError(const QXmlParseException &exception); -// QString errorString() const; - -private: - const QString isoCode; - const QString qName; - QList& isoEntryList; -}; - -bool XmlHandler::startElement(const QString &/*namespaceURI*/, const QString &/*localName*/, - const QString &qName, const QXmlAttributes &attributes) -{ - if( qName == this->qName ) { - IsoCodeEntry entry; - for(int i=0; i IsoCodes::getEntryList() -{ - if( ! d->loaded ) { - d->buildIsoEntryList(); - } - return d->isoEntryList; -} - -//const char* IsoCodes::iso_639="639"; -const char IsoCodes::iso_639_3[]="639_3"; -const char IsoCodes::attr_name[]="name"; -//const char* IsoCodes::attr_iso_639_2B_code="iso_639_2B_code"; -//const char* IsoCodes::attr_iso_639_2T_code="iso_639_2T_code"; -//const char* IsoCodes::attr_iso_639_1_code="iso_639_1_code"; -const char IsoCodes::attr_iso_639_3_id[]="id"; - -const IsoCodeEntry* IsoCodes::getEntry(const QString& attributeName, const QString& attributeValue) -{ - if( ! d->loaded ) { - d->buildIsoEntryList(); - } - for(QList::Iterator it = d->isoEntryList.begin(); it != d->isoEntryList.end(); ++it) { - const IsoCodeEntry* isoCodeEntry = &(*it); - if( isoCodeEntry->value(attributeName) == attributeValue ) - return isoCodeEntry; - } - return NULL; -} - -void IsoCodesPrivate::buildIsoEntryList() -{ - loaded = true; - - QFile file(QStringLiteral("%1/iso_%2.xml").arg(isoCodesXmlDir, isoCode)); - if( !file.open(QFile::ReadOnly | QFile::Text) ) { - qCCritical(KCM_KEYBOARD) << "Can't open the xml file" << file.fileName(); - return; - } - - XmlHandler xmlHandler(isoCode, isoEntryList); - - QXmlSimpleReader reader; - reader.setContentHandler(&xmlHandler); - reader.setErrorHandler(&xmlHandler); - - QXmlInputSource xmlInputSource(&file); - - if( ! reader.parse(xmlInputSource) ) { - qCCritical(KCM_KEYBOARD) << "Failed to parse the xml file" << file.fileName(); - return; - } - - qCDebug(KCM_KEYBOARD) << "Loaded" << isoEntryList.count() << ("iso entry definitions for iso"+isoCode) << "from" << file.fileName(); -} diff --git a/kcms/keyboard/kcm_add_layout_dialog.h b/kcms/keyboard/kcm_add_layout_dialog.h deleted file mode 100644 --- a/kcms/keyboard/kcm_add_layout_dialog.h +++ /dev/null @@ -1,63 +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. - */ - - -#ifndef KCM_ADD_LAYOUT_DIALOG_H_ -#define KCM_ADD_LAYOUT_DIALOG_H_ - -#include - -#include "keyboard_config.h" -#include "preview/keyboardpainter.h" - -#include - -struct Rules; -class Flags; -class Ui_AddLayoutDialog; - -class AddLayoutDialog: public QDialog -{ - Q_OBJECT - -public: - AddLayoutDialog(const Rules* rules, Flags* flags, const QString& model, bool showLabel, QWidget* parent=NULL); - - 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 - -private: - const Rules* rules; - Flags* flags; - const QString& model; - Ui_AddLayoutDialog* layoutDialogUi; - QString selectedLanguage; - QString selectedLayout; - LayoutUnit selectedLayoutUnit; -}; - - -#endif /* KCM_ADD_LAYOUT_DIALOG_H_ */ diff --git a/kcms/keyboard/kcm_add_layout_dialog.cpp b/kcms/keyboard/kcm_add_layout_dialog.cpp deleted file mode 100644 --- a/kcms/keyboard/kcm_add_layout_dialog.cpp +++ /dev/null @@ -1,178 +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. - */ - -#include "kcm_add_layout_dialog.h" -#include -#include - -#include "xkb_rules.h" -#include "flags.h" -#include "iso_codes.h" - -#include "ui_kcm_add_layout_dialog.h" - -#include - - -AddLayoutDialog::AddLayoutDialog(const Rules* rules_, Flags* flags_, const QString& model_, bool showLabel, QWidget* parent): - QDialog(parent), - rules(rules_), - flags(flags_), - model(model_), - selectedLanguage(QStringLiteral("no_language")) -{ - layoutDialogUi = new Ui_AddLayoutDialog(); - layoutDialogUi->setupUi(this); - - QSet languages; - foreach(const LayoutInfo* layoutInfo, rules->layoutInfos) { - QSet langs = QSet::fromList(layoutInfo->languages); - languages.unite( langs ); - } - IsoCodes isoCodes(IsoCodes::iso_639_3); - foreach(const QString& lang, languages) { - const IsoCodeEntry* isoCodeEntry = isoCodes.getEntry(IsoCodes::attr_iso_639_3_id, lang); -// const IsoCodeEntry* isoCodeEntry = isoCodes.getEntry(IsoCodes::attr_iso_639_2B_code, lang); -// if( isoCodeEntry == NULL ) { -// isoCodeEntry = isoCodes.getEntry(IsoCodes::attr_iso_639_2T_code, lang); -// } - QString name = isoCodeEntry != NULL ? i18n(isoCodeEntry->value(IsoCodes::attr_name).toUtf8()) : lang; - layoutDialogUi->languageComboBox->addItem(name, lang); - } - layoutDialogUi->languageComboBox->model()->sort(0); - layoutDialogUi->languageComboBox->insertItem(0, i18n("Any language"), ""); - layoutDialogUi->languageComboBox->setCurrentIndex(0); - - if( showLabel ) { - layoutDialogUi->labelEdit->setMaxLength(LayoutUnit::MAX_LABEL_LENGTH); - } - else { - layoutDialogUi->labelLabel->setVisible(false); - layoutDialogUi->labelEdit->setVisible(false); - } - - 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 -} - -void AddLayoutDialog::languageChanged(int langIdx) -{ - QString lang = layoutDialogUi->languageComboBox->itemData(langIdx).toString(); - if( lang == selectedLanguage ) - return; - - QPixmap emptyPixmap(layoutDialogUi->layoutComboBox->iconSize()); - emptyPixmap.fill(Qt::transparent); - - layoutDialogUi->layoutComboBox->clear(); - int defaultIndex = -1; - int i = 0; - foreach(const LayoutInfo* layoutInfo, rules->layoutInfos) { - if( lang.isEmpty() || layoutInfo->isLanguageSupportedByLayout(lang) ) { - if( flags ) { - QIcon icon(flags->getIcon(layoutInfo->name)); - if( icon.isNull() ) { - icon = QIcon(emptyPixmap); // align text with no icons - } - layoutDialogUi->layoutComboBox->addItem(icon, layoutInfo->description, layoutInfo->name); - } - else { - layoutDialogUi->layoutComboBox->addItem(layoutInfo->description, layoutInfo->name); - } - - // try to guess best default layout selection for given language - if( ! lang.isEmpty() && defaultIndex == -1 && layoutInfo->isLanguageSupportedByDefaultVariant(lang) ) { - defaultIndex = i; - } - i++; - } - } - if( defaultIndex == -1 ) { - defaultIndex = 0; - } - - layoutDialogUi->layoutComboBox->model()->sort(0); - layoutDialogUi->layoutComboBox->setCurrentIndex(defaultIndex); - layoutChanged(defaultIndex); - - selectedLanguage = lang; -} - -void AddLayoutDialog::layoutChanged(int layoutIdx) -{ - QString layoutName = layoutDialogUi->layoutComboBox->itemData(layoutIdx).toString(); - if( layoutName == selectedLayout ) - return; - - QString lang = layoutDialogUi->languageComboBox->itemData(layoutDialogUi->languageComboBox->currentIndex()).toString(); - - layoutDialogUi->variantComboBox->clear(); - const LayoutInfo* layoutInfo = rules->getLayoutInfo(layoutName); - foreach(const VariantInfo* variantInfo, layoutInfo->variantInfos) { - if( lang.isEmpty() || layoutInfo->isLanguageSupportedByVariant(variantInfo, lang) ) { - layoutDialogUi->variantComboBox->addItem(variantInfo->description, variantInfo->name); - } - } - - layoutDialogUi->variantComboBox->model()->sort(0); - - if( lang.isEmpty() || layoutInfo->isLanguageSupportedByDefaultVariant(lang) ) { - layoutDialogUi->variantComboBox->insertItem(0, i18nc("variant", "Default"), ""); - } - layoutDialogUi->variantComboBox->setCurrentIndex(0); - - layoutDialogUi->labelEdit->setText(layoutName); - - selectedLayout = layoutName; -} - -void AddLayoutDialog::accept() -{ - selectedLayoutUnit.layout = layoutDialogUi->layoutComboBox->itemData(layoutDialogUi->layoutComboBox->currentIndex()).toString(); - selectedLayoutUnit.variant = layoutDialogUi->variantComboBox->itemData(layoutDialogUi->variantComboBox->currentIndex()).toString(); - QString label = layoutDialogUi->labelEdit->text(); - if( label == selectedLayoutUnit.layout ) { - label = QLatin1String(""); - } - selectedLayoutUnit.setDisplayName( label ); - selectedLayoutUnit.setShortcut(layoutDialogUi->kkeysequencewidget->keySequence()); - 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; -} -#endif diff --git a/kcms/keyboard/kcm_add_layout_dialog.ui b/kcms/keyboard/kcm_add_layout_dialog.ui deleted file mode 100644 --- a/kcms/keyboard/kcm_add_layout_dialog.ui +++ /dev/null @@ -1,157 +0,0 @@ - - - AddLayoutDialog - - - - 0 - 0 - 525 - 270 - - - - Add Layout - - - - - - - 0 - 0 - - - - - - - - Layout: - - - - - - - - 0 - 0 - - - - - - - - Shortcut: - - - - - - - Variant: - - - - - - - - - - Label: - - - - - - - Limit selection by language: - - - - - - - - 0 - 0 - - - - - - - - Qt::Horizontal - - - QDialogButtonBox::Cancel|QDialogButtonBox::Ok - - - - - - - - - - Preview - - - - - - - - KKeySequenceWidget - QWidget -
kkeysequencewidget.h
-
-
- - languageComboBox - layoutComboBox - variantComboBox - labelEdit - prevbutton - buttonBox - - - - - buttonBox - accepted() - AddLayoutDialog - accept() - - - 248 - 254 - - - 157 - 274 - - - - - buttonBox - rejected() - AddLayoutDialog - reject() - - - 316 - 260 - - - 286 - 274 - - - - -
diff --git a/kcms/keyboard/kcm_keyboard.h b/kcms/keyboard/kcm_keyboard.h deleted file mode 100644 --- a/kcms/keyboard/kcm_keyboard.h +++ /dev/null @@ -1,47 +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. - */ - - -#ifndef KCM_KEYBOARD_H_ -#define KCM_KEYBOARD_H_ - -#include - -class KCMKeyboardWidget; -class KeyboardConfig; -struct Rules; - -class KCMKeyboard: public KCModule -{ -Q_OBJECT - -public: - KCMKeyboard(QWidget *parent, const QVariantList &); - ~KCMKeyboard() override; - - void save() override; - void load() override; - void defaults() override; - -private: - Rules* rules; - KeyboardConfig* keyboardConfig; - KCMKeyboardWidget *widget; -}; - -#endif /* KCM_KEYBOARD_H_ */ diff --git a/kcms/keyboard/kcm_keyboard.cpp b/kcms/keyboard/kcm_keyboard.cpp deleted file mode 100644 --- a/kcms/keyboard/kcm_keyboard.cpp +++ /dev/null @@ -1,105 +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. - */ - - -#include "kcm_keyboard.h" - -#include -#include -//#include -#include - -#include -#include - -#include "kcm_keyboard_widget.h" -#include "x11_helper.h" -#include "keyboard_config.h" -#include "xkb_rules.h" -#include "keyboard_dbus.h" - -#include "xkb_helper.h" - -//temp hack -#include "kcmmisc.h" - - -K_PLUGIN_FACTORY(KeyboardModuleFactory, registerPlugin();) - -KCMKeyboard::KCMKeyboard(QWidget *parent, const QVariantList &args) - : KCModule(parent) -{ - KAboutData *about = - new KAboutData(QStringLiteral("kcmkeyboard"), i18n("KDE Keyboard Control Module"), - QStringLiteral("1.0"), QString(), KAboutLicense::GPL, - i18n("(c) 2010 Andriy Rysin")); - - setAboutData( about ); - setQuickHelp( i18n("

Keyboard

This control module can be used to configure keyboard" - " parameters and layouts.")); - - - rules = Rules::readRules(Rules::READ_EXTRAS); - - keyboardConfig = new KeyboardConfig(); - - QVBoxLayout *layout = new QVBoxLayout(this); - layout->setMargin(0); -// layout->setSpacing(KDialog::spacingHint()); - - widget = new KCMKeyboardWidget(rules, keyboardConfig, args, parent); - layout->addWidget(widget); - - connect(widget, SIGNAL(changed(bool)), this, SIGNAL(changed(bool))); - - setButtons(Help|Default|Apply); -} - -KCMKeyboard::~KCMKeyboard() -{ - delete keyboardConfig; - delete rules; -} - -void KCMKeyboard::defaults() -{ - keyboardConfig->setDefaults(); - widget->updateUI(); - widget->getKcmMiscWidget()->defaults(); - emit changed(true); -} - -void KCMKeyboard::load() -{ - keyboardConfig->load(); - widget->updateUI(); - widget->getKcmMiscWidget()->load(); -} - -//static void initializeKeyboardSettings(); -void KCMKeyboard::save() -{ - keyboardConfig->save(); - widget->save(); - widget->getKcmMiscWidget()->save(); - - QDBusMessage message = QDBusMessage::createSignal(KEYBOARD_DBUS_OBJECT_PATH, KEYBOARD_DBUS_SERVICE_NAME, KEYBOARD_DBUS_CONFIG_RELOAD_MESSAGE); - QDBusConnection::sessionBus().send(message); -} - -#include "kcm_keyboard.moc" diff --git a/kcms/keyboard/kcm_keyboard.ui b/kcms/keyboard/kcm_keyboard.ui deleted file mode 100644 --- a/kcms/keyboard/kcm_keyboard.ui +++ /dev/null @@ -1,487 +0,0 @@ - - - TabWidget - - - - 0 - 0 - 677 - 485 - - - - 1 - - - - Hardware - - - - 0 - - - - - - 1 - 0 - - - - Keyboard &model: - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - keyboardModelComboBox - - - - - - - - 2 - 0 - - - - Here you can choose a keyboard model. This setting is independent of your keyboard layout and refers to the "hardware" model, i.e. the way your keyboard is manufactured. Modern keyboards that come with your computer usually have two extra keys and are referred to as "104-key" models, which is probably what you want if you do not know what kind of keyboard you have. - - - - 15 - - - QComboBox::AdjustToContentsOnFirstShow - - - - - - - - 1 - 1 - - - - - 0 - 100 - - - - - 0 - 0 - - - - - 0 - - - - - - - - - Layouts - - - - - - - - Layout Indicator - - - - - - Show layout indicator - - - - - - - Show for single layout - - - - - - - Show flag - - - - - - - Show label - - - - - - - Show label on flag - - - - - - - - - - If you select "Application" or "Window" switching policy, changing the keyboard layout will only affect the current application or window. - - - Switching Policy - - - - - - &Global - - - true - - - switchingPolicyButtonGroup - - - - - - - &Desktop - - - switchingPolicyButtonGroup - - - - - - - &Application - - - switchingPolicyButtonGroup - - - - - - - &Window - - - switchingPolicyButtonGroup - - - - - - - - - - Shortcuts for Switching Layout - - - - - - Main shortcuts: - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - xkbGrpShortcutBtn - - - - - - - This is a shortcut for switching layouts which is handled by X.org. It allows modifier-only shortcuts. - - - None - - - - - - - ... - - - - - - - 3rd level shortcuts: - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - xkb3rdLevelShortcutBtn - - - - - - - This is a shortcut for switching to a third level of the active layout (if it has one) which is handled by X.org. It allows modifier-only shortcuts. - - - None - - - - - - - ... - - - - - - - Alternative shortcut: - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - kdeKeySequence - - - - - - - This is a shortcut for switching layouts. It does not support modifier-only shortcuts and also may not work in some situations (e.g. if popup is active or from screensaver). - - - false - - - - - - - - - - - - true - - - Configure layouts - - - false - - - true - - - - - - - - Add - - - - - - - false - - - Remove - - - - - - - false - - - Move Up - - - - - - - false - - - Move Down - - - - - - - false - - - Preview - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - - - QAbstractItemView::SelectRows - - - false - - - false - - - - - - - Spare layouts - - - - - - - Qt::Horizontal - - - QSizePolicy::Fixed - - - - 15 - 20 - - - - - - - - - - - true - - - - - - Main layout count: - - - - - - - - - - Qt::Horizontal - - - - 431 - 20 - - - - - - - - - - - - - - - Advanced - - - - - - &Configure keyboard options - - - - - - - false - - - true - - - - - - - - - KKeySequenceWidget - QWidget -
kkeysequencewidget.h
-
-
- - - - changed(bool) - - - - -
diff --git a/kcms/keyboard/kcm_keyboard_widget.h b/kcms/keyboard/kcm_keyboard_widget.h deleted file mode 100644 --- a/kcms/keyboard/kcm_keyboard_widget.h +++ /dev/null @@ -1,103 +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. - */ - - -#ifndef KCM_KEYBOARD_WIDGET_H_ -#define KCM_KEYBOARD_WIDGET_H_ - -#include "ui_kcm_keyboard.h" - -#include - -#include - -class QWidget; -class KeyboardConfig; -struct Rules; -class Flags; -class QString; -class QPushButton; -class LayoutsTableModel; -class KCMiscKeyboardWidget; -class KeyboardLayoutActionCollection; - -class KCMKeyboardWidget: public QTabWidget -{ - Q_OBJECT - -public: - KCMKeyboardWidget(Rules* rules, KeyboardConfig* keyboardConfig, - const QVariantList &args, QWidget* parent=0); - ~KCMKeyboardWidget() override; - - void updateUI(); - void save(); - - //temp hack - KCMiscKeyboardWidget* getKcmMiscWidget() const { return kcmMiscWidget; } - -Q_SIGNALS: - void changed(bool state); - -private Q_SLOTS: - void addLayout(); - void removeLayout(); - void layoutSelectionChanged(); - void uiChanged(); - void scrollToGroupShortcut(); - void scrollTo3rdLevelShortcut(); - void clearGroupShortcuts(); - void clear3rdLevelShortcuts(); - void updateXkbShortcutsButtons(); - void moveUp(); - void moveDown(); - void configureLayoutsChanged(); - void configureXkbOptionsChanged(); -#ifdef NEW_GEOMETRY - void previewLayout(); -#endif - -private: - Rules *rules; - Flags *flags; - Ui::TabWidget *uiWidget; - KeyboardConfig *keyboardConfig; - KeyboardLayoutActionCollection* actionCollection; - LayoutsTableModel* layoutsTableModel; - KCMiscKeyboardWidget* kcmMiscWidget; - bool uiUpdating; - - void initializeLayoutsUI(); - void initializeXkbOptionsUI(); - void initializeKeyboardModelUI(); - void updateHardwareUI(); - void updateLayoutsUI(); - void updateShortcutsUI(); - void updateXkbOptionsUI(); - void updateSwitcingPolicyUI(); - void updateXkbShortcutButton(const QString& groupName, QPushButton* button); - void clearXkbGroup(const QString& groupName); - void moveSelectedLayouts(int shift); - void populateWithCurrentLayouts(); - void populateWithCurrentXkbOptions(); - void updateLoopCount(); - void handleParameters(const QVariantList &args); -}; - - -#endif /* KCM_KEYBOARD_WIDGET_H_ */ diff --git a/kcms/keyboard/kcm_keyboard_widget.cpp b/kcms/keyboard/kcm_keyboard_widget.cpp deleted file mode 100644 --- a/kcms/keyboard/kcm_keyboard_widget.cpp +++ /dev/null @@ -1,708 +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. - */ - -#include "kcm_keyboard_widget.h" -#include "debug.h" - -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#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 "kcmmisc.h" -#include "ui_kcm_add_layout_dialog.h" - - -static const QString GROUP_SWITCH_GROUP_NAME(QStringLiteral("grp")); -static const QString LV3_SWITCH_GROUP_NAME(QStringLiteral("lv3")); -//static const QString RESET_XKB_OPTIONS("-option"); - -static const int TAB_HARDWARE = 0; -static const int TAB_LAYOUTS = 1; -static const int TAB_ADVANCED = 2; - -static const int MIN_LOOPING_COUNT = 2; - - -KCMKeyboardWidget::KCMKeyboardWidget(Rules* rules_, KeyboardConfig* keyboardConfig_, - const QVariantList &args, QWidget* /*parent*/): - rules(rules_), - actionCollection(NULL), - uiUpdating(false) -{ - flags = new Flags(); - keyboardConfig = keyboardConfig_; - - uiWidget = new Ui::TabWidget; - uiWidget->setupUi(this); - - kcmMiscWidget = new KCMiscKeyboardWidget(uiWidget->lowerHardwareWidget); - uiWidget->lowerHardwareWidget->layout()->addWidget( kcmMiscWidget ); - connect(kcmMiscWidget, SIGNAL(changed(bool)), this, SIGNAL(changed(bool))); - - if( rules != NULL ) { - initializeKeyboardModelUI(); - initializeXkbOptionsUI(); - initializeLayoutsUI(); - } - else { - uiWidget->tabLayouts->setEnabled(false); - uiWidget->tabAdvanced->setEnabled(false); - uiWidget->keyboardModelComboBox->setEnabled(false); - } - - handleParameters(args); -} - -KCMKeyboardWidget::~KCMKeyboardWidget() -{ - delete uiWidget; - delete flags; -} - -void KCMKeyboardWidget::handleParameters(const QVariantList &args) -{ - // TODO: improve parameter handling - setCurrentIndex(TAB_HARDWARE); - foreach(const QVariant& arg, args) { - if( arg.type() == QVariant::String ) { - QString str = arg.toString(); - if( str == QLatin1String("--tab=layouts") ) { - setCurrentIndex(TAB_LAYOUTS); - } - else if( str == QLatin1String("--tab=advanced") ) { - setCurrentIndex(TAB_ADVANCED); - } - } - } -} - -void KCMKeyboardWidget::save() -{ - if( rules == NULL ) - return; - - if( actionCollection != NULL ) { - actionCollection->resetLayoutShortcuts(); - actionCollection->clear(); - delete actionCollection; - } - actionCollection = new KeyboardLayoutActionCollection(this, true); - actionCollection->setToggleShortcut(uiWidget->kdeKeySequence->keySequence()); - actionCollection->setLayoutShortcuts(keyboardConfig->layouts, rules); -} - -void KCMKeyboardWidget::updateUI() -{ - if( rules == NULL ) - return; - - uiWidget->layoutsTableView->setModel(uiWidget->layoutsTableView->model()); - layoutsTableModel->refresh(); - uiWidget->layoutsTableView->resizeRowsToContents(); - - uiUpdating = true; - updateHardwareUI(); - updateXkbOptionsUI(); - updateSwitcingPolicyUI(); - updateLayoutsUI(); - updateShortcutsUI(); - layoutSelectionChanged(); - uiUpdating = false; -} - -void KCMKeyboardWidget::uiChanged() -{ - if( rules == NULL ) - return; - - ((LayoutsTableModel*)uiWidget->layoutsTableView->model())->refresh(); - layoutSelectionChanged(); -// this collapses the tree so use more fine-grained updates -// ((LayoutsTableModel*)uiWidget->xkbOptionsTreeView->model())->refresh(); - - if( uiUpdating ) - return; - - keyboardConfig->showIndicator = uiWidget->showIndicatorChk->isChecked(); - keyboardConfig->showSingle = uiWidget->showSingleChk->isChecked(); - - keyboardConfig->configureLayouts = uiWidget->layoutsGroupBox->isChecked(); - keyboardConfig->keyboardModel = uiWidget->keyboardModelComboBox->itemData(uiWidget->keyboardModelComboBox->currentIndex()).toString(); - - if( uiWidget->showFlagRadioBtn->isChecked() ) { - keyboardConfig->indicatorType = KeyboardConfig::SHOW_FLAG; - } - else - if( uiWidget->showLabelRadioBtn->isChecked() ) { - keyboardConfig->indicatorType = KeyboardConfig::SHOW_LABEL; - } - else { -// if( uiWidget->showFlagRadioBtn->isChecked() ) { - keyboardConfig->indicatorType = KeyboardConfig::SHOW_LABEL_ON_FLAG; - } - - keyboardConfig->resetOldXkbOptions = uiWidget->configureKeyboardOptionsChk->isChecked(); - - if( uiWidget->switchByDesktopRadioBtn->isChecked() ) { - keyboardConfig->switchingPolicy = KeyboardConfig::SWITCH_POLICY_DESKTOP; - } - else - if( uiWidget->switchByApplicationRadioBtn->isChecked() ) { - keyboardConfig->switchingPolicy = KeyboardConfig::SWITCH_POLICY_APPLICATION; - } - else - if( uiWidget->switchByWindowRadioBtn->isChecked() ) { - keyboardConfig->switchingPolicy = KeyboardConfig::SWITCH_POLICY_WINDOW; - } - else { - keyboardConfig->switchingPolicy = KeyboardConfig::SWITCH_POLICY_GLOBAL; - } - - updateXkbShortcutsButtons(); - - updateLoopCount(); - int loop = uiWidget->layoutLoopCountSpinBox->text().isEmpty() - ? KeyboardConfig::NO_LOOPING - : uiWidget->layoutLoopCountSpinBox->value(); - keyboardConfig->layoutLoopCount = loop; - - layoutsTableModel->refresh(); - layoutSelectionChanged(); - - emit changed(true); -} - -void KCMKeyboardWidget::initializeKeyboardModelUI() -{ - foreach(ModelInfo* modelInfo, rules->modelInfos) { - QString vendor = modelInfo->vendor; - if( vendor.isEmpty() ) { - vendor = i18nc("unknown keyboard model vendor", "Unknown"); - } - uiWidget->keyboardModelComboBox->addItem(i18nc("vendor | keyboard model", "%1 | %2", vendor, modelInfo->description), modelInfo->name); - } - uiWidget->keyboardModelComboBox->model()->sort(0); - connect(uiWidget->keyboardModelComboBox, SIGNAL(activated(int)), this, SLOT(uiChanged())); -} - -void KCMKeyboardWidget::addLayout() -{ - if( keyboardConfig->layouts.count() >= X11Helper::ARTIFICIAL_GROUP_LIMIT_COUNT ) { // artificial limit now - QMessageBox msgBox; - msgBox.setText(i18np("Only up to %1 keyboard layout is supported", "Only up to %1 keyboard layouts are supported", X11Helper::ARTIFICIAL_GROUP_LIMIT_COUNT)); - // more information https://bugs.freedesktop.org/show_bug.cgi?id=19501 - msgBox.exec(); - return; - } - - AddLayoutDialog dialog(rules, keyboardConfig->isFlagShown() ? flags : NULL, keyboardConfig->keyboardModel, keyboardConfig->isLabelShown(), this); - dialog.setModal(true); - if( dialog.exec() == QDialog::Accepted ) { - keyboardConfig->layouts.append( dialog.getSelectedLayoutUnit() ); - layoutsTableModel->refresh(); - uiWidget->layoutsTableView->resizeRowsToContents(); - uiChanged(); - } - - updateLoopCount(); -} - -void KCMKeyboardWidget::updateLoopCount() -{ - int maxLoop = qMin(X11Helper::MAX_GROUP_COUNT, keyboardConfig->layouts.count() - 1); - uiWidget->layoutLoopCountSpinBox->setMaximum(qMax(MIN_LOOPING_COUNT, maxLoop)); - - bool layoutsConfigured = uiWidget->layoutsGroupBox->isChecked(); - - if( maxLoop < MIN_LOOPING_COUNT ) { - uiWidget->layoutLoopingCheckBox->setEnabled(false); - uiWidget->layoutLoopingCheckBox->setChecked(false); - } - else if( maxLoop >= X11Helper::MAX_GROUP_COUNT ) { - uiWidget->layoutLoopingCheckBox->setEnabled(false); - uiWidget->layoutLoopingCheckBox->setChecked(true); - } - else { - uiWidget->layoutLoopingCheckBox->setEnabled(layoutsConfigured); - } - - uiWidget->layoutLoopingGroupBox->setEnabled( - layoutsConfigured && uiWidget->layoutLoopingCheckBox->isChecked()); - - if( uiWidget->layoutLoopingCheckBox->isChecked() ) { - if( uiWidget->layoutLoopCountSpinBox->text().isEmpty() ) { - uiWidget->layoutLoopCountSpinBox->setValue(maxLoop); - keyboardConfig->layoutLoopCount = maxLoop; - } - } - else { - uiWidget->layoutLoopCountSpinBox->clear(); - keyboardConfig->layoutLoopCount = KeyboardConfig::NO_LOOPING; - } -} - -void KCMKeyboardWidget::initializeLayoutsUI() -{ - layoutsTableModel = new LayoutsTableModel(rules, flags, keyboardConfig, uiWidget->layoutsTableView); - uiWidget->layoutsTableView->setEditTriggers(QAbstractItemView::SelectedClicked | QAbstractItemView::DoubleClicked | QAbstractItemView::EditKeyPressed | QAbstractItemView::AnyKeyPressed); - uiWidget->layoutsTableView->setModel(layoutsTableModel); - uiWidget->layoutsTableView->setIconSize( flags->getTransparentPixmap().size() ); - - //TODO: do we need to delete this delegate or parent will take care of it? - VariantComboDelegate* variantDelegate = new VariantComboDelegate(keyboardConfig, rules, uiWidget->layoutsTableView); - uiWidget->layoutsTableView->setItemDelegateForColumn(LayoutsTableModel::VARIANT_COLUMN, variantDelegate); - - LabelEditDelegate* labelDelegate = new LabelEditDelegate(keyboardConfig, uiWidget->layoutsTableView); - uiWidget->layoutsTableView->setItemDelegateForColumn(LayoutsTableModel::DISPLAY_NAME_COLUMN, labelDelegate); - - KKeySequenceWidgetDelegate* shortcutDelegate = new KKeySequenceWidgetDelegate(keyboardConfig, uiWidget->layoutsTableView); - uiWidget->layoutsTableView->setItemDelegateForColumn(LayoutsTableModel::SHORTCUT_COLUMN, shortcutDelegate); - - //TODO: is it ok to hardcode sizes? any better approach? - uiWidget->layoutsTableView->setColumnWidth(LayoutsTableModel::MAP_COLUMN, 70); - uiWidget->layoutsTableView->setColumnWidth(LayoutsTableModel::LAYOUT_COLUMN, 200); - uiWidget->layoutsTableView->setColumnWidth(LayoutsTableModel::VARIANT_COLUMN, 200); - uiWidget->layoutsTableView->setColumnWidth(LayoutsTableModel::DISPLAY_NAME_COLUMN, 50); - uiWidget->layoutsTableView->setColumnWidth(LayoutsTableModel::SHORTCUT_COLUMN, 130); - - connect(layoutsTableModel, &LayoutsTableModel::dataChanged, this, [this]() { Q_EMIT changed(true); }); - - uiWidget->layoutLoopCountSpinBox->setMinimum(MIN_LOOPING_COUNT); - -#ifdef DRAG_ENABLED - uiWidget->layoutsTableView->setDragEnabled(true); - uiWidget->layoutsTableView->setAcceptDrops(true); -#endif - - uiWidget->moveUpBtn->setIcon(QIcon::fromTheme(QStringLiteral("arrow-up"))); - uiWidget->moveDownBtn->setIcon(QIcon::fromTheme(QStringLiteral("arrow-down"))); - uiWidget->addLayoutBtn->setIcon(QIcon::fromTheme(QStringLiteral("list-add"))); - uiWidget->removeLayoutBtn->setIcon(QIcon::fromTheme(QStringLiteral("list-remove"))); - - QIcon clearIcon = qApp->isLeftToRight() ? QIcon::fromTheme(QStringLiteral("edit-clear-locationbar-rtl")) : QIcon::fromTheme(QStringLiteral("edit-clear-locationbar-ltr")); - uiWidget->xkbGrpClearBtn->setIcon(clearIcon); - uiWidget->xkb3rdLevelClearBtn->setIcon(clearIcon); - - QIcon configIcon = QIcon::fromTheme(QStringLiteral("configure")); - uiWidget->xkbGrpShortcutBtn->setIcon(configIcon); - uiWidget->xkb3rdLevelShortcutBtn->setIcon(configIcon); - - uiWidget->kdeKeySequence->setModifierlessAllowed(false); - - connect(uiWidget->addLayoutBtn, &QAbstractButton::clicked, this, &KCMKeyboardWidget::addLayout); - connect(uiWidget->removeLayoutBtn, &QAbstractButton::clicked, this, &KCMKeyboardWidget::removeLayout); -// connect(uiWidget->layoutsTable, SIGNAL(itemSelectionChanged()), this, SLOT(layoutSelectionChanged())); - connect(uiWidget->layoutsTableView->selectionModel(), &QItemSelectionModel::selectionChanged, this, &KCMKeyboardWidget::layoutSelectionChanged); - -// connect(uiWidget->moveUpBtn, SIGNAL(triggered(QAction*)), this, SLOT(moveUp())); -// connect(uiWidget->moveDownBtn, SIGNAL(triggered(QAction*)), this, SLOT(moveDown())); - 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); - -// connect(uiWidget->xkbGrpClearBtn, SIGNAL(triggered(QAction*)), this, SLOT(uiChanged())); -// connect(uiWidget->xkb3rdLevelClearBtn, SIGNAL(triggered(QAction*)), this, SLOT(uiChanged())); - connect(uiWidget->kdeKeySequence, &KKeySequenceWidget::keySequenceChanged, this, &KCMKeyboardWidget::uiChanged); - connect(uiWidget->switchingPolicyButtonGroup, SIGNAL(buttonClicked(int)), this, SLOT(uiChanged())); - connect(uiWidget->xkbGrpShortcutBtn, &QAbstractButton::clicked, this, &KCMKeyboardWidget::scrollToGroupShortcut); - connect(uiWidget->xkb3rdLevelShortcutBtn, &QAbstractButton::clicked, this, &KCMKeyboardWidget::scrollTo3rdLevelShortcut); - - // connect(uiWidget->configureLayoutsChk, SIGNAL(toggled(bool)), uiWidget->layoutsGroupBox, SLOT(setEnabled(bool))); - connect(uiWidget->layoutsGroupBox, &QGroupBox::toggled, this, &KCMKeyboardWidget::configureLayoutsChanged); - - connect(uiWidget->showIndicatorChk, &QAbstractButton::clicked, this, &KCMKeyboardWidget::uiChanged); - connect(uiWidget->showIndicatorChk, &QAbstractButton::toggled, uiWidget->showSingleChk, &QWidget::setEnabled); - connect(uiWidget->showFlagRadioBtn, &QAbstractButton::clicked, this, &KCMKeyboardWidget::uiChanged); - connect(uiWidget->showLabelRadioBtn, &QAbstractButton::clicked, this, &KCMKeyboardWidget::uiChanged); - connect(uiWidget->showLabelOnFlagRadioBtn, &QAbstractButton::clicked, this, &KCMKeyboardWidget::uiChanged); - connect(uiWidget->showSingleChk, &QAbstractButton::toggled, this, &KCMKeyboardWidget::uiChanged); - - connect(uiWidget->layoutLoopingCheckBox, &QAbstractButton::clicked, this, &KCMKeyboardWidget::uiChanged); - connect(uiWidget->layoutLoopCountSpinBox, SIGNAL(valueChanged(int)), this, SLOT(uiChanged())); -} - -#ifdef NEW_GEOMETRY -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) ; - QString variant=uiWidget->layoutsTableView->model()->data(idvariant).toString(); - QString model = keyboardConfig->keyboardModel; - - KeyboardPainter layoutPreview; - const LayoutInfo* layoutInfo = rules->getLayoutInfo(country); - if (!layoutInfo) { - return; - } - - foreach(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(); -} -#endif - -void KCMKeyboardWidget::configureLayoutsChanged() -{ - if( uiWidget->layoutsGroupBox->isChecked() && keyboardConfig->layouts.isEmpty() ) { - populateWithCurrentLayouts(); - } - uiChanged(); -} - -static QPair getSelectedRowRange(const QModelIndexList& selected) -{ - if( selected.isEmpty() ) { - return QPair(-1, -1); - } - - QList rows; - foreach(const QModelIndex& index, selected) { - rows << index.row(); - } - qSort(rows); - return QPair(rows[0], rows[rows.size()-1]); -} - -void KCMKeyboardWidget::layoutSelectionChanged() -{ - QModelIndexList selected = uiWidget->layoutsTableView->selectionModel()->selectedIndexes(); - 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->moveDownBtn->setEnabled( ! selected.isEmpty() && rowsRange.second < keyboardConfig->layouts.size()-1 ); -} - -void KCMKeyboardWidget::removeLayout() -{ - if( ! uiWidget->layoutsTableView->selectionModel()->hasSelection() ) - return; - - QModelIndexList selected = uiWidget->layoutsTableView->selectionModel()->selectedIndexes(); - QPair rowsRange( getSelectedRowRange(selected) ); - foreach(const QModelIndex& idx, selected) { - if( idx.column() == 0 ) { - keyboardConfig->layouts.removeAt(rowsRange.first); - } - } - layoutsTableModel->refresh(); - uiChanged(); - - if( keyboardConfig->layouts.size() > 0 ) { - int rowToSelect = rowsRange.first; - if( rowToSelect >= keyboardConfig->layouts.size() ) { - rowToSelect--; - } - - QModelIndex topLeft = layoutsTableModel->index(rowToSelect, 0, QModelIndex()); - QModelIndex bottomRight = layoutsTableModel->index(rowToSelect, layoutsTableModel->columnCount(topLeft)-1, QModelIndex()); - QItemSelection selection(topLeft, bottomRight); - uiWidget->layoutsTableView->selectionModel()->select(selection, QItemSelectionModel::SelectCurrent); - uiWidget->layoutsTableView->setFocus(); - } - - layoutSelectionChanged(); - - updateLoopCount(); -} - -void KCMKeyboardWidget::moveUp() -{ - moveSelectedLayouts(-1); -} - -void KCMKeyboardWidget::moveDown() -{ - moveSelectedLayouts(1); -} - -void KCMKeyboardWidget::moveSelectedLayouts(int shift) -{ - QItemSelectionModel* selectionModel = uiWidget->layoutsTableView->selectionModel(); - if( selectionModel == NULL || !selectionModel->hasSelection() ) - return; - - QModelIndexList selected = selectionModel->selectedRows(); - if( selected.count() < 1 ) - return; - - int newFirstRow = selected[0].row() + shift; - int newLastRow = selected[ selected.size()-1 ].row() + shift; - - if( newFirstRow >= 0 && newLastRow <= keyboardConfig->layouts.size() - 1 ) { - QList selectionRows; - foreach(const QModelIndex& index, selected) { - int newRowIndex = index.row() + shift; - keyboardConfig->layouts.move(index.row(), newRowIndex); - selectionRows << newRowIndex; - } - uiChanged(); - - QItemSelection selection; - foreach(int row, selectionRows) { - QModelIndex topLeft = layoutsTableModel->index(row, 0, QModelIndex()); - QModelIndex bottomRight = layoutsTableModel->index(row, layoutsTableModel->columnCount(topLeft)-1, QModelIndex()); - selection << QItemSelectionRange(topLeft, bottomRight); - } - uiWidget->layoutsTableView->selectionModel()->select(selection, QItemSelectionModel::SelectCurrent); - uiWidget->layoutsTableView->setFocus(); - } -} - -void KCMKeyboardWidget::scrollToGroupShortcut() -{ - this->setCurrentIndex(TAB_ADVANCED); - if( ! uiWidget->configureKeyboardOptionsChk->isChecked() ) { - uiWidget->configureKeyboardOptionsChk->setChecked(true); - } - ((XkbOptionsTreeModel*)uiWidget->xkbOptionsTreeView->model())->gotoGroup(GROUP_SWITCH_GROUP_NAME, uiWidget->xkbOptionsTreeView); -} - -void KCMKeyboardWidget::scrollTo3rdLevelShortcut() -{ - this->setCurrentIndex(TAB_ADVANCED); - if( ! uiWidget->configureKeyboardOptionsChk->isChecked() ) { - uiWidget->configureKeyboardOptionsChk->setChecked(true); - } - ((XkbOptionsTreeModel*)uiWidget->xkbOptionsTreeView->model())->gotoGroup(LV3_SWITCH_GROUP_NAME, uiWidget->xkbOptionsTreeView); -} - -void KCMKeyboardWidget::clearGroupShortcuts() -{ - clearXkbGroup(GROUP_SWITCH_GROUP_NAME); -} - -void KCMKeyboardWidget::clear3rdLevelShortcuts() -{ - clearXkbGroup(LV3_SWITCH_GROUP_NAME); -} - -void KCMKeyboardWidget::clearXkbGroup(const QString& groupName) -{ - for(int ii=keyboardConfig->xkbOptions.count()-1; ii>=0; ii--) { - if( keyboardConfig->xkbOptions[ii].startsWith(groupName + Rules::XKB_OPTION_GROUP_SEPARATOR) ) { - keyboardConfig->xkbOptions.removeAt(ii); - } - } - ((XkbOptionsTreeModel*)uiWidget->xkbOptionsTreeView->model())->reset(); - uiWidget->xkbOptionsTreeView->update(); - updateXkbShortcutsButtons(); - emit changed(true); -} - -static -bool xkbOptionGroupLessThan(const OptionGroupInfo* og1, const OptionGroupInfo* og2) -{ - return og1->description.toLower() < og2->description.toLower(); -} -static -bool xkbOptionLessThan(const OptionInfo* o1, const OptionInfo* o2) -{ - return o1->description.toLower() < o2->description.toLower(); -} - -void KCMKeyboardWidget::initializeXkbOptionsUI() -{ - qSort(rules->optionGroupInfos.begin(), rules->optionGroupInfos.end(), xkbOptionGroupLessThan); - foreach(OptionGroupInfo* optionGroupInfo, rules->optionGroupInfos) { - qSort(optionGroupInfo->optionInfos.begin(), optionGroupInfo->optionInfos.end(), xkbOptionLessThan); - } - - XkbOptionsTreeModel* model = new XkbOptionsTreeModel(rules, keyboardConfig, uiWidget->xkbOptionsTreeView); - uiWidget->xkbOptionsTreeView->setModel(model); - connect(model, &QAbstractItemModel::dataChanged, this, &KCMKeyboardWidget::uiChanged); - - connect(uiWidget->configureKeyboardOptionsChk, &QAbstractButton::toggled, this, &KCMKeyboardWidget::configureXkbOptionsChanged); - // connect(uiWidget->configureKeyboardOptionsChk, SIGNAL(toggled(bool)), this, SLOT(uiChanged())); - connect(uiWidget->configureKeyboardOptionsChk, &QAbstractButton::toggled, uiWidget->xkbOptionsTreeView, &QWidget::setEnabled); -} - -void KCMKeyboardWidget::configureXkbOptionsChanged() -{ - if( uiWidget->configureKeyboardOptionsChk->isChecked() && keyboardConfig->xkbOptions.isEmpty() ) { - populateWithCurrentXkbOptions(); - } - ((XkbOptionsTreeModel*)uiWidget->xkbOptionsTreeView->model())->reset(); - uiChanged(); -} - -void KCMKeyboardWidget::updateSwitcingPolicyUI() -{ - switch (keyboardConfig->switchingPolicy){ - case KeyboardConfig::SWITCH_POLICY_DESKTOP: - uiWidget->switchByDesktopRadioBtn->setChecked(true); - break; - case KeyboardConfig::SWITCH_POLICY_APPLICATION: - uiWidget->switchByApplicationRadioBtn->setChecked(true); - break; - case KeyboardConfig::SWITCH_POLICY_WINDOW: - uiWidget->switchByWindowRadioBtn->setChecked(true); - break; - default: - case KeyboardConfig::SWITCH_POLICY_GLOBAL: - uiWidget->switchByGlobalRadioBtn->setChecked(true); - } -} - -void KCMKeyboardWidget::updateXkbShortcutButton(const QString& groupName, QPushButton* button) -{ - QStringList grpOptions; - if( keyboardConfig->resetOldXkbOptions ) { - QRegExp regexp = QRegExp("^" + groupName + Rules::XKB_OPTION_GROUP_SEPARATOR); - grpOptions = keyboardConfig->xkbOptions.filter(regexp); - } - switch( grpOptions.size() ) { - case 0: - button->setText(i18nc("no shortcuts defined", "None")); - break; - case 1: { - const QString& option = grpOptions.first(); - const OptionGroupInfo* optionGroupInfo = rules->getOptionGroupInfo(groupName); - const OptionInfo* optionInfo = optionGroupInfo->getOptionInfo(option); - if( optionInfo == NULL || optionInfo->description == NULL ) { - qCDebug(KCM_KEYBOARD) << "Could not find option info for " << option; - button->setText(grpOptions.first()); - } - else { - button->setText(optionInfo->description); - } - } - break; - default: - button->setText(i18np("%1 shortcut", "%1 shortcuts", grpOptions.size())); - } -} - -void KCMKeyboardWidget::updateXkbShortcutsButtons() -{ - updateXkbShortcutButton(GROUP_SWITCH_GROUP_NAME, uiWidget->xkbGrpShortcutBtn); - updateXkbShortcutButton(LV3_SWITCH_GROUP_NAME, uiWidget->xkb3rdLevelShortcutBtn); -} - -void KCMKeyboardWidget::updateShortcutsUI() -{ - updateXkbShortcutsButtons(); - - delete actionCollection; - actionCollection = new KeyboardLayoutActionCollection(this, true); - QAction* toggleAction = actionCollection->getToggleAction(); - const auto shortcuts = KGlobalAccel::self()->shortcut(toggleAction); - uiWidget->kdeKeySequence->setKeySequence(shortcuts.isEmpty() ? QKeySequence() : shortcuts.first()); - actionCollection->loadLayoutShortcuts(keyboardConfig->layouts, rules); - layoutsTableModel->refresh(); -} - -void KCMKeyboardWidget::updateXkbOptionsUI() -{ - uiWidget->configureKeyboardOptionsChk->setChecked(keyboardConfig->resetOldXkbOptions); -} - -void KCMKeyboardWidget::updateLayoutsUI() { - uiWidget->layoutsGroupBox->setChecked(keyboardConfig->configureLayouts); - uiWidget->showIndicatorChk->setChecked(keyboardConfig->showIndicator); - uiWidget->showSingleChk->setChecked(keyboardConfig->showSingle); - uiWidget->showFlagRadioBtn->setChecked(keyboardConfig->indicatorType == KeyboardConfig::SHOW_FLAG); - uiWidget->showLabelRadioBtn->setChecked(keyboardConfig->indicatorType == KeyboardConfig::SHOW_LABEL); - uiWidget->showLabelOnFlagRadioBtn->setChecked(keyboardConfig->indicatorType == KeyboardConfig::SHOW_LABEL_ON_FLAG); - - bool loopingOn = keyboardConfig->configureLayouts && keyboardConfig->layoutLoopCount - != KeyboardConfig::NO_LOOPING; - uiWidget->layoutLoopingCheckBox->setChecked(loopingOn); - uiWidget->layoutLoopingGroupBox->setEnabled(loopingOn); - if( loopingOn ) { - // Set maximum to 99 to make sure following setValue succeeds - // Correct maximum value will be set in updateLoopCount() - uiWidget->layoutLoopCountSpinBox->setMaximum(99); - uiWidget->layoutLoopCountSpinBox->setValue(keyboardConfig->layoutLoopCount); - } - else { - uiWidget->layoutLoopCountSpinBox->clear(); - } - - updateLoopCount(); -} - -void KCMKeyboardWidget::updateHardwareUI() -{ - int idx = uiWidget->keyboardModelComboBox->findData(keyboardConfig->keyboardModel); - if( idx != -1 ) { - uiWidget->keyboardModelComboBox->setCurrentIndex(idx); - } -} - -void KCMKeyboardWidget::populateWithCurrentLayouts() -{ - QList layouts = X11Helper::getLayoutsList(); - foreach(LayoutUnit layoutUnit, layouts) { - keyboardConfig->layouts.append(layoutUnit); - } -} - -void KCMKeyboardWidget::populateWithCurrentXkbOptions() -{ - if (!KWindowSystem::isPlatformX11()) { - // TODO: implement for Wayland - query dbus maybe? - return; - } - XkbConfig xkbConfig; - if( X11Helper::getGroupNames(QX11Info::display(), &xkbConfig, X11Helper::ALL) ) { - foreach(QString xkbOption, xkbConfig.options) { - keyboardConfig->xkbOptions.append(xkbOption); - } - } -} diff --git a/kcms/keyboard/kcm_view_models.h b/kcms/keyboard/kcm_view_models.h deleted file mode 100644 --- a/kcms/keyboard/kcm_view_models.h +++ /dev/null @@ -1,175 +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. - */ - - -#ifndef KCM_VIEW_MODELS_H_ -#define KCM_VIEW_MODELS_H_ - -#include -#include -#include -#include - -class QTreeView; -class KeyboardConfig; -struct Rules; -class Flags; - -class LayoutsTableModel : public QAbstractTableModel -{ - Q_OBJECT - - public: - LayoutsTableModel(Rules* rules, Flags *flags, KeyboardConfig* keyboardConfig, QObject *parent = 0); - - int columnCount(const QModelIndex&) const override; - Qt::ItemFlags flags(const QModelIndex &index) const override; - QVariant headerData(int section, Qt::Orientation orientation, - int role = Qt::DisplayRole) const override; - - int rowCount(const QModelIndex &parent = QModelIndex()) const override; - QVariant data(const QModelIndex &index, int role) const override; - bool setData(const QModelIndex &index, const QVariant &value, int role) override; -#ifdef DRAG_ENABLED - Qt::DropActions supportedDropActions() const { - return Qt::MoveAction; - } - QStringList mimeTypes() const; - QMimeData *mimeData(const QModelIndexList &indexes) const; -#endif - void refresh(); - - static const int MAP_COLUMN; - static const int LAYOUT_COLUMN; - static const int VARIANT_COLUMN; - static const int DISPLAY_NAME_COLUMN; - static const int SHORTCUT_COLUMN; - - private: - KeyboardConfig* keyboardConfig; - const Rules *rules; - Flags *countryFlags; -}; - -class LabelEditDelegate : public QStyledItemDelegate -{ - Q_OBJECT - -public: - explicit LabelEditDelegate(const KeyboardConfig* keyboardConfig, QObject *parent = 0); - - QWidget *createEditor(QWidget *parent, const QStyleOptionViewItem &option, - const QModelIndex &index) const override; - - void updateEditorGeometry(QWidget *editor, - const QStyleOptionViewItem &option, const QModelIndex &index) const override; - -// void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const; - -private: - const KeyboardConfig* keyboardConfig; -}; - -class VariantComboDelegate : public QStyledItemDelegate -{ - Q_OBJECT - -public: - VariantComboDelegate(const KeyboardConfig* keyboardConfig, const Rules* rules, QObject *parent = 0); - - QWidget *createEditor(QWidget *parent, const QStyleOptionViewItem &option, - const QModelIndex &index) const override; - - void setEditorData(QWidget *editor, const QModelIndex &index) const override; - void setModelData(QWidget *editor, QAbstractItemModel *model, - const QModelIndex &index) const override; - - void updateEditorGeometry(QWidget *editor, - const QStyleOptionViewItem &option, const QModelIndex &index) const override; - -private: - const KeyboardConfig* keyboardConfig; - const Rules* rules; -}; - -class KKeySequenceWidgetDelegate : public QStyledItemDelegate -{ - Q_OBJECT - -public: - KKeySequenceWidgetDelegate(const KeyboardConfig* keyboardConfig_, QObject *parent = 0); - - QWidget *createEditor(QWidget *parent, const QStyleOptionViewItem &option, - const QModelIndex &index) const override; -// void setEditorData(QWidget *editor, const QModelIndex &index) const; - void setModelData(QWidget *editor, QAbstractItemModel *model, - const QModelIndex &index) const override; - void paint(QPainter* painter, const QStyleOptionViewItem& option, - const QModelIndex& index) const override; - -private: - const KeyboardConfig* keyboardConfig; - mutable QSet itemsBeingEdited; -}; - - -class XkbOptionsTreeModel: public QAbstractItemModel -{ -public: - XkbOptionsTreeModel(Rules* rules_, KeyboardConfig* keyboardConfig_, QObject *parent) - : QAbstractItemModel(parent), - keyboardConfig(keyboardConfig_), - rules(rules_) { } - - int columnCount(const QModelIndex& /*parent*/) const override { return 1; } - int rowCount(const QModelIndex& parent) const override; - QModelIndex parent(const QModelIndex& index) const override { - if (!index.isValid() ) - return QModelIndex(); - if( index.internalId() < 100 ) - return QModelIndex(); - return createIndex(((index.internalId() - index.row())/100) - 1, index.column()); - } - QModelIndex index(int row, int column, const QModelIndex& parent) const override { - if(!parent.isValid()) return createIndex(row, column); - return createIndex(row, column, (100 * (parent.row()+1)) + row); - } - Qt::ItemFlags flags ( const QModelIndex & index ) const override { - if( ! index.isValid() ) - return 0; - - if( !index.parent().isValid() ) - return Qt::ItemIsEnabled | Qt::ItemIsSelectable; - - return Qt::ItemIsEnabled | Qt::ItemIsUserCheckable | Qt::ItemIsSelectable; - } - - bool setData ( const QModelIndex & index, const QVariant & value, int role = Qt::EditRole ) override; - QVariant data(const QModelIndex& index, int role) const override; - void reset() { - beginResetModel(); - endResetModel(); - } - void gotoGroup(const QString& group, QTreeView* view); - -private: - KeyboardConfig* keyboardConfig; - Rules *rules; -}; - -#endif /* KCM_VIEW_MODELS_H_ */ diff --git a/kcms/keyboard/kcm_view_models.cpp b/kcms/keyboard/kcm_view_models.cpp deleted file mode 100644 --- a/kcms/keyboard/kcm_view_models.cpp +++ /dev/null @@ -1,521 +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. - */ - -#include "kcm_view_models.h" - -#include -#include - -#include -#include -#include -#include -#include - -#ifdef DRAG_ENABLED -#include -#endif - -#include "keyboard_config.h" -#include "xkb_rules.h" -#include "flags.h" -#include "x11_helper.h" -#include "bindings.h" - -const int LayoutsTableModel::MAP_COLUMN = 0; -const int LayoutsTableModel::LAYOUT_COLUMN = 1; -const int LayoutsTableModel::VARIANT_COLUMN = 2; -const int LayoutsTableModel::DISPLAY_NAME_COLUMN = 3; -const int LayoutsTableModel::SHORTCUT_COLUMN = 4; -static const int COLUMN_COUNT = 5; - -LayoutsTableModel::LayoutsTableModel(Rules* rules_, Flags *flags_, KeyboardConfig* keyboardConfig_, QObject* parent): - QAbstractTableModel(parent), - keyboardConfig(keyboardConfig_), - rules(rules_), - countryFlags(flags_) -{ -} - -void LayoutsTableModel::refresh() -{ - beginResetModel(); - endResetModel(); - - countryFlags->clearCache(); -} - -int LayoutsTableModel::rowCount(const QModelIndex &/*parent*/) const -{ - return keyboardConfig->layouts.count(); -} - -int LayoutsTableModel::columnCount(const QModelIndex&) const -{ - return COLUMN_COUNT; -} - -Qt::ItemFlags LayoutsTableModel::flags(const QModelIndex &index) const -{ - if (!index.isValid()) - return 0; - - Qt::ItemFlags flags = QAbstractTableModel::flags(index); - - if( index.column() == DISPLAY_NAME_COLUMN - || index.column() == VARIANT_COLUMN - || index.column() == SHORTCUT_COLUMN ) { - flags |= Qt::ItemIsEditable; - } - -#ifdef DRAG_ENABLED - flags |= Qt::ItemIsDragEnabled | Qt::ItemIsDropEnabled; -#endif - - return flags; -} - -#ifdef DRAG_ENABLED -QStringList LayoutsTableModel::mimeTypes() const -{ - QStringList types; - types << "application/keyboard-layout-item"; - return types; -} - -QMimeData *LayoutsTableModel::mimeData(const QModelIndexList &indexes) const - { - QMimeData *mimeData = new QMimeData(); - QByteArray encodedData; - - QDataStream stream(&encodedData, QIODevice::WriteOnly); - - QSet rows; - foreach (const QModelIndex& index, indexes) { - if (index.isValid()) { - rows << index.row(); - } - } - foreach (int row, rows) { - stream << row; - } - - mimeData->setData("application/keyboard-layout-item", encodedData); - return mimeData; -} -#endif - -QVariant LayoutsTableModel::data(const QModelIndex &index, int role) const -{ - if (!index.isValid()) - return QVariant(); - - if (index.row() >= keyboardConfig->layouts.size()) - return QVariant(); - - const LayoutUnit& layoutUnit = keyboardConfig->layouts.at(index.row()); - - if (role == Qt::DecorationRole) { - switch( index.column() ) { - case DISPLAY_NAME_COLUMN: { -// if( keyboardConfig->isFlagShown() ) { - QIcon icon = countryFlags->getIconWithText(layoutUnit, *keyboardConfig); - return icon.isNull() ? countryFlags->getTransparentPixmap() : icon; -// } - } -//TODO: show the cells are editable -// case VARIANT_COLUMN: { -// case DISPLAY_NAME_COLUMN: { -// int sz = 5; -// QPixmap pm = QPixmap(sz, sz+5); -// pm.fill(Qt::transparent); -// QPainter p(&pm); -// QPoint points[] = { QPoint(0, 0), QPoint(0, sz), QPoint(sz, 0) }; -// p.drawPolygon(points, 3); -// return pm; -// } - break; - } - } - else - if( role == Qt::BackgroundRole ) { - if( keyboardConfig->layoutLoopCount != KeyboardConfig::NO_LOOPING - && index.row() >= keyboardConfig->layoutLoopCount ) { - return QBrush(Qt::lightGray); - } - } - else - if (role == Qt::DisplayRole) { - switch( index.column() ) { - case MAP_COLUMN: - return layoutUnit.layout; - break; - case LAYOUT_COLUMN: { - const LayoutInfo* layoutInfo = rules->getLayoutInfo(layoutUnit.layout); - return layoutInfo != NULL ? layoutInfo->description : layoutUnit.layout; - } - case VARIANT_COLUMN: { - if( layoutUnit.variant.isEmpty() ) - return QVariant(); - const LayoutInfo* layoutInfo = rules->getLayoutInfo(layoutUnit.layout); - if( layoutInfo == NULL ) - return QVariant(); - const VariantInfo* variantInfo = layoutInfo->getVariantInfo(layoutUnit.variant); - return variantInfo != NULL ? variantInfo->description : layoutUnit.variant; - } - break; - case DISPLAY_NAME_COLUMN: -// if( keyboardConfig->indicatorType == KeyboardConfig::SHOW_LABEL ) { -// return layoutUnit.getDisplayName(); -// } - break; - case SHORTCUT_COLUMN: { - return layoutUnit.getShortcut().toString(); - } - break; - } - } - else if (role==Qt::EditRole ) { - switch( index.column() ) { - case DISPLAY_NAME_COLUMN: - return layoutUnit.getDisplayName(); - break; - case VARIANT_COLUMN: - return layoutUnit.variant; - break; - case SHORTCUT_COLUMN: - return layoutUnit.getShortcut().toString(); - break; - default:; - } - } - else if( role == Qt::TextAlignmentRole ) { - switch( index.column() ) { - case MAP_COLUMN: - case DISPLAY_NAME_COLUMN: - case SHORTCUT_COLUMN: - return Qt::AlignCenter; - break; - default:; - } - } - return QVariant(); -} - -QVariant LayoutsTableModel::headerData(int section, Qt::Orientation orientation, int role) const -{ - if (role != Qt::DisplayRole) - return QVariant(); - - if (orientation == Qt::Horizontal) { - const QString headers[] = {i18nc("layout map name", "Map"), i18n("Layout"), i18n("Variant"), i18n("Label"), i18n("Shortcut")}; - return headers[section]; - } - - return QVariant(); -} - -bool LayoutsTableModel::setData(const QModelIndex &index, const QVariant &value, int role) -{ - if (role != Qt::EditRole - || (index.column() != DISPLAY_NAME_COLUMN && index.column() != VARIANT_COLUMN && index.column() != SHORTCUT_COLUMN) ) - return false; - - if (index.row() >= keyboardConfig->layouts.size() || index.data(role) == value) - return false; - - LayoutUnit& layoutUnit = keyboardConfig->layouts[index.row()]; - - switch( index.column() ) { - case DISPLAY_NAME_COLUMN: { - QString displayText = value.toString().left(3); - layoutUnit.setDisplayName(displayText); - countryFlags->clearCache(); // regenerate the label - } - break; - case VARIANT_COLUMN: { - QString variant = value.toString(); - layoutUnit.variant = variant; - } - break; - case SHORTCUT_COLUMN: { - QString shortcut = value.toString(); - layoutUnit.setShortcut(QKeySequence(shortcut)); - } - break; - } - emit dataChanged(index, index); - - return true; -} - -// -// LabelEditDelegate -// -LabelEditDelegate::LabelEditDelegate(const KeyboardConfig* keyboardConfig_, QObject *parent): - QStyledItemDelegate(parent), - keyboardConfig(keyboardConfig_) -{} - -QWidget *LabelEditDelegate::createEditor(QWidget *parent, const QStyleOptionViewItem & option , - const QModelIndex & index ) const -{ - if( keyboardConfig->indicatorType == KeyboardConfig::SHOW_FLAG ) - return NULL; - - QWidget* widget = QStyledItemDelegate::createEditor(parent, option, index); - QLineEdit* lineEdit = static_cast(widget); - if( lineEdit != NULL ) { - lineEdit->setMaxLength(LayoutUnit::MAX_LABEL_LENGTH); - connect(lineEdit, &QLineEdit::textEdited, this, [this, lineEdit]() { - Q_EMIT const_cast(this)->commitData(lineEdit); - }); - } - return widget; -} - -void LabelEditDelegate::updateEditorGeometry(QWidget *editor, - const QStyleOptionViewItem &option, const QModelIndex &/* index */) const -{ - editor->setGeometry(option.rect); -} - -//void LabelEditDelegate::paint( QPainter * painter, const QStyleOptionViewItem & option, const QModelIndex & index ) const -//{ -// QStyleOptionViewItem option2(option); -//// option2.decorationPosition = QStyleOptionViewItem::Right; -// option2.decorationAlignment = Qt::AlignHCenter | Qt::AlignVCenter; -// QStyledItemDelegate::paint(painter, option2, index); -//} - - -// -// VariantComboDelegate -// -//TODO: reuse this function in kcm_add_layout_dialog.cpp -static void populateComboWithVariants(QComboBox* combo, const QString& layout, const Rules* rules) -{ - combo->clear(); - const LayoutInfo* layoutInfo = rules->getLayoutInfo(layout); - foreach(const VariantInfo* variantInfo, layoutInfo->variantInfos) { - combo->addItem(variantInfo->description, variantInfo->name); - } - combo->model()->sort(0); - combo->insertItem(0, i18nc("variant", "Default"), ""); - combo->setCurrentIndex(0); -} - -VariantComboDelegate::VariantComboDelegate(const KeyboardConfig* keyboardConfig_, const Rules* rules_, QObject *parent): - QStyledItemDelegate(parent), - keyboardConfig(keyboardConfig_), - rules(rules_) -{} - -QWidget *VariantComboDelegate::createEditor(QWidget *parent, const QStyleOptionViewItem &/* option */, - const QModelIndex & index ) const -{ - QComboBox *editor = new QComboBox(parent); - const LayoutUnit& layoutUnit = keyboardConfig->layouts[index.row()]; - populateComboWithVariants(editor, layoutUnit.layout, rules); - connect(editor, &QComboBox::currentTextChanged, this, [this, editor]() { - Q_EMIT const_cast(this)->commitData(editor); - }); - return editor; -} - -void VariantComboDelegate::setEditorData(QWidget *editor, const QModelIndex &index) const -{ - QComboBox *combo = static_cast(editor); - QString variant = index.model()->data(index, Qt::EditRole).toString(); - int itemIndex = combo->findData(variant); - if( itemIndex == -1 ) { - itemIndex = 0; - } - combo->setCurrentIndex(itemIndex); -} - -void VariantComboDelegate::setModelData(QWidget *editor, QAbstractItemModel *model, - const QModelIndex &index) const -{ - QComboBox *combo = static_cast(editor); - QString variant = combo->itemData(combo->currentIndex()).toString(); - model->setData(index, variant, Qt::EditRole); -} - -void VariantComboDelegate::updateEditorGeometry(QWidget *editor, - const QStyleOptionViewItem &option, const QModelIndex &/* index */) const -{ - editor->setGeometry(option.rect); -} - -// -// KKeySequenceWidgetDelegate -// -KKeySequenceWidgetDelegate::KKeySequenceWidgetDelegate(const KeyboardConfig* keyboardConfig_, QObject *parent): - QStyledItemDelegate(parent), - keyboardConfig(keyboardConfig_) -{} - -QWidget *KKeySequenceWidgetDelegate::createEditor(QWidget *parent, const QStyleOptionViewItem & /*option*/, - const QModelIndex & index ) const -{ - itemsBeingEdited.insert(index); - - KKeySequenceWidget *editor = new KKeySequenceWidget(parent); - editor->setFocusPolicy(Qt::StrongFocus); - editor->setModifierlessAllowed(false); - - const LayoutUnit& layoutUnit = keyboardConfig->layouts[index.row()]; - editor->setKeySequence(layoutUnit.getShortcut()); - - editor->captureKeySequence(); - connect(editor, &KKeySequenceWidget::keySequenceChanged, this, [this, editor]() { - Q_EMIT const_cast(this)->commitData(editor); - }); - - return editor; -} - -//void KKeySequenceWidgetDelegate::setEditorData(QWidget *editor, const QModelIndex &index) const -//{ -// KKeySequenceWidget *kkeysequencewidget = static_cast(editor); -// QString shortcut = index.model()->data(index, Qt::EditRole).toString(); -// kkeysequencewidget->setKeySequence(QKeySequence(shortcut)); -// kkeysequencewidget->captureKeySequence(); -// qDebug() << "set editor data"; -//} - -void KKeySequenceWidgetDelegate::setModelData(QWidget *editor, QAbstractItemModel *model, - const QModelIndex &index) const -{ - KKeySequenceWidget *kkeysequencewidget = static_cast(editor); - QString shortcut = kkeysequencewidget->keySequence().toString(); - model->setData(index, shortcut, Qt::EditRole); - itemsBeingEdited.remove(index); -} - -void KKeySequenceWidgetDelegate::paint(QPainter* painter, const QStyleOptionViewItem& option, - const QModelIndex& index) const -{ - if (itemsBeingEdited.contains(index)) { -// StyledBackgroundPainter::drawBackground(painter,option,index); - } - else { - QStyledItemDelegate::paint(painter,option,index); - } -} -// -// Xkb Options Tree View -// - -int XkbOptionsTreeModel::rowCount(const QModelIndex& parent) const { - if( ! parent.isValid() ) - return rules->optionGroupInfos.count(); - if( ! parent.parent().isValid() ) - return rules->optionGroupInfos[parent.row()]->optionInfos.count(); - return 0; -} - -QVariant XkbOptionsTreeModel::data(const QModelIndex& index, int role) const -{ - if (!index.isValid()) - return QVariant(); - - int row = index.row(); - - if (role == Qt::DisplayRole) { - if( ! index.parent().isValid() ) { - return rules->optionGroupInfos[row]->description; - } - else { - int groupRow = index.parent().row(); - const OptionGroupInfo* xkbGroup = rules->optionGroupInfos[groupRow]; - return xkbGroup->optionInfos[row]->description; - } - } - else if (role==Qt::CheckStateRole ) { - if( index.parent().isValid() ) { - int groupRow = index.parent().row(); - const OptionGroupInfo* xkbGroup = rules->optionGroupInfos[groupRow]; - const QString& xkbOptionName = xkbGroup->optionInfos[row]->name; - return keyboardConfig->xkbOptions.indexOf(xkbOptionName) == -1 - ? Qt::Unchecked : Qt::Checked; - } - else { - int groupRow = index.row(); - const OptionGroupInfo* xkbGroup = rules->optionGroupInfos[groupRow]; - foreach(const OptionInfo* optionInfo, xkbGroup->optionInfos) { - if( keyboardConfig->xkbOptions.indexOf(optionInfo->name) != -1 ) - return Qt::PartiallyChecked; - } - return Qt::Unchecked; - } - } - return QVariant(); -} - -bool XkbOptionsTreeModel::setData(const QModelIndex & index, const QVariant & value, int role) { - int groupRow = index.parent().row(); - if( groupRow < 0 ) return false; - - const OptionGroupInfo* xkbGroup = rules->optionGroupInfos[groupRow]; - const OptionInfo* option = xkbGroup->optionInfos[index.row()]; - - if( value.toInt() == Qt::Checked ) { - if( xkbGroup->exclusive ) { - // clear if exclusive (TODO: radiobutton) - int idx = keyboardConfig->xkbOptions.indexOf(QRegExp(xkbGroup->name + ".*")); - if( idx >= 0 ) { - for(int i=0; ioptionInfos.count(); i++) - if( xkbGroup->optionInfos[i]->name == keyboardConfig->xkbOptions[idx] ) { - setData(createIndex(i, index.column(), (quint32)index.internalId()-index.row()+i), Qt::Unchecked, role); - break; - } - // m_kxkbConfig->m_options.removeAt(idx); - // idx = m_kxkbConfig->m_options.indexOf(QRegExp(xkbGroupNm+".*")); - } - } - if( keyboardConfig->xkbOptions.indexOf(option->name) < 0 ) { - keyboardConfig->xkbOptions.append(option->name); - } - } - else { - keyboardConfig->xkbOptions.removeAll(option->name); - } - - emit dataChanged(index, index); - emit dataChanged(index.parent(), index.parent()); - return true; -} - -void XkbOptionsTreeModel::gotoGroup(const QString& groupName, QTreeView* view) { - const OptionGroupInfo* optionGroupInfo = rules->getOptionGroupInfo(groupName); - int index = rules->optionGroupInfos.indexOf((OptionGroupInfo*)optionGroupInfo); - if( index != -1 ) { - QModelIndex modelIdx = createIndex(index,0); -// view->selectionModel()->setCurrentIndex(createIndex(index,0), QItemSelectionModel::NoUpdate); - view->setExpanded(modelIdx, true); - view->scrollTo(modelIdx, QAbstractItemView::PositionAtTop); - view->selectionModel()->setCurrentIndex(modelIdx, QItemSelectionModel::Current); - view->setFocus(Qt::OtherFocusReason); - } -// else { -// qDebug() << "can't scroll to group" << group; -// } -} - diff --git a/kcms/keyboard/kcmmisc.h b/kcms/keyboard/kcmmisc.h deleted file mode 100644 --- a/kcms/keyboard/kcmmisc.h +++ /dev/null @@ -1,94 +0,0 @@ -/* - * keyboard.h - * - * Copyright (c) 1997 Patrick Dowler dowler@morgul.fsh.uvic.ca - * - * Requires the Qt widget libraries, available at no cost at - * http://www.troll.no/ - * - * 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 __KCMMISC_H__ -#define __KCMMISC_H__ - -#include -#include - -class QButtonGroup; -class Ui_KeyboardConfigWidget; - -const int DEFAULT_REPEAT_DELAY = 600; -const double DEFAULT_REPEAT_RATE = 25.0; - -enum TriState { - STATE_ON = 0, STATE_OFF = 1, STATE_UNCHANGED = 2 -}; - -class TriStateHelper { -public: - static void setTriState(QButtonGroup* group, TriState state); - static TriState getTriState(const QButtonGroup* group); - - static TriState getTriState(int state) { return static_cast(state); } - static int getInt(TriState state) { return static_cast(state); } - static const char* getString(TriState state) { - return state == STATE_ON ? "0" : state == STATE_OFF ? "1" : "2"; - } -}; - -class KCMiscKeyboardWidget : public QWidget -{ - Q_OBJECT -public: - KCMiscKeyboardWidget(QWidget *parent); - ~KCMiscKeyboardWidget(); - - void save(); - void load(); - void defaults(); - - QString quickHelp() const; - -private Q_SLOTS: - void changed(); - - void delaySliderChanged (int value); - void delaySpinboxChanged (int value); - void rateSliderChanged (int value); - void rateSpinboxChanged (double value); - void keyboardRepeatStateChanged(int selection); - -Q_SIGNALS: - void changed(bool state); - -private: - void setRepeat( TriState flag, int delay, double rate); - void setRepeatRate( int ); - - int getRepeatRate(); - - int sliderMax; - int clickVolume; - enum TriState keyboardRepeat; - enum TriState numlockState; - - QButtonGroup* _numlockButtonGroup; - QButtonGroup* _keyboardRepeatButtonGroup; - Ui_KeyboardConfigWidget& ui; -}; - -#endif - diff --git a/kcms/keyboard/kcmmisc.cpp b/kcms/keyboard/kcmmisc.cpp deleted file mode 100644 --- a/kcms/keyboard/kcmmisc.cpp +++ /dev/null @@ -1,231 +0,0 @@ -/* - * kcmmisc.cpp - * - * Copyright (c) 1997 Patrick Dowler dowler@morgul.fsh.uvic.ca - * - * Layout management, cleanups: - * Copyright (c) 1999 Dirk A. Mueller - * - * Requires the Qt widget libraries, available at no cost at - * http://www.troll.no/ - * - * 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 "kcmmisc.h" -#include "ui_kcmmiscwidget.h" - -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -#include -#include - - -KCMiscKeyboardWidget::KCMiscKeyboardWidget(QWidget *parent) - : QWidget(parent), - ui(*new Ui_KeyboardConfigWidget) -{ - ui.setupUi(this); - - ui.delay->setRange(100, 5000); - ui.delay->setSingleStep(50); - ui.rate->setRange(0.2, 50); - ui.rate->setSingleStep(5); - - sliderMax = (int)floor (0.5 + 2*(log(5000.0L)-log(100.0L)) / (log(5000.0L)-log(4999.0L))); - ui.delaySlider->setRange(0, sliderMax); - ui.delaySlider->setSingleStep(sliderMax/100); - ui.delaySlider->setPageStep(sliderMax/10); - ui.delaySlider->setTickInterval(sliderMax/10); - - ui.rateSlider->setRange(20, 5000); - ui.rateSlider->setSingleStep(30); - ui.rateSlider->setPageStep(500); - ui.rateSlider->setTickInterval(498); - - connect(ui.delay, SIGNAL(valueChanged(int)), this, SLOT(delaySpinboxChanged(int))); - connect(ui.delaySlider, &QAbstractSlider::valueChanged, this, &KCMiscKeyboardWidget::delaySliderChanged); - connect(ui.rate, SIGNAL(valueChanged(double)), this, SLOT(rateSpinboxChanged(double))); - connect(ui.rateSlider, &QAbstractSlider::valueChanged, this, &KCMiscKeyboardWidget::rateSliderChanged); - - _numlockButtonGroup = new QButtonGroup(ui.numlockButtonGroup); - _numlockButtonGroup->addButton(ui.radioButton1, 0); - _numlockButtonGroup->addButton(ui.radioButton2, 1); - _numlockButtonGroup->addButton(ui.radioButton3, 2); - - connect(_numlockButtonGroup, SIGNAL(buttonClicked(int)), this, SLOT(changed())); - - _keyboardRepeatButtonGroup = new QButtonGroup(ui.keyboardRepeatButtonGroup); - _keyboardRepeatButtonGroup->addButton(ui.keyboardRepeatOnRadioButton, 0); - _keyboardRepeatButtonGroup->addButton(ui.keyboardRepeatOffRadioButton, 1); - _keyboardRepeatButtonGroup->addButton(ui.keyboardRepeatUnchangedRadioButton, 2); - - connect(_keyboardRepeatButtonGroup, SIGNAL(buttonClicked(int)), this, SLOT(changed())); - connect(_keyboardRepeatButtonGroup, SIGNAL(buttonClicked(int)), this, SLOT(keyboardRepeatStateChanged(int))); - -// Not sure why we need this - if XKB is not found the whole keyboard module won't be compiled -//#if !defined(HAVE_XTEST) && !defined(HAVE_XKB) -// ui.numlockButtonGroup->setDisabled( true ); -//#endif -//#if !defined(HAVE_XKB) && !defined(HAVE_XF86MISC) -// ui.delay->setDisabled( true ); -// ui.rate->setDisabled( true ); -//#endif -} - -KCMiscKeyboardWidget::~KCMiscKeyboardWidget() -{ - delete &ui; -} - -// set the slider and LCD values -void KCMiscKeyboardWidget::setRepeat(TriState keyboardRepeat, int delay_, double rate_) -{ - TriStateHelper::setTriState( _keyboardRepeatButtonGroup, keyboardRepeat ); -// ui.repeatBox->setChecked(r == AutoRepeatModeOn); - ui.delay->setValue(delay_); - ui.rate->setValue(rate_); - delaySpinboxChanged(delay_); - rateSpinboxChanged(rate_); -} - -TriState TriStateHelper::getTriState(const QButtonGroup* group) -{ - int selected = group->checkedId(); - return selected < 0 ? STATE_UNCHANGED : getTriState(selected); -} - -void TriStateHelper::setTriState(QButtonGroup* group, TriState state) -{ - group->button( getInt(state) )->click(); -} - -void KCMiscKeyboardWidget::load() -{ - KConfigGroup config(KSharedConfig::openConfig(QStringLiteral("kcminputrc"), KConfig::NoGlobals), "Keyboard"); - - ui.delay->blockSignals(true); - ui.rate->blockSignals(true); - - // need to read as string to support old "true/false" parameter - QString key = config.readEntry("KeyboardRepeating", TriStateHelper::getString(STATE_ON)); - if( key == QLatin1String("true") || key == TriStateHelper::getString(STATE_ON)) { - keyboardRepeat = STATE_ON; - } - else if( key == QLatin1String("false") || key == TriStateHelper::getString(STATE_OFF)) { - keyboardRepeat = STATE_OFF; - } - else { - keyboardRepeat = STATE_UNCHANGED; - } - -// keyboardRepeat = (key ? AutoRepeatModeOn : AutoRepeatModeOff); - int delay = config.readEntry("RepeatDelay", DEFAULT_REPEAT_DELAY); - double rate = config.readEntry("RepeatRate", DEFAULT_REPEAT_RATE); - setRepeat(keyboardRepeat, delay, rate); - - // setRepeat(kbd.global_auto_repeat, ui.delay->value(), ui.rate->value()); - - numlockState = TriStateHelper::getTriState(config.readEntry( "NumLock", TriStateHelper::getInt(STATE_UNCHANGED) )); - TriStateHelper::setTriState( _numlockButtonGroup, numlockState ); - - ui.delay->blockSignals(false); - ui.rate->blockSignals(false); -} - -void KCMiscKeyboardWidget::save() -{ - KConfigGroup config(KSharedConfig::openConfig(QStringLiteral("kcminputrc"), KConfig::NoGlobals), "Keyboard"); - - keyboardRepeat = TriStateHelper::getTriState(_keyboardRepeatButtonGroup); - numlockState = TriStateHelper::getTriState(_numlockButtonGroup); - - config.writeEntry("KeyboardRepeating", TriStateHelper::getInt(keyboardRepeat)); - config.writeEntry("RepeatRate", ui.rate->value() ); - config.writeEntry("RepeatDelay", ui.delay->value() ); - config.writeEntry("NumLock", TriStateHelper::getInt(numlockState) ); - config.sync(); -} - -void KCMiscKeyboardWidget::defaults() -{ - setRepeat(STATE_ON, DEFAULT_REPEAT_DELAY, DEFAULT_REPEAT_RATE); - TriStateHelper::setTriState( _numlockButtonGroup, STATE_UNCHANGED ); - emit changed(true); -} - -QString KCMiscKeyboardWidget::quickHelp() const -{ - return QString(); - - /* "

Keyboard

This module allows you to choose options" - " for the way in which your keyboard works. The actual effect of" - " setting these options depends upon the features provided by your" - " keyboard hardware and the X server on which Plasma is running.

" - " For example, you may find that changing the key click volume" - " has no effect because this feature is not available on your system." */ -} - -void KCMiscKeyboardWidget::delaySliderChanged (int value) { - double alpha = sliderMax / (log(5000.0L) - log(100.0L)); - double linearValue = exp (value/alpha + log(100.0L)); - - ui.delay->setValue((int)floor(0.5 + linearValue)); - - emit changed(true); -} - -void KCMiscKeyboardWidget::delaySpinboxChanged (int value) { - double alpha = sliderMax / (log(5000.0L) - log(100.0L)); - double logVal = alpha * (log((double)value)-log(100.0L)); - - ui.delaySlider->setValue ((int)floor (0.5 + logVal)); - - emit changed(true); -} - -void KCMiscKeyboardWidget::rateSliderChanged (int value) { - ui.rate->setValue(value/100.0); - - emit changed(true); -} - -void KCMiscKeyboardWidget::rateSpinboxChanged (double value) { - ui.rateSlider->setValue ((int)(value*100)); - - emit changed(true); -} - -void KCMiscKeyboardWidget::changed() -{ - emit changed(true); -} - -void KCMiscKeyboardWidget::keyboardRepeatStateChanged(int selection) -{ - bool enabled = selection == TriStateHelper::getInt(STATE_ON); - ui.keyboardRepeatParamsGroupBox->setEnabled(enabled); - changed(); -} diff --git a/kcms/keyboard/kcmmiscwidget.ui b/kcms/keyboard/kcmmiscwidget.ui deleted file mode 100644 --- a/kcms/keyboard/kcmmiscwidget.ui +++ /dev/null @@ -1,273 +0,0 @@ - - - KeyboardConfigWidget - - - - 0 - 0 - 577 - 411 - - - - - - - If supported, this option allows you to setup the state of NumLock after Plasma startup.<p>You can configure NumLock to be turned on or off, or configure Plasma not to set NumLock state. - - - NumLock on Plasma Startup - - - - - - true - - - - - - T&urn on - - - - - - - &Turn off - - - - - - - Leave unchan&ged - - - - - - - - - - - - - Keyboard Repeat - - - - - - true - - - - - - T&urn on - - - - - - - Turn o&ff - - - - - - - &Leave unchanged - - - - - - - - - - Qt::Horizontal - - - - 159 - 20 - - - - - - - - - - - false - - - - - - - 0 - 0 - - - - &Delay: - - - delay - - - - - - - If supported, this option allows you to set the delay after which a pressed key will start generating keycodes. The 'Repeat rate' option controls the frequency of these keycodes. - - - 0 - - - 10000 - - - 1000 - - - 1000 - - - 5000 - - - Qt::Horizontal - - - 1000 - - - - - - - If supported, this option allows you to set the delay after which a pressed key will start generating keycodes. The 'Repeat rate' option controls the frequency of these keycodes. - - - ms - - - - - - - - 0 - 0 - - - - &Rate: - - - rate - - - - - - - If supported, this option allows you to set the rate at which keycodes are generated while a key is pressed. - - - 0 - - - 10000 - - - 1000 - - - 1000 - - - 5000 - - - Qt::Horizontal - - - 1000 - - - - - - - If supported, this option allows you to set the rate at which keycodes are generated while a key is pressed. - - - repeats/s - - - - - - - - - - - - - - - - - - Test area: - - - - - - - Allows to test keyboard repeat and click volume (just don't forget to apply the changes). - - - - - - - - - Qt::Horizontal - - - - - - - Qt::Vertical - - - - 20 - 40 - - - - - - - - - diff --git a/kcms/keyboard/kcmui/CMakeLists.txt b/kcms/keyboard/kcmui/CMakeLists.txt new file mode 100644 --- /dev/null +++ b/kcms/keyboard/kcmui/CMakeLists.txt @@ -0,0 +1,83 @@ +cmake_minimum_required(VERSION 3.10) + +set(CMAKE_AUTOMOC ON) + +# Find includes in corresponding build directories +set(CMAKE_INCLUDE_CURRENT_DIR ON) + +# Instruct CMake to run moc automatically when needed. +set(CMAKE_AUTOMOC ON) + +find_package(ECM REQUIRED NO_MODULE) +set(CMAKE_MODULE_PATH ${ECM_MODULE_PATH} ${ECM_KDE_MODULE_DIR}) + +find_package(Qt5 REQUIRED COMPONENTS + Core + Qml +) + +find_package(KF5 REQUIRED COMPONENTS + CoreAddons + KCMUtils + I18n + Plasma + PlasmaQuick + Declarative +) + +include(KDEInstallDirs) +include(KDECompilerSettings) +include(KDECMakeSettings) + +# KI18N Translation Domain for this library +add_definitions(-DTRANSLATION_DOMAIN=\"kcmkeyboard\") + +set(kcm_keyboard_SRCS + kcm_keyboard.cpp + hardware_config_model.cpp + layout_config_model.cpp + keyboard_model_model.cpp + abstract_advanced_model.cpp + advanced_model.cpp + advanced_flatten_proxy_model.cpp + advanced_filter_proxy_model.cpp +) + +ecm_qt_declare_logging_category(kcm_keyboard_SRCS + HEADER debug.h + IDENTIFIER KCM_KEYBOARD + CATEGORY_NAME org.kde.kcm_keyboard + DEFAULT_SEVERITY Warning) + +add_library(kcm_keyboard MODULE ${kcm_keyboard_SRCS}) + +target_link_libraries(kcm_keyboard + KF5::ConfigCore + KF5::CoreAddons + KF5::QuickAddons + KF5::Declarative + KF5::KCMUtils + KF5::I18n + KF5::GlobalAccel + KF5::WindowSystem + KF5::IconThemes + KF5::XmlGui + KF5::Plasma + KF5::ItemModels + KF5::GuiAddons + Qt5::Quick + Qt5::Concurrent + Qt5::X11Extras + Qt5::DBus + kcm_keyboard_layoutmodel +) + +kcoreaddons_desktop_to_json(kcm_keyboard "kcm_keyboard.desktop" SERVICE_TYPES kcmodule.desktop) +install(FILES kcm_keyboard.desktop DESTINATION ${KDE_INSTALL_KSERVICES5DIR}) +install(TARGETS kcm_keyboard DESTINATION ${KDE_INSTALL_PLUGINDIR}/kcms) + +# need this line because the old .so will be loaded without it +install(TARGETS kcm_keyboard DESTINATION ${KDE_INSTALL_PLUGINDIR}) + +kpackage_install_package(package kcm_keyboard kcms) + diff --git a/kcms/keyboard/kcmui/abstract_advanced_model.h b/kcms/keyboard/kcmui/abstract_advanced_model.h new file mode 100644 --- /dev/null +++ b/kcms/keyboard/kcmui/abstract_advanced_model.h @@ -0,0 +1,26 @@ +#ifndef ABSTRACT_ADVANCED_MODEL_H +#define ABSTRACT_ADVANCED_MODEL_H + +#include + +class AbstractAdvancedModel +{ +public: + virtual ~AbstractAdvancedModel() = default; + + QHash roleNames() const; + + struct Roles { + enum { + DescriptionRole = Qt::DisplayRole, + NameRole = Qt::UserRole + 1, + SectionNameRole, + ExclusiveRole, + SelectedRole, + IsGroupRole, + SectionNamePlusIsGroupRole, + }; + }; +}; + +#endif // ABSTRACT_ADVANCED_MODEL_H diff --git a/kcms/keyboard/kcmui/abstract_advanced_model.cpp b/kcms/keyboard/kcmui/abstract_advanced_model.cpp new file mode 100644 --- /dev/null +++ b/kcms/keyboard/kcmui/abstract_advanced_model.cpp @@ -0,0 +1,14 @@ +#include "abstract_advanced_model.h" + +QHash AbstractAdvancedModel::roleNames() const +{ + return { + { Roles::DescriptionRole, "description" }, + { Roles::NameRole, "name" }, + { Roles::SectionNameRole, "section_name" }, + { Roles::SelectedRole, "selected" }, + { Roles::ExclusiveRole, "exclusive" }, + { Roles::IsGroupRole, "is_group" }, + { Roles::SectionNamePlusIsGroupRole, "section_name_plus_is_group" } + }; +} diff --git a/kcms/keyboard/kcmui/advanced_filter_proxy_model.h b/kcms/keyboard/kcmui/advanced_filter_proxy_model.h new file mode 100644 --- /dev/null +++ b/kcms/keyboard/kcmui/advanced_filter_proxy_model.h @@ -0,0 +1,15 @@ +#ifndef ADVANCED_FILTER_PROXY_MODEL_H +#define ADVANCED_FILTER_PROXY_MODEL_H + +#include "abstract_advanced_model.h" +#include + +class AdvancedFilterProxyModel : public QSortFilterProxyModel, public AbstractAdvancedModel { + Q_OBJECT +public: + explicit AdvancedFilterProxyModel(QObject* parent = nullptr); + + bool filterAcceptsRow(int source_row, const QModelIndex &source_parent) const override; +}; + +#endif // ADVANCED_FILTER_PROXY_MODEL_H diff --git a/kcms/keyboard/kcmui/advanced_filter_proxy_model.cpp b/kcms/keyboard/kcmui/advanced_filter_proxy_model.cpp new file mode 100644 --- /dev/null +++ b/kcms/keyboard/kcmui/advanced_filter_proxy_model.cpp @@ -0,0 +1,13 @@ +#include "advanced_filter_proxy_model.h" + +AdvancedFilterProxyModel::AdvancedFilterProxyModel(QObject* parent) + : QSortFilterProxyModel(parent) +{ +} + +bool AdvancedFilterProxyModel::filterAcceptsRow(int source_row, const QModelIndex &source_parent) const +{ + QString groupName = sourceModel()->data(sourceModel()->index(source_row, 0, source_parent), + Roles::SectionNameRole).toString(); + return !QStringList({"grp", "lv3", "lv5"}).contains(groupName); +} diff --git a/kcms/keyboard/kcmui/advanced_flatten_proxy_model.h b/kcms/keyboard/kcmui/advanced_flatten_proxy_model.h new file mode 100644 --- /dev/null +++ b/kcms/keyboard/kcmui/advanced_flatten_proxy_model.h @@ -0,0 +1,17 @@ +#ifndef ADVANCED_FLATTEN_PROXY_MODEL_H +#define ADVANCED_FLATTEN_PROXY_MODEL_H + +#include + +#include "abstract_advanced_model.h" + +class AdvancedFlattenProxyModel : public KDescendantsProxyModel, public AbstractAdvancedModel +{ + Q_OBJECT + +public: + AdvancedFlattenProxyModel(QObject *parent = nullptr); + QHash roleNames() const override; +}; + +#endif // ADVANCED_FLATTEN_PROXY_MODEL_H diff --git a/kcms/keyboard/kcmui/advanced_flatten_proxy_model.cpp b/kcms/keyboard/kcmui/advanced_flatten_proxy_model.cpp new file mode 100644 --- /dev/null +++ b/kcms/keyboard/kcmui/advanced_flatten_proxy_model.cpp @@ -0,0 +1,11 @@ +#include "advanced_flatten_proxy_model.h" + +AdvancedFlattenProxyModel::AdvancedFlattenProxyModel(QObject *parent) + : KDescendantsProxyModel(parent) +{ +} + +QHash AdvancedFlattenProxyModel::roleNames() const +{ + return AbstractAdvancedModel::roleNames(); +} diff --git a/kcms/keyboard/kcmui/advanced_model.h b/kcms/keyboard/kcmui/advanced_model.h new file mode 100644 --- /dev/null +++ b/kcms/keyboard/kcmui/advanced_model.h @@ -0,0 +1,36 @@ +#ifndef ADVANCEDMODEL_H +#define ADVANCEDMODEL_H + +#include +#include "abstract_advanced_model.h" + +class AdvancedModel : public QAbstractItemModel, public AbstractAdvancedModel +{ + Q_OBJECT + +public: + explicit AdvancedModel(QObject *parent = nullptr); + + int rowCount(const QModelIndex& parent = QModelIndex()) const override; + + int columnCount(const QModelIndex& parent = QModelIndex()) const override; + + Qt::ItemFlags flags(const QModelIndex& index) const override; + + QModelIndex index(int row, int column, + const QModelIndex& parent = QModelIndex()) const override; + + QModelIndex parent(const QModelIndex& index) const override; + + QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const override; + + bool setData(const QModelIndex &index, const QVariant &value, int role) override; + + QStringList enabledOptions() const; + void setEnabledOptions(const QStringList &enabledOptions); + +private: + QStringList m_enabledOptions; +}; + +#endif // ADVANCEDMODEL_H diff --git a/kcms/keyboard/kcmui/advanced_model.cpp b/kcms/keyboard/kcmui/advanced_model.cpp new file mode 100644 --- /dev/null +++ b/kcms/keyboard/kcmui/advanced_model.cpp @@ -0,0 +1,155 @@ +#include "advanced_model.h" +#include "../xkb_rules.h" +#include + +AdvancedModel::AdvancedModel(QObject *parent) + : QAbstractItemModel(parent) +{ +} + +int AdvancedModel::rowCount(const QModelIndex &parent) const +{ + if (!parent.isValid()) { // root + return XkbRules::self()->optionGroupInfos.size(); + } + + if (!parent.parent().isValid()) { // 2nd level + return XkbRules::self()->optionGroupInfos[parent.row()]->optionInfos.size(); + } + + return 0; +} + +int AdvancedModel::columnCount(const QModelIndex &parent) const +{ + Q_UNUSED(parent); + return 1; +} + +Qt::ItemFlags AdvancedModel::flags(const QModelIndex &index) const +{ + if (!index.isValid()) { + return Qt::NoItemFlags; + } + + return QAbstractItemModel::flags(index); +} + +QModelIndex AdvancedModel::index(int row, int column, const QModelIndex &parent) const +{ + if (column > 0) return QModelIndex(); + if (!parent.isValid()) { + return createIndex(row, column, quintptr(-1)); + } + else if (!parent.parent().isValid()){ + return createIndex(row, column, quintptr(parent.row())); + } + return QModelIndex(); +} + +QModelIndex AdvancedModel::parent(const QModelIndex &index) const +{ + if (!index.isValid()) { + return QModelIndex(); + } + + if (index.internalId() == quintptr(-1)) { // root + return QModelIndex(); + } + + return createIndex(static_cast(index.internalId()), 0, quintptr(-1)); +} + +QVariant AdvancedModel::data(const QModelIndex &index, int role) const +{ + if (!index.isValid()) { + return QVariant(); + } + + if (!index.parent().isValid()) { + auto const& infos = XkbRules::self()->optionGroupInfos[index.row()]; + + switch (role) { + case Roles::DescriptionRole: + return infos->description; + case Roles::NameRole: + case Roles::SectionNameRole: + return infos->name; + case Roles::SelectedRole: + return false; + case Roles::ExclusiveRole: + return infos->exclusive; + case Roles::IsGroupRole: + return true; + case Roles::SectionNamePlusIsGroupRole: + return infos->name + "+true"; + } + } + else if (!index.parent().parent().isValid()){ + auto const& info = XkbRules::self()->optionGroupInfos[index.parent().row()]->optionInfos[index.row()]; + + switch (role) { + case Roles::DescriptionRole: + return info->description; + case Roles::NameRole: + return info->name; + case Roles::SectionNameRole: + return data(index.parent(), Roles::SectionNameRole); + case Roles::SelectedRole: + return m_enabledOptions.contains(info->name); + case Roles::ExclusiveRole: + return data(index.parent(), Roles::ExclusiveRole); + case Roles::IsGroupRole: + return false; + case Roles::SectionNamePlusIsGroupRole: + return data(index.parent(), Roles::SectionNameRole).toString() + "+false"; + } + } + + return QVariant(); +} + +bool AdvancedModel::setData(const QModelIndex &idx, const QVariant &value, int role) +{ + if (role == Roles::SelectedRole) { + QString optionName = data(idx, Roles::NameRole).toString(); + bool exclusive = data(idx, Roles::ExclusiveRole).toBool(); + + m_enabledOptions.removeAll(optionName); + if (exclusive) { + for (int i = 0; i < m_enabledOptions.size(); ++i) { + QString name = m_enabledOptions[i]; + if (name.split(":")[0] == optionName.split(":")[0]) { + m_enabledOptions.removeAt(i); + + for (int j = 0; j < rowCount(idx.parent()); ++j) { + QModelIndex otherIdx = index(j, 0, idx.parent()); + if (data(otherIdx, Roles::NameRole).toString() == name) { + emit dataChanged(otherIdx, otherIdx, { Roles::SelectedRole }); + } + } + + } + } + } + + if (value.toBool()) { + m_enabledOptions << optionName; + } + + emit dataChanged(idx, idx, { Roles::SelectedRole }); + qDebug() << m_enabledOptions; + return true; + } + return false; +} + +QStringList AdvancedModel::enabledOptions() const +{ + return m_enabledOptions; +} + +void AdvancedModel::setEnabledOptions(const QStringList &enabledOptions) +{ + m_enabledOptions = enabledOptions; +} diff --git a/kcms/keyboard/kcmui/hardware_config_model.h b/kcms/keyboard/kcmui/hardware_config_model.h new file mode 100644 --- /dev/null +++ b/kcms/keyboard/kcmui/hardware_config_model.h @@ -0,0 +1,68 @@ +#ifndef KCM_KEYBOARD_DATAMODEL_H +#define KCM_KEYBOARD_DATAMODEL_H + +#include + +#include + +#include "keyboard_model_model.h" +#include "../xkb_rules.h" + +enum class TriState { + ON = 0, + OFF = 1, + UNCHANGED = 2 +}; + +class HardwareConfigModel : public QObject { + Q_OBJECT + Q_PROPERTY(KeyboardModelModel* keyboardModelModel READ keyboardModelModel NOTIFY keyboardModelModelChanged) + Q_PROPERTY(int currentIndex READ currentIndex WRITE setCurrentIndex NOTIFY currentIndexChanged) + Q_PROPERTY(int numlockOnStartup READ numlockOnStartup WRITE setNumlockOnStartup NOTIFY numlockOnStartupChanged) + Q_PROPERTY(int keyboardRepeat READ keyboardRepeat WRITE setKeyboardRepeat NOTIFY keyboardRepeatChanged) + Q_PROPERTY(int repeatDelay READ repeatDelay WRITE setRepeatDelay NOTIFY repeatDelayChanged) + Q_PROPERTY(double repeatRate READ repeatRate WRITE setRepeatRate NOTIFY repeatRateChanged) + +public: + explicit HardwareConfigModel(QObject* parent); + +public: + KeyboardModelModel* keyboardModelModel(); + + int currentIndex(); + void setCurrentIndex(int idx); + + int numlockOnStartup(); + void setNumlockOnStartup(int state); + + int keyboardRepeat(); + void setKeyboardRepeat(int state); + + int repeatDelay(); + void setRepeatDelay(int ms); + + double repeatRate(); + void setRepeatRate(double rate); + + QString keyboardModel() const; + void setKeyboardModel(const QString &keyboardModel); + +Q_SIGNALS: + void keyboardModelModelChanged(); + void currentIndexChanged(); + void numlockOnStartupChanged(); + void keyboardRepeatChanged(); + void repeatDelayChanged(); + void repeatRateChanged(); + +private: + KeyboardModelModel m_keyboard_model_model; + + TriState m_numlockOnStartup; + TriState m_keyboardRepeat; + int m_repeatDelay; + double m_repeatRate; + QString m_keyboardModel; +}; + +#endif // KCM_KEYBOARD_DATAMODEL_H diff --git a/kcms/keyboard/kcmui/hardware_config_model.cpp b/kcms/keyboard/kcmui/hardware_config_model.cpp new file mode 100644 --- /dev/null +++ b/kcms/keyboard/kcmui/hardware_config_model.cpp @@ -0,0 +1,99 @@ +#include "hardware_config_model.h" + +#include +#include +#include +#include +#include + +HardwareConfigModel::HardwareConfigModel(QObject* parent) + : QObject(parent) + , m_keyboard_model_model(*XkbRules::self()) +{ +} + +KeyboardModelModel* HardwareConfigModel::keyboardModelModel() +{ + return &m_keyboard_model_model; +} + +int HardwareConfigModel::currentIndex() +{ + int index = m_keyboard_model_model.findIndexByName(m_keyboardModel); + if (index >= 0) + return index; + return m_keyboard_model_model.findIndexByName("pc104"); +} + +void HardwareConfigModel::setCurrentIndex(int idx) +{ + QModelIndex mindex = m_keyboard_model_model.index(idx); + QVariant data = m_keyboard_model_model.data(mindex, KeyboardModelModel::Roles::NameRole); + m_keyboardModel = data.value(); + emit currentIndexChanged(); +} + +int HardwareConfigModel::numlockOnStartup() +{ + return static_cast(m_numlockOnStartup); +} + +void HardwareConfigModel::setNumlockOnStartup(int state) +{ + if (m_numlockOnStartup != static_cast(state)) { + m_numlockOnStartup = static_cast(state); + emit numlockOnStartupChanged(); + } +} + +int HardwareConfigModel::keyboardRepeat() +{ + return static_cast(m_keyboardRepeat); +} + +void HardwareConfigModel::setKeyboardRepeat(int state) +{ + if (m_keyboardRepeat != static_cast(state)) { + m_keyboardRepeat = static_cast(state); + emit keyboardRepeatChanged(); + } +} + +int HardwareConfigModel::repeatDelay() +{ + return m_repeatDelay; +} + +void HardwareConfigModel::setRepeatDelay(int ms) +{ + if (m_repeatDelay != ms) { + m_repeatDelay = ms; + emit repeatDelayChanged(); + } +} + +double HardwareConfigModel::repeatRate() +{ + return m_repeatRate; +} + +void HardwareConfigModel::setRepeatRate(double rate) +{ + if (m_repeatRate != rate) { + m_repeatRate = rate; + emit repeatRateChanged(); + } +} + +QString HardwareConfigModel::keyboardModel() const +{ + return m_keyboardModel; +} + +void HardwareConfigModel::setKeyboardModel(const QString &keyboardModel) +{ + if (m_keyboardModel != keyboardModel) { + m_keyboardModel = keyboardModel; + emit currentIndexChanged(); + } +} diff --git a/kcms/keyboard/kcmui/kcm_keyboard.h b/kcms/keyboard/kcmui/kcm_keyboard.h new file mode 100644 --- /dev/null +++ b/kcms/keyboard/kcmui/kcm_keyboard.h @@ -0,0 +1,48 @@ +#ifndef NEW_KEYBOARD_MAIN_H +#define NEW_KEYBOARD_MAIN_H + +#include + +#include "hardware_config_model.h" +#include "layout_config_model.h" +#include "advanced_flatten_proxy_model.h" + +class AdvancedModel; + +class KcmKeyboard : public KQuickAddons::ConfigModule { + Q_OBJECT + Q_PROPERTY(HardwareConfigModel* hardwareModel READ hardwareModel NOTIFY hardwareModelChanged) + Q_PROPERTY(LayoutConfigModel* layoutModel READ layoutModel NOTIFY layoutModelChanged) + Q_PROPERTY(AdvancedFlattenProxyModel* advancedModel READ advancedModel NOTIFY advancedModelChanged) + +public: + KcmKeyboard(QObject* parent, const QVariantList& args); + virtual ~KcmKeyboard() override; + +public Q_SLOTS: + virtual void load() override; + virtual void save() override; + virtual void defaults() override; + void changed(); + +public: + HardwareConfigModel* hardwareModel(); + LayoutConfigModel* layoutModel(); + AdvancedFlattenProxyModel *advancedModel(); + +Q_SIGNALS: + void hardwareModelChanged(); + void layoutModelChanged(); + void advancedModelChanged(); + +private: + HardwareConfigModel* m_hardwareConfigModel; + LayoutConfigModel* m_layoutConfigModel; + AdvancedFlattenProxyModel* m_advancedModel; + AdvancedModel* m_underlyingAdvancedModel; + + KActionCollection* m_actionCollection; + QAction* m_nextLayoutAction; +}; + +#endif // NEW_KEYBOARD_MAIN_H diff --git a/kcms/keyboard/kcmui/kcm_keyboard.cpp b/kcms/keyboard/kcmui/kcm_keyboard.cpp new file mode 100644 --- /dev/null +++ b/kcms/keyboard/kcmui/kcm_keyboard.cpp @@ -0,0 +1,237 @@ +#include "kcm_keyboard.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "hardware_config_model.h" +#include "layout_config_model.h" +#include "layout_list_xkb_expand_proxy_model.h" +#include "advanced_model.h" +#include "advanced_filter_proxy_model.h" +#include "advanced_flatten_proxy_model.h" + +#include "../keyboard_dbus.h" + +K_PLUGIN_FACTORY_WITH_JSON(KeyboardModuleFactory, + "kcm_keyboard.json", + registerPlugin();) + +KcmKeyboard::KcmKeyboard(QObject* parent, const QVariantList& args) + : KQuickAddons::ConfigModule(parent, args) + , m_hardwareConfigModel(new HardwareConfigModel(this)) + , m_layoutConfigModel(new LayoutConfigModel(this)) + , m_advancedModel(new AdvancedFlattenProxyModel(this)) + , m_underlyingAdvancedModel(new AdvancedModel(this)) +{ + AdvancedFilterProxyModel *filter = new AdvancedFilterProxyModel(this); + filter->setSourceModel(m_underlyingAdvancedModel); + m_advancedModel->setSourceModel(filter); + + KAboutData* about = new KAboutData( + "kcm_keyboard", i18n("..."), + QStringLiteral("1.0"), QString(), KAboutLicense::GPL); + + about->addAuthor(i18n("Andriy Rysin")); + about->addAuthor(i18n("Park Gun")); + setAboutData(about); + setButtons(Help | Apply | Default); + + m_actionCollection = new KActionCollection(this, QStringLiteral("KDE Keyboard Layout Switcher")); + m_nextLayoutAction = m_actionCollection->addAction(QStringLiteral("Switch to Next Keyboard Layout")); + m_nextLayoutAction->setText(i18n("Switch to Next Keyboard Layout")); + m_nextLayoutAction->setProperty("isConfigurationAction", true); + + QObject::connect(mainUi(), SIGNAL(changed()), this, SLOT(changed())); +} + +KcmKeyboard::~KcmKeyboard() +{ +} + +void KcmKeyboard::load() +{ + { + KConfigGroup kxkbrc( + KSharedConfig::openConfig(QStringLiteral("kxkbrc"), KConfig::NoGlobals), + QStringLiteral("Layout")); + + m_hardwareConfigModel->setKeyboardModel(kxkbrc.readEntry("Model", "pc104")); + + m_layoutConfigModel->loadEnabledLayouts(); + + m_layoutConfigModel->setShowLayoutIndicator(kxkbrc.readEntry("ShowLayoutIndicator", true)); + m_layoutConfigModel->setShowForSingleLayout(kxkbrc.readEntry("ShowSingle", false)); + + m_layoutConfigModel->setLayoutIndicatorShowFlag(kxkbrc.readEntry("ShowFlag", false)); + m_layoutConfigModel->setLayoutIndicatorShowLabel(kxkbrc.readEntry("ShowLabel", true)); + + QString switching_policy = kxkbrc.readEntry("SwitchMode", "Global"); + + auto it = std::find( + std::begin(LayoutConfigModel::switch_modes), + std::end(LayoutConfigModel::switch_modes), + switching_policy); + if (it != std::end(LayoutConfigModel::switch_modes)) { + m_layoutConfigModel->setSwitchingPolicyIndex( + static_cast(it - std::begin(LayoutConfigModel::switch_modes))); + } else { + qWarning() << "invalid switching policy " << switching_policy; + } + + QStringList options = kxkbrc.readEntry("Options", "").split(","); + QStringList miscOptions; + for (QString const& option : options) { + QString groupName = option.split(":")[0]; + + if (groupName == "grp") { + m_layoutConfigModel->setMainShiftKey(option); + } + else if (groupName == "lv3") { + m_layoutConfigModel->setThirdLevelShortcut(option); + } + else { + miscOptions << option; + } + } + + m_underlyingAdvancedModel->setEnabledOptions(miscOptions); + } + + // Alternative Shortcut + KGlobalAccel::self()->setShortcut( + m_nextLayoutAction, + QList() << QKeySequence(Qt::ALT + Qt::CTRL + Qt::Key_K), + KGlobalAccel::Autoloading); + QList shortcuts = KGlobalAccel::self()->shortcut(m_nextLayoutAction); + QKeySequence shortcut = shortcuts.isEmpty() ? QKeySequence() : shortcuts.first(); + m_layoutConfigModel->setAlternativeShortcut(shortcut.toString()); + + { + KConfigGroup kcminputrc( + KSharedConfig::openConfig(QStringLiteral("kcminputrc")), + QStringLiteral("Keyboard")); + + m_hardwareConfigModel->setNumlockOnStartup( + kcminputrc.readEntry("NumLock", static_cast(TriState::UNCHANGED))); + m_hardwareConfigModel->setKeyboardRepeat( + kcminputrc.readEntry("KeyboardRepeating", static_cast(TriState::UNCHANGED))); + m_hardwareConfigModel->setRepeatDelay( + kcminputrc.readEntry("RepeatDelay", 600)); + m_hardwareConfigModel->setRepeatRate( + kcminputrc.readEntry("RepeatRate", 25.0)); + } +} + +void KcmKeyboard::save() +{ + { + KConfigGroup kxkbrc( + KSharedConfig::openConfig(QStringLiteral("kxkbrc"), KConfig::NoGlobals), + QStringLiteral("Layout")); + + kxkbrc.writeEntry("Model", m_hardwareConfigModel->keyboardModel()); + + kxkbrc.writeEntry("ShowLayoutIndicator", m_layoutConfigModel->showLayoutIndicator()); + + kxkbrc.writeEntry("ShowSingle", m_layoutConfigModel->showForSingleLayout()); + + kxkbrc.writeEntry("ShowFlag", m_layoutConfigModel->layoutIndicatorShowFlag()); + kxkbrc.writeEntry("ShowLabel", m_layoutConfigModel->layoutIndicatorShowLabel()); + + if (m_layoutConfigModel->switchingPolicyIndex() >= 0 && m_layoutConfigModel->switchingPolicyIndex() < std::end(LayoutConfigModel::switch_modes) - std::begin(LayoutConfigModel::switch_modes)) { + kxkbrc.writeEntry("SwitchMode", LayoutConfigModel::switch_modes[m_layoutConfigModel->switchingPolicyIndex()]); + } else { + qWarning() << "invalid switching policy index" << m_layoutConfigModel->switchingPolicyIndex(); + } + + QStringList options = m_underlyingAdvancedModel->enabledOptions(); + if (!m_layoutConfigModel->mainShiftKey().isEmpty()) { + options << m_layoutConfigModel->mainShiftKey(); + } + if (!m_layoutConfigModel->thirdLevelShortcut().isEmpty()) { + options << m_layoutConfigModel->thirdLevelShortcut(); + } + kxkbrc.writeEntry("Options", options.join(",")); + + m_layoutConfigModel->saveEnabledLayouts(); + + kxkbrc.sync(); + } + + KGlobalAccel::self()->setShortcut( + m_nextLayoutAction, + QList() << QKeySequence(m_layoutConfigModel->alternativeShortcut()), + KGlobalAccel::NoAutoloading); + + { + KConfigGroup kcminputrc( + KSharedConfig::openConfig(QStringLiteral("kcminputrc")), + QStringLiteral("Keyboard")); + + kcminputrc.writeEntry("NumLock", static_cast(m_hardwareConfigModel->numlockOnStartup())); + kcminputrc.writeEntry("KeyboardRepeating", static_cast(m_hardwareConfigModel->keyboardRepeat())); + kcminputrc.writeEntry("RepeatDelay", m_hardwareConfigModel->repeatDelay()); + kcminputrc.writeEntry("RepeatRate", m_hardwareConfigModel->repeatRate()); + + kcminputrc.sync(); + } + + // dbus call to the kded (in X11) / kwin (in Wayland) to apply the config changes + QDBusMessage message = QDBusMessage::createSignal( + KEYBOARD_DBUS_OBJECT_PATH, + KEYBOARD_DBUS_SERVICE_NAME, + KEYBOARD_DBUS_CONFIG_RELOAD_MESSAGE); + QDBusConnection::sessionBus().send(message); +} + +void KcmKeyboard::defaults() +{ + m_hardwareConfigModel->setKeyboardModel(QStringLiteral("pc104")); + + m_hardwareConfigModel->setNumlockOnStartup(static_cast(TriState::UNCHANGED)); + m_hardwareConfigModel->setKeyboardRepeat(static_cast(TriState::UNCHANGED)); + m_hardwareConfigModel->setRepeatDelay(600); + m_hardwareConfigModel->setRepeatRate(25.0); + + m_layoutConfigModel->setShowLayoutIndicator(true); + m_layoutConfigModel->setShowForSingleLayout(false); + m_layoutConfigModel->setLayoutIndicatorShowFlag(false); + m_layoutConfigModel->setLayoutIndicatorShowLabel(true); + m_layoutConfigModel->setSwitchingPolicyIndex(0); + m_layoutConfigModel->setAlternativeShortcut( + QKeySequence(Qt::ALT + Qt::CTRL + Qt::Key_K).toString()); + + changed(); +} + +void KcmKeyboard::changed() +{ + setNeedsSave(true); + emit needsSaveChanged(); +} + +HardwareConfigModel* KcmKeyboard::hardwareModel() +{ + return m_hardwareConfigModel; +} + +LayoutConfigModel* KcmKeyboard::layoutModel() +{ + return m_layoutConfigModel; +} + +AdvancedFlattenProxyModel *KcmKeyboard::advancedModel() +{ + return m_advancedModel; +} + +#include diff --git a/kcms/keyboard/kcm_keyboard.desktop b/kcms/keyboard/kcmui/kcm_keyboard.desktop rename from kcms/keyboard/kcm_keyboard.desktop rename to kcms/keyboard/kcmui/kcm_keyboard.desktop --- a/kcms/keyboard/kcm_keyboard.desktop +++ b/kcms/keyboard/kcmui/kcm_keyboard.desktop @@ -168,7 +168,7 @@ X-KDE-Keywords[gl]=teclado, repetición de teclas, volume do clic, dispositivo de entrada, repetición, volume, Bloq num, tipo de teclado, modelo, disposición idioma, teclado alternativo, troco de teclado, Ctrl, Bloq maiús, til, circunflexo, matar o servidor X, LED X-KDE-Keywords[hu]=Billentyűzet,Billentyűzet ismétlés,Kattintási hangerő,Beviteli eszközök,ismétlés,hangerő,NumLock,Numerikus billentyűzet,Billentyűzet típus,Billentyűzet modell,Billentyűzetkiosztás,Nyelv,Alternatív billentyűzet,Billentyűzetváltó,Ctrl billentyű,Caps Lock,Eszperantó,Ékezet,X kiszolgáló kilövése,LED billentyűzet,Levélírás billentyű X-KDE-Keywords[ia]=Claviero,Repetition de claviero,Volumine de click,Dispositivos de ingresso,volumine, NumLock,Typo de claviero,modello de Claviero,disposition de claviero, Disposition de clave, Linguage,Claviero alternate,commutation de claviero,Clave Ctrl,Caps Lock,Esperanto, Circumflexe,Occide X Server, Claviero LED, Clave composite -X-KDE-Keywords[id]=Keyboard,ulangi Keyboard,volume Klik,Perangkat Input,ulangi,volume,NumLock,NumPad,tipe Keyboard,model Keyboard,tata letak Keyboard,tata letak Tuts,Bahasa,Keyboard Alternatif,pengganti Keyboard,Tuts Ctrl,Caps Lock,Esperanto,Circumflex,Matikan X Server,Keyboard LED,Buat Tuts +X-KDE-Keywords[id]=Keyboard,ulangi Keyboard,volume Klik,Perangkat Masukan,ulangi,volume,NumLock,NumPad,tipe Keyboard,model Keyboard,tata letak Keyboard,tata letak Tombol,Bahasa,Keyboard Alternatif,pengganti Keyboard,Tombol Ctrl,Caps Lock,Esperanto,Circumflex,Matikan X Server,Keyboard LED,Buat Tombol X-KDE-Keywords[it]=tastiera,ripetizione tastiera,clic volume,dispositivi di ingresso,ripetizione,volume,bloc num,tastierino numerico,tipo tastiera, modello tastiera,mappatura tastiera,mappatura tasto,lingua,tastiera alternativa,cambio tastiera, tasto ctrl,maiusc,esperanto,circonflesso,uccidi server x,led tastiera,tasto composizione X-KDE-Keywords[kk]=Keyboard,Keyboard repeat,Click volume,Input Devices,repeat,volume,NumLock,NumPad,Keyboard type,Keyboard model,Keyboard layout,Key layout,Language,Alternate Keyboard,Keyboard switching,Ctrl Key,Caps Lock,Esperanto,Circumflex,Kill X Server,LED Keyboard,Compose Key X-KDE-Keywords[km]=Keyboard,Keyboard repeat,Click volume,Input Devices,repeat,volume,NumLock,NumPad,Keyboard type,Keyboard model,Keyboard layout,Key layout,Language,Alternate Keyboard,Keyboard switching,Ctrl Key,Caps Lock,Esperanto,Circumflex,Kill X Server,LED Keyboard,Compose Key diff --git a/kcms/keyboard/kcmui/keyboard_model_model.h b/kcms/keyboard/kcmui/keyboard_model_model.h new file mode 100644 --- /dev/null +++ b/kcms/keyboard/kcmui/keyboard_model_model.h @@ -0,0 +1,44 @@ +#ifndef KCM_KEYBOARD_KEYBOARDMODELMODEL_H +#define KCM_KEYBOARD_KEYBOARDMODELMODEL_H + +#include +#include + +#include "../xkb_rules.h" + +class KeyboardModelModel : public QAbstractListModel { + Q_OBJECT + +public: + explicit KeyboardModelModel(XkbRules const& rules, QObject* parent = nullptr); + + int rowCount(const QModelIndex& parent = QModelIndex()) const override; + + QVariant data(const QModelIndex& index, int role) const override; + + Qt::ItemFlags flags(const QModelIndex& index) const override; + + struct Roles { + enum { + DescriptionRole = Qt::UserRole + 1, + NameRole, + }; + }; + + QHash roleNames() const override; + +public: + int findIndexByName(QString const& name) const; + +private: + struct KeyboardModel { + QString vendor; + QString name; + QString description; + + QString display_text() const; + }; + QVector m_list; +}; + +#endif // KCM_KEYBOARD_KEYBOARDMODELMODEL_H diff --git a/kcms/keyboard/kcmui/keyboard_model_model.cpp b/kcms/keyboard/kcmui/keyboard_model_model.cpp new file mode 100644 --- /dev/null +++ b/kcms/keyboard/kcmui/keyboard_model_model.cpp @@ -0,0 +1,65 @@ +#include "keyboard_model_model.h" + +#include +#include +#include + +#include + +KeyboardModelModel::KeyboardModelModel(XkbRules const& rules, QObject* parent) + : QAbstractListModel(parent) +{ + m_list.reserve(rules.modelInfos.count()); + for (auto model_info : rules.modelInfos) { + m_list.push_back({model_info->vendor, model_info->name, model_info->description}); + } + std::sort(m_list.begin(), m_list.end(), [](KeyboardModel const& a, KeyboardModel const& b) { + return a.display_text() < b.display_text(); + }); +} + +int KeyboardModelModel::rowCount(const QModelIndex& /* parent */) const +{ + return m_list.size(); +} + +QVariant KeyboardModelModel::data(const QModelIndex& index, int role) const +{ + auto model = m_list.at(index.row()); + if (role == Roles::DescriptionRole) { + return model.display_text(); + } + if (role == Roles::NameRole) { + return model.name; + } + return QVariant(); +} + +Qt::ItemFlags KeyboardModelModel::flags(const QModelIndex& /* index */) const +{ + return Qt::ItemIsEnabled | Qt::ItemIsSelectable; +} + +QHash KeyboardModelModel::roleNames() const +{ + return { { Roles::DescriptionRole, "description" }, { Roles::NameRole, "name" } }; +} + +int KeyboardModelModel::findIndexByName(const QString &name) const +{ + int index; + for (index = 0; index < m_list.size(); ++index) { + if (m_list[index].name == name) + break; + } + if (index == m_list.size()) { + qWarning() << i18nc("keyboard model", "Keyboard model \"%1\" not detected", name); + return -1; + } + return index; +} + +QString KeyboardModelModel::KeyboardModel::display_text() const +{ + return i18nc("vendor | keyboard model", "%1 | %2", vendor, description); +} diff --git a/kcms/keyboard/kcmui/layout_config_model.h b/kcms/keyboard/kcmui/layout_config_model.h new file mode 100644 --- /dev/null +++ b/kcms/keyboard/kcmui/layout_config_model.h @@ -0,0 +1,95 @@ +#ifndef LAYOUTMODEL_H +#define LAYOUTMODEL_H + +#include +#include + +#include "layout_list_models.h" + +class LayoutConfigModel : public QObject { + Q_OBJECT + Q_PROPERTY(bool showLayoutIndicator READ showLayoutIndicator WRITE setShowLayoutIndicator NOTIFY showLayoutIndicatorChanged) + Q_PROPERTY(bool showForSingleLayout READ showForSingleLayout WRITE setShowForSingleLayout NOTIFY showForSingleLayoutChanged) + Q_PROPERTY(bool layoutIndicatorShowFlag READ layoutIndicatorShowFlag WRITE setLayoutIndicatorShowFlag NOTIFY layoutIndicatorShowFlagChanged) + Q_PROPERTY(bool layoutIndicatorShowLabel READ layoutIndicatorShowLabel WRITE setLayoutIndicatorShowLabel NOTIFY layoutIndicatorShowLabelChanged) + Q_PROPERTY(int switchingPolicyIndex READ switchingPolicyIndex WRITE setSwitchingPolicyIndex NOTIFY switchingPolicyIndexChanged) + Q_PROPERTY(QString alternativeShortcut READ alternativeShortcut WRITE setAlternativeShortcut NOTIFY alternativeShortcutChanged) + Q_PROPERTY(LayoutListFilterDuplicatesProxyModel* layoutListModel READ layoutListModel NOTIFY layoutListModelChanged) + Q_PROPERTY(LayoutListSortByPriorityProxyModel* currentLayoutListModel READ currentLayoutListModel NOTIFY currentLayoutListModelChanged) + Q_PROPERTY(QStringList mainShiftKeyModel READ mainShiftKeyModel) + Q_PROPERTY(int mainShiftKeyIndex READ mainShiftKeyIndex WRITE setMainShiftKeyIndex NOTIFY mainShiftKeyIndexChanged) + Q_PROPERTY(QStringList thirdLevelShortcutModel READ thirdLevelShortcutModel) + Q_PROPERTY(int thirdLevelShortcutIndex READ thirdLevelShortcutIndex WRITE setThirdLevelShortcutIndex NOTIFY thirdLevelShortcutChanged) + +public: + explicit LayoutConfigModel(QObject* parent); + +public: + bool showLayoutIndicator() const; + void setShowLayoutIndicator(bool showLayoutIndicator); + + bool showForSingleLayout() const; + void setShowForSingleLayout(bool showForSingleLayout); + + bool layoutIndicatorShowFlag() const; + void setLayoutIndicatorShowFlag(bool b); + + bool layoutIndicatorShowLabel() const; + void setLayoutIndicatorShowLabel(bool b); + + int switchingPolicyIndex() const; + void setSwitchingPolicyIndex(int switchingPolicyIndex); + + QString alternativeShortcut() const; + void setAlternativeShortcut(QString alternativeShortcut); + + LayoutListFilterDuplicatesProxyModel* layoutListModel() const; + LayoutListSortByPriorityProxyModel* currentLayoutListModel() const; + + void loadEnabledLayouts(); + void saveEnabledLayouts(); + + QStringList mainShiftKeyModel() const; + QStringList thirdLevelShortcutModel() const; + + static const char* switch_modes[4]; + + int mainShiftKeyIndex() const; + QString mainShiftKey() const; + void setMainShiftKeyIndex(int mainShiftKeyIndex); + void setMainShiftKey(QString const& name); + + int thirdLevelShortcutIndex() const; + QString thirdLevelShortcut() const; + void setThirdLevelShortcutIndex(int thirdLevelShortcut); + void setThirdLevelShortcut(QString const& name); + +Q_SIGNALS: + void showLayoutIndicatorChanged(); + void showForSingleLayoutChanged(); + void layoutIndicatorShowFlagChanged(); + void layoutIndicatorShowLabelChanged(); + void switchingPolicyIndexChanged(); + void alternativeShortcutChanged(); + void layoutListModelChanged(); + void currentLayoutListModelChanged(); + void mainShiftKeyIndexChanged(); + void thirdLevelShortcutChanged(); + +private: + bool m_showLayoutIndicator; + bool m_showForSingleLayout; + + bool m_layoutIndicatorShowFlag; + bool m_layoutIndicatorShowLabel; + + int m_switchingPolicyIndex; + int m_mainShiftKeyIndex; + int m_thirdLevelShortcutIndex; + + QString m_alternativeShortcuts; + + LayoutListModels* m_layoutListModels; +}; + +#endif // LAYOUTMODEL_H diff --git a/kcms/keyboard/kcmui/layout_config_model.cpp b/kcms/keyboard/kcmui/layout_config_model.cpp new file mode 100644 --- /dev/null +++ b/kcms/keyboard/kcmui/layout_config_model.cpp @@ -0,0 +1,228 @@ +#include "layout_config_model.h" + +#include +#include +#include + +#include "../xkb_rules.h" + +#include "layout_list_model_selected.h" + +const char* LayoutConfigModel::switch_modes[4] = { + "Global", "Desktop", "Application", "Window" +}; + +LayoutConfigModel::LayoutConfigModel(QObject* parent) + : QObject(parent) + , m_layoutListModels(new LayoutListModels(this)) +{ + m_mainShiftKeyIndex = 0; + m_thirdLevelShortcutIndex = 0; +} + +bool LayoutConfigModel::showLayoutIndicator() const +{ + return m_showLayoutIndicator; +} + +void LayoutConfigModel::setShowLayoutIndicator(bool showLayoutIndicator) +{ + if (showLayoutIndicator != m_showLayoutIndicator) { + m_showLayoutIndicator = showLayoutIndicator; + emit showLayoutIndicatorChanged(); + } +} + +bool LayoutConfigModel::showForSingleLayout() const +{ + return m_showForSingleLayout; +} + +void LayoutConfigModel::setShowForSingleLayout(bool showForSingleLayout) +{ + if (m_showForSingleLayout != showForSingleLayout) { + m_showForSingleLayout = showForSingleLayout; + emit showForSingleLayoutChanged(); + } +} + +bool LayoutConfigModel::layoutIndicatorShowFlag() const +{ + return m_layoutIndicatorShowFlag; +} + +void LayoutConfigModel::setLayoutIndicatorShowFlag(bool b) +{ + if (m_layoutIndicatorShowFlag != b) { + m_layoutIndicatorShowFlag = b; + emit layoutIndicatorShowFlagChanged(); + } +} + +bool LayoutConfigModel::layoutIndicatorShowLabel() const +{ + return m_layoutIndicatorShowLabel; +} + +void LayoutConfigModel::setLayoutIndicatorShowLabel(bool b) +{ + if (m_layoutIndicatorShowLabel != b) { + m_layoutIndicatorShowLabel = b; + emit layoutIndicatorShowLabelChanged(); + } +} + +int LayoutConfigModel::switchingPolicyIndex() const +{ + return m_switchingPolicyIndex; +} + +void LayoutConfigModel::setSwitchingPolicyIndex(int switchingPolicyIndex) +{ + if (m_switchingPolicyIndex != switchingPolicyIndex) { + m_switchingPolicyIndex = switchingPolicyIndex; + emit switchingPolicyIndexChanged(); + } +} + +QString LayoutConfigModel::alternativeShortcut() const +{ + return m_alternativeShortcuts; +} + +void LayoutConfigModel::setAlternativeShortcut(QString alternativeShortcut) +{ + if (m_alternativeShortcuts != alternativeShortcut) { + m_alternativeShortcuts = alternativeShortcut; + emit alternativeShortcutChanged(); + } +} + +LayoutListFilterDuplicatesProxyModel* LayoutConfigModel::layoutListModel() const +{ + return m_layoutListModels->entireLayoutListModel(); +} + +LayoutListSortByPriorityProxyModel* LayoutConfigModel::currentLayoutListModel() const +{ + return m_layoutListModels->configuredLayoutListModel(); +} + +void LayoutConfigModel::loadEnabledLayouts() +{ + m_layoutListModels->loadConfig(); +} + +void LayoutConfigModel::saveEnabledLayouts() +{ + m_layoutListModels->saveConfig(); +} + +QStringList LayoutConfigModel::mainShiftKeyModel() const +{ + QStringList list; + list << i18n("None"); + for (auto const& item : XkbRules::self()->optionGroupInfos) { + if (item->name == "grp") { + for (auto const& option : item->optionInfos) { + list << option->description; + } + break; + } + } + return list; +} + +QStringList LayoutConfigModel::thirdLevelShortcutModel() const +{ + QStringList list; + list << i18n("None"); + for (auto const& item : XkbRules::self()->optionGroupInfos) { + qDebug() << item ->name << item ->description; + if (item->name == "lv3") { + for (auto const& option : item->optionInfos) { + list << option->description; + } + break; + } + } + return list; +} + +int LayoutConfigModel::mainShiftKeyIndex() const +{ + return m_mainShiftKeyIndex; +} + +QString LayoutConfigModel::mainShiftKey() const +{ + if (m_mainShiftKeyIndex > 0) { + for (auto const& item : XkbRules::self()->optionGroupInfos) { + if (item->name == "grp") { + return item->optionInfos[m_mainShiftKeyIndex - 1]->name; + } + } + } + return ""; +} + +void LayoutConfigModel::setMainShiftKeyIndex(int mainShiftKeyIndex) +{ + if (m_mainShiftKeyIndex != mainShiftKeyIndex) { + m_mainShiftKeyIndex = mainShiftKeyIndex; + emit mainShiftKeyIndexChanged(); + } +} + +void LayoutConfigModel::setMainShiftKey(const QString &name) +{ + for (auto const& item : XkbRules::self()->optionGroupInfos) { + if (item->name == "grp") { + for (int i = 0; i < item->optionInfos.size(); ++i) { + if (item->optionInfos[i]->name == name) { + setMainShiftKeyIndex(i); + } + } + break; + } + } +} + +int LayoutConfigModel::thirdLevelShortcutIndex() const +{ + return m_thirdLevelShortcutIndex; +} + +QString LayoutConfigModel::thirdLevelShortcut() const +{ + if (m_thirdLevelShortcutIndex > 0) { + for (auto const& item : XkbRules::self()->optionGroupInfos) { + if (item->name == "lv3") { + return item->optionInfos[m_thirdLevelShortcutIndex - 1]->name; + } + } + } + return ""; +} + +void LayoutConfigModel::setThirdLevelShortcutIndex(int thirdLevelShortcut) +{ + if (m_thirdLevelShortcutIndex != thirdLevelShortcut) { + m_thirdLevelShortcutIndex = thirdLevelShortcut; + emit thirdLevelShortcutChanged(); + } +} + +void LayoutConfigModel::setThirdLevelShortcut(const QString &name) +{ + for (auto const& item : XkbRules::self()->optionGroupInfos) { + if (item->name == "lv3") { + for (int i = 0; i < item->optionInfos.size(); ++i) { + if (item->optionInfos[i]->name == name) { + setThirdLevelShortcutIndex(i); + } + } + break; + } + } +} diff --git a/kcms/keyboard/kcmui/package/contents/ui/Advanced.qml b/kcms/keyboard/kcmui/package/contents/ui/Advanced.qml new file mode 100644 --- /dev/null +++ b/kcms/keyboard/kcmui/package/contents/ui/Advanced.qml @@ -0,0 +1,67 @@ +import QtQuick 2.9 +import QtQuick.Layouts 1.3 +import QtQuick.Controls 2.3 as Controls +import org.kde.kirigami 2.5 as Kirigami +import org.kde.plasma.core 2.1 as PlasmaCore +import org.kde.kcm 1.2 as KCM +import org.kde.kquickcontrols 2.0 as KQuickControls + +KCM.ScrollViewKCM { + id: root + + property var dataModel; + signal changed(); + + property var openedGroups: []; + + view: ListView { + model: PlasmaCore.SortFilterModel { + id: sortFilterModel + sourceModel: dataModel + filterRole: "section_name_plus_is_group" + filterCallback: function(idx, item) { + var sectionName = item.split('+')[0]; + var isGroup = item.split('+')[1] === "true"; + return isGroup || root.openedGroups.indexOf(sectionName) >= 0; + } + } + + delegate: Kirigami.BasicListItem { + id: item + reserveSpaceForIcon: !model.is_group + separatorVisible: true + + Controls.CheckBox { + id: checkbox + + Binding on checked { + when: !model.is_group + value: model.selected + } + + checked: model.is_group && root.openedGroups.indexOf(model.section_name) >= 0 + + onClicked: { + if (model.is_group) { + if (checked) { + root.openedGroups.push(model.section_name); + sortFilterModel.invalidate(); + } + else { + root.openedGroups.splice(openedGroups.indexOf(model.section_name), 1); + sortFilterModel.invalidate(); + } + } + else { + model.selected = checked; + root.changed(); + } + } + } + + Text { + text: model.description + } + } + } +} diff --git a/kcms/keyboard/kcmui/package/contents/ui/FcitxIMConfig.qml b/kcms/keyboard/kcmui/package/contents/ui/FcitxIMConfig.qml new file mode 100644 --- /dev/null +++ b/kcms/keyboard/kcmui/package/contents/ui/FcitxIMConfig.qml @@ -0,0 +1,166 @@ +import QtQuick 2.9 +import QtQuick.Layouts 1.3 +import QtQuick.Controls 2.3 as Controls +import org.kde.kirigami 2.4 as Kirigami + +Controls.Dialog { + header: Kirigami.Heading { text: i18n("IM Config") } + id: root + property var configModel; + + function openForModel(model) { + configModel = model; + open(); + } + + ColumnLayout { + anchors.fill: parent + + ColumnLayout { + id: header + visible: false + Layout.fillHeight: true + + Connections { + target: root + onOpened: { + if (configModel.isRealIM) { + header.visible = true; + + latinCheckbox.checked = configModel.isLatinSwitchingEnabled + latinLayoutList.model = configModel.latinModeLayoutList + latinLayoutList.currentIndex = configModel.selectedLatinLayoutIndex + } + else { + header.visible = false; + } + } + } + + Controls.CheckBox { + id: latinCheckbox + text: i18n("Enable Switching to Latin") + onCheckedChanged: configModel.isLatinSwitchingEnabled = checked; + } + + Controls.ComboBox { + enabled: latinCheckbox.checked + id: latinLayoutList + textRole: "description" + Layout.minimumWidth: 500 + onActivated: configModel.selectedLatinLayoutIndex = currentIndex + } + } + + ListView { + id: configList; + model: configModel + + width: parent.width + Layout.fillHeight: true + + clip: true + + Component { + id: sectionHeading + Rectangle { + width: parent.width + height: childrenRect.height + color: "transparent" + + Text { + text: section + font.bold: true + font.pixelSize: 20 + } + } + } + + section.property: "group" + section.delegate: sectionHeading + + delegate: RowLayout { + id: itemDelegate + property var model_: model; + height: 40 + spacing: 10 + + Controls.Label { + Layout.minimumWidth: 300 + Layout.fillHeight: true + verticalAlignment: Text.AlignVCenter + horizontalAlignment: Text.AlignRight + text: model.description; + } + + Component.onCompleted: { + switch (model.type) { + case "EnumType": + Qt.createQmlObject( + "import QtQuick 2.9; + import QtQuick.Controls 2.3 as Controls; + Controls.ComboBox { + model: model_.data; + currentIndex: model_.data.indexOf(model_.current_value); + onActivated: model_.current_value = currentText; + }", itemDelegate, "dynamicSnippet1"); + break; + case "BooleanType": + Qt.createQmlObject( + "import QtQuick 2.9; + import QtQuick.Controls 2.3 as Controls; + Controls.CheckBox { + checked: model_.current_value + onCheckedChanged: model_.current_value = checked; + }", itemDelegate, "dynamicSnippet2"); + break; + case "HotkeyType": + Qt.createQmlObject( + "import QtQuick 2.9; + import org.kde.kquickcontrols 2.0 as KQuickControls; + KQuickControls.KeySequenceItem { + keySequence: model_.current_value + onKeySequenceChanged: model_.current_value = keySequence; + }", itemDelegate, "dynamicSnippet3"); + break; + case "IntegerType": + Qt.createQmlObject( + "import QtQuick 2.9; + import QtQuick.Controls 2.3 as Controls; + Controls.TextField { + text: model_.current_value; + onTextChanged: model_.current_value = text; + }", itemDelegate, "dynamicSnippet4"); + break; + case "StringType": + case "CharType": + Qt.createQmlObject( + "import QtQuick 2.9; + import QtQuick.Controls 2.3 as Controls; + Controls.TextField { + text: model_.current_value; + onTextChanged: model_.current_value = text; + }", itemDelegate, "dynamicSnippet4"); + break; + } + } + } + } + } + + footer: RowLayout { + Controls.Button { + text: i18n("Save"); + onClicked: { + configList.model.save(); + close(); + } + } + Controls.Button { + text: i18n("Discard"); + onClicked: { + close(); + } + } + } +} diff --git a/kcms/keyboard/kcmui/package/contents/ui/Hardware.qml b/kcms/keyboard/kcmui/package/contents/ui/Hardware.qml new file mode 100644 --- /dev/null +++ b/kcms/keyboard/kcmui/package/contents/ui/Hardware.qml @@ -0,0 +1,152 @@ +import QtQuick 2.6 +import QtQuick.Layouts 1.3 +import QtQuick.Controls 2.3 as Controls +import org.kde.kirigami 2.4 as Kirigami +import org.kde.kcm 1.1 as KCM + +KCM.SimpleKCM { + id: root + + property var dataModel; + signal changed(); + + Kirigami.FormLayout { + id: formLayout + + Controls.ComboBox { + id: keyboardModelComboBox + Kirigami.FormData.label: i18n("Keyboard Model:") + model: dataModel.keyboardModelModel + textRole: "description" + implicitWidth: textarea.width + + Binding on currentIndex { + value: dataModel.currentIndex + } + + MouseArea { + anchors.fill: parent + onWheel: { + // disable wheel events + } + onPressed: { + // propogate to ComboBox + mouse.accepted = false; + } + onReleased: { + // propogate to ComboBox + mouse.accepted = false; + } + } + onActivated: { + dataModel.currentIndex = currentIndex; + root.changed(); + } + } + + Item { + Kirigami.FormData.isSection: true + } + + TriSelector { + Kirigami.FormData.label: i18n("Numlock on Plasma Startup:") + Binding on tristate { + value: dataModel.numlockOnStartup + } + tristate: dataModel.numlockOnStartup + onChanged: { + dataModel.numlockOnStartup = tristate; + root.changed(); + } + } + + TriSelector { + Kirigami.FormData.label: i18n("Keyboard Repeat:") + Binding on tristate { + value: dataModel.keyboardRepeat + } + onChanged: { + dataModel.keyboardRepeat = tristate; + root.changed(); + } + } + + Item { + Kirigami.FormData.isSection: true + } + + RowLayout { + id: delay + Kirigami.FormData.label: i18n("Delay:") + + Controls.Slider { + id: delay_slider + + enabled: dataModel.keyboardRepeat === 0 + + Layout.fillWidth: true; + width: 300 + from: 100 + value: dataModel.repeatDelay + to: 5000 + + onMoved: { + dataModel.repeatDelay = value; + root.changed(); + } + } + + Controls.TextField { + enabled: dataModel.keyboardRepeat === 0 + Layout.fillWidth: false; + Layout.preferredWidth: 150; + id: delay_number_field; + readOnly: true; + text: Math.floor(delay_slider.value) + " ms"; + } + } + + RowLayout { + Kirigami.FormData.label: i18n("Rate:") + + Controls.Slider { + id: rate_slider + + enabled: dataModel.keyboardRepeat === 0 + + Layout.fillWidth: true; + width: 300 + from: 0.2 + value: dataModel.repeatRate + to: 50 + + onMoved: { + dataModel.repeatRate = value; + root.changed(); + } + } + + Controls.TextField { + enabled: dataModel.keyboardRepeat === 0 + Layout.fillWidth: false; + Layout.preferredWidth: 150; + id: rate_number_field; + readOnly: true; + text: parseFloat(rate_slider.value).toFixed(2) + " repeats/s"; + } + } + + Item { + Kirigami.FormData.isSection: true + } + + Controls.TextArea { + Kirigami.FormData.label: i18n("Test area:") + id: textarea + implicitWidth: Math.max(parent.width / 3, delay.width) + implicitHeight: 200 + wrapMode: TextEdit.Wrap + } + + } +} diff --git a/kcms/keyboard/kcmui/package/contents/ui/LayoutPreview.qml b/kcms/keyboard/kcmui/package/contents/ui/LayoutPreview.qml new file mode 100644 --- /dev/null +++ b/kcms/keyboard/kcmui/package/contents/ui/LayoutPreview.qml @@ -0,0 +1,7 @@ +import QtQuick 2.0 + +Rectangle { + color: "white" + width: parent.width + height: parent.height +} diff --git a/kcms/keyboard/kcmui/package/contents/ui/Layouts.qml b/kcms/keyboard/kcmui/package/contents/ui/Layouts.qml new file mode 100644 --- /dev/null +++ b/kcms/keyboard/kcmui/package/contents/ui/Layouts.qml @@ -0,0 +1,400 @@ +import QtQuick 2.9 +import QtQuick.Layouts 1.3 +import QtQuick.Controls 2.3 as Controls +import org.kde.kirigami 2.5 as Kirigami +import org.kde.plasma.core 2.1 as PlasmaCore +import org.kde.kcm 1.2 as KCM +import org.kde.kquickcontrols 2.0 as KQuickControls + +KCM.ScrollViewKCM { + id: root + + property var dataModel; + signal changed(); + + Controls.Dialog { + id: addLayoutDialog + standardButtons: Controls.Dialog.Ok | Controls.Dialog.Discard + title: i18n("Select Layout") + + x: Math.floor((parent.width - width) / 2) + y: Math.floor((parent.height - height) / 2) + width: 500 + height: Math.floor(Math.min(parent.height, 500)); + + property var selected: [] + + ColumnLayout { + anchors.fill: parent + + Component { + id: sectionHeading + Rectangle { + width: parent.width + height: childrenRect.height + color: "transparent" + + Text { + text: section + font.bold: true + font.pixelSize: 20 + } + } + } + + ListView { + id: layoutSelectList + implicitWidth: parent.width + Layout.fillHeight: true + + Controls.ScrollBar.vertical: Controls.ScrollBar {} + + model: PlasmaCore.SortFilterModel { + id: nameFilterModel + sourceModel: PlasmaCore.SortFilterModel { + id: enabledFilterModel + sourceModel: dataModel.layoutListModel + + filterRole: "enabled" + filterCallback: function(source_row, value) { return !value; } + + sortRole: "languages" + } + + filterRole: "description" + filterCaseSensitivity: Qt.CaseInsensitive + filterString: filterText.text + } + + clip: true + + section.property: "languages" + section.delegate: sectionHeading + + delegate: Kirigami.BasicListItem { + label: model.description + checkable: true + icon: "input-keyboard" + + function origIdx() { + return enabledFilterModel.mapRowToSource( + nameFilterModel.mapRowToSource(model.index)); + } + + checked: addLayoutDialog.selected[origIdx()] === true + onCheckedChanged: addLayoutDialog.selected[origIdx()] = checked; + } + } + + Controls.TextArea { + id: filterText + implicitWidth: parent.width + } + } + + onOpened: filterText.forceActiveFocus() + onOpenedChanged: filterText.text = "" + + onAccepted: { + selected.forEach(function(checked, index) { + if (checked) { + dataModel.layoutListModel.add(index); + changed(); + } + }); + close(); + } + onDiscarded: close(); + onClosed: { + selected = [] + layoutSelectList.positionViewAtBeginning(); + } + } + + Controls.Dialog { + id: previewDialog + title: "Preview" + standardButtons: Controls.Dialog.Ok + + x: Math.floor((parent.width - width) / 2) + y: Math.floor((parent.height - height) / 2) + width: 500 + height: Math.floor(Math.min(parent.height, 500)); + + LayoutPreview { + id: preview + } + } + + header: Kirigami.FormLayout { + id: formLayout + + Item { + Kirigami.FormData.isSection: true + Kirigami.FormData.label: i18n("Layout Indicator Icon") + } + + Controls.CheckBox { + id: showLayoutIndicatorIconCheckbox + Kirigami.FormData.label: i18n("Show layout indicator icon") + + Binding on checked { + value: dataModel.showLayoutIndicator + } + + onCheckedChanged: { + dataModel.showLayoutIndicator = checked; + root.changed(); + } + } + + Controls.CheckBox { + Kirigami.FormData.label: i18n("Show for single layout") + + enabled: showLayoutIndicatorIconCheckbox.checked + + Binding on checked { + value: dataModel.showForSingleLayout + } + + onCheckedChanged: { + dataModel.showForSingleLayout = checked; + root.changed(); + } + } + + Item { + Kirigami.FormData.isSection: true + Kirigami.FormData.label: i18n("Shortcuts for Switching Layout") + } + + Controls.ComboBox { + Kirigami.FormData.label: i18n("Main shift key:") + model: dataModel.mainShiftKeyModel + + Binding on currentIndex { + value: dataModel.mainShiftKeyIndex + } + + onActivated: { + dataModel.mainShiftKeyIndex = currentIndex; + root.changed(); + } + } + + Controls.ComboBox { + Kirigami.FormData.label: i18n("3rd level shift key:") + model: dataModel.thirdLevelShortcutModel + + Binding on currentIndex { + value: dataModel.thirdLevelShortcutIndex + } + + onActivated: { + dataModel.thirdLevelShortcutIndex = currentIndex; + root.changed(); + } + } + + KQuickControls.KeySequenceItem { + Kirigami.FormData.label: i18n("Cycle through layouts:") + width: 200 + + Binding on keySequence { + value: dataModel.alternativeShortcut + } + + onKeySequenceChanged: { + dataModel.alternativeShortcut = keySequence; + root.changed(); + } + } + + Item { + Kirigami.FormData.isSection: true + Kirigami.FormData.label: i18n("Layouts") + } + + Kirigami.InlineMessage { + Kirigami.FormData.isSection: true + id: inlineMessage + + PlasmaCore.SortFilterModel { + id: missingLayouts + sourceModel: dataModel.layoutListModel + + filterRole: "source" + filterCallback: function(source_row, value) { return value == 0; } + + function join(str) { + var l = [] + for (var i = 0; i < missingLayouts.count; ++i) { + l.push(missingLayouts.get(i).save_name); + } + return l.join(str); + } + } + + Layout.fillWidth: true + + type: Kirigami.MessageType.Error + + Connections { + target: dataModel.layoutListModel + onMissingCountChanged: { + inlineMessage.text = + i18ncp("@info %2 is the layout code", + "The input support for the keyboard layout with the code '%2' could not be found. If it is not needed, please remove it from your configuration.", + "The input support for the keyboard layouts with the codes '%2' could not be found. If they are not needed, please remove them from your configuration.", + missingLayouts.count, + missingLayouts.join("', '")) + inlineMessage.visible = missingLayouts.count > 0 + } + } + } + } + + Component { + id: listviewDelegateComponent + Kirigami.SwipeListItem { + checkable: true + id: listItem + + contentItem: RowLayout { + Kirigami.ListItemDragHandle { + listItem: listItem + listView: layoutList + onMoveRequested: { + dataModel.currentLayoutListModel.simulateMove(oldIndex, newIndex); + } + onDropped: { + dataModel.currentLayoutListModel.applyOrderChanges(); + changed(); + } + } + + Kirigami.Icon { + visible: model.source == 0 + + Layout.alignment: Qt.AlignVCenter + + width: Kirigami.Units.iconSizes.smallMedium + height: width + + source: "error" + color: Kirigami.Theme.negativeTextColor + } + + Controls.Label { + Layout.fillWidth: true + text: model.description + } + } + + onClicked: { + if (checked) { + if (layoutList.checkedItem.length === 1) { + layoutList.checkedItem[0].item.checked = false; + } + layoutList.checkedItem[0] = {index: model.index, model: model, item: this}; + configureLayoutButton.enabled = model.is_configurable; + } + else { + layoutList.checkedItem = [] + configureLayoutButton.enabled = false; + } + } + + + actions: [ + Kirigami.Action { + iconName: "list-remove" + tooltip: i18nc("@info:tooltip", "Remove") + onTriggered: { + dataModel.currentLayoutListModel.remove(index) + changed(); + } + }] + } + } + + + view: ListView { + id: layoutList + + property var checkedItem; + + Component.onCompleted: checkedItem = []; + + Rectangle { + color: "white" + anchors.fill: parent + z: -10 + } + + implicitWidth: formLayout.width - buttonColumn.width - parent.spacing + implicitHeight: 300 + + model: dataModel.currentLayoutListModel + + clip: true + + Controls.ScrollBar.vertical: Controls.ScrollBar { + active: true + } + + delegate: Kirigami.DelegateRecycler { + width: layoutList.width + sourceComponent: listviewDelegateComponent + } + } + + footer: Row { + id: buttonColumn + + Controls.Button { + text: i18n("Add...") + icon.name: "list-add" + + onClicked: addLayoutDialog.open(); + } + + /* TODO + Controls.Button { + text: i18n("Preview...") + onClicked: previewDialog.open(); + } + */ + + Controls.Button { + id: configureLayoutButton + text: i18n("Configure..."); + enabled: false; + icon.name: "configure" + + onClicked: { + var item = layoutList.checkedItem[0].model; + var component; + var imConfigDialog; + if (item.source === 1) { // xkb + component = Qt.createComponent("XkbLayoutConfig.qml"); + } + else if (item.source === 2) { // fcitx + component = Qt.createComponent("FcitxIMConfig.qml"); + } + else { + return; + } + + if (component.status === Component.Ready) { + imConfigDialog = component.createObject(root.parent, {width:700, height:500}) + imConfigDialog.openForModel(item.config_model); + } + else { + console.log(component.errorString()) + } + + } + } + } +} diff --git a/kcms/keyboard/kcmui/package/contents/ui/TriSelector.qml b/kcms/keyboard/kcmui/package/contents/ui/TriSelector.qml new file mode 100644 --- /dev/null +++ b/kcms/keyboard/kcmui/package/contents/ui/TriSelector.qml @@ -0,0 +1,37 @@ +import QtQuick 2.6 +import QtQuick.Controls 2.3 as Controls +import org.kde.kirigami 2.3 as Kirigami + +Column { + + property int tristate; + signal changed(); + + Controls.RadioButton { + id: turn_on; + text: i18n("Turn on"); + checked: tristate == 0; + onClicked: { + tristate = 0; + changed(); + } + } + Controls.RadioButton { + id: turn_off; + text: i18n("Turn off"); + checked: tristate == 1; + onClicked: { + tristate = 1; + changed(); + } + } + Controls.RadioButton { + id: leave_unchanged; + text: i18n("Leave unchanged"); + checked: tristate == 2; + onClicked: { + tristate = 2; + changed(); + } + } +} diff --git a/kcms/keyboard/kcmui/package/contents/ui/XkbLayoutConfig.qml b/kcms/keyboard/kcmui/package/contents/ui/XkbLayoutConfig.qml new file mode 100644 --- /dev/null +++ b/kcms/keyboard/kcmui/package/contents/ui/XkbLayoutConfig.qml @@ -0,0 +1,46 @@ +import QtQuick 2.9 +import QtQuick.Layouts 1.3 +import QtQuick.Controls 2.3 as Controls +import org.kde.kirigami 2.4 as Kirigami + +Controls.Dialog { + header: Kirigami.Heading { text: i18n("IM Config") } + id: root + property var configModel; + + function openForModel(model) { + configModel = model; + open(); + } + + ListView { + id: configList; + model: configModel + + anchors.fill: parent + + clip: true + + delegate: RowLayout { + Controls.Label { + text: model.description + } + } + } + + footer: RowLayout { + Controls.Button { + text: i18n("Save"); + onClicked: { + configList.model.save(); + close(); + } + } + Controls.Button { + text: i18n("Discard"); + onClicked: { + close(); + } + } + } +} diff --git a/kcms/keyboard/kcmui/package/contents/ui/main.qml b/kcms/keyboard/kcmui/package/contents/ui/main.qml new file mode 100644 --- /dev/null +++ b/kcms/keyboard/kcmui/package/contents/ui/main.qml @@ -0,0 +1,52 @@ +import QtQuick 2.6 +import QtQuick.Layouts 1.3 +import QtQuick.Controls 2.3 as Controls +import org.kde.kirigami 2.4 as Kirigami +import org.kde.kcm 1.2 + +Item { + id: rootItem; + + signal changed(); + + Controls.TabBar { + id: tabbar + anchors.top: parent.top + anchors.left: parent.left + anchors.right: parent.right + width: parent.width + Controls.TabButton { + text: i18n("Hardware") + } + Controls.TabButton { + text: i18n("Layouts") + } + Controls.TabButton { + text: i18n("Advanced") + } + } + + StackLayout { + anchors.top: tabbar.bottom + anchors.left: parent.left + anchors.right: parent.right + anchors.bottom: parent.bottom + + currentIndex: tabbar.currentIndex + + Hardware { + dataModel: kcm.hardwareModel + onChanged: rootItem.changed(); + } + + Layouts { + dataModel: kcm.layoutModel + onChanged: rootItem.changed(); + } + + Advanced { + dataModel: kcm.advancedModel + onChanged: rootItem.changed(); + } + } +} diff --git a/kcms/keyboard/kcmui/package/metadata.desktop b/kcms/keyboard/kcmui/package/metadata.desktop new file mode 100644 --- /dev/null +++ b/kcms/keyboard/kcmui/package/metadata.desktop @@ -0,0 +1,17 @@ +[Desktop Entry] +Name=Keyboard and IME + +Icon=preferences-desktop-keyboard +Keywords= +Type=Service +X-KDE-ParentApp= +X-KDE-PluginInfo-Author=Park Gun +X-KDE-PluginInfo-Email=mujjingun@gmail.com +X-KDE-PluginInfo-License=GPL +X-KDE-PluginInfo-Name=kcm_keyboard +X-KDE-PluginInfo-Version= +X-KDE-PluginInfo-Website= +X-KDE-ServiceTypes=Plasma/Generic +X-Plasma-API=declarativeappletscript + +X-Plasma-MainScript=ui/main.qml diff --git a/kcms/keyboard/keyboard_config.h b/kcms/keyboard/keyboard_config.h deleted file mode 100644 --- a/kcms/keyboard/keyboard_config.h +++ /dev/null @@ -1,91 +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. - */ - - -#ifndef KEYBOARD_CONFIG_H_ -#define KEYBOARD_CONFIG_H_ - -#include "x11_helper.h" - -#include -#include -#include -#include -#include - -/** - * This class provides configuration options for keyboard module - */ -class KeyboardConfig -{ -public: - static const int MAX_LABEL_LEN = 3; - static const int NO_LOOPING; // = -1; - - enum SwitchingPolicy { - SWITCH_POLICY_GLOBAL = 0, - SWITCH_POLICY_DESKTOP = 1, - SWITCH_POLICY_APPLICATION = 2, - SWITCH_POLICY_WINDOW = 3 - }; - - enum IndicatorType { - SHOW_LABEL = 0, - SHOW_FLAG = 1, - SHOW_LABEL_ON_FLAG = 2 - }; - - QString keyboardModel; - // resetOldXkbOptions is now also "set xkb options" - bool resetOldXkbOptions; - QStringList xkbOptions; - - // init layouts options - bool configureLayouts; - QList layouts; - int layoutLoopCount; - - // switch cotrol options - SwitchingPolicy switchingPolicy; -// bool stickySwitching; -// int stickySwitchingDepth; - - // display options - bool showIndicator; - IndicatorType indicatorType; - bool showSingle; - - KeyboardConfig(); - - QList getDefaultLayouts() const; - QList getExtraLayouts() const; - bool isFlagShown() const { - return indicatorType == SHOW_FLAG || indicatorType == SHOW_LABEL_ON_FLAG; - } - bool isLabelShown() const { - return indicatorType == SHOW_LABEL || indicatorType == SHOW_LABEL_ON_FLAG; - } - - void setDefaults(); - void load(); - void save(); - - static QString getSwitchingPolicyString(SwitchingPolicy switchingPolicy); -}; - -#endif /* KEYBOARD_CONFIG_H_ */ diff --git a/kcms/keyboard/keyboard_config.cpp b/kcms/keyboard/keyboard_config.cpp deleted file mode 100644 --- a/kcms/keyboard/keyboard_config.cpp +++ /dev/null @@ -1,208 +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. - */ - -#include "keyboard_config.h" -#include "debug.h" - -#include -#include - - -static const char* const SWITCHING_POLICIES[] = {"Global", "Desktop", "WinClass", "Window", NULL }; -static const char LIST_SEPARATOR[] = ","; -//static const char* DEFAULT_LAYOUT = "us"; -static const char DEFAULT_MODEL[] = "pc104"; - -static const QString CONFIG_FILENAME(QStringLiteral("kxkbrc")); -static const QString CONFIG_GROUPNAME(QStringLiteral("Layout")); - -const int KeyboardConfig::NO_LOOPING = -1; - -KeyboardConfig::KeyboardConfig() -{ - setDefaults(); -} - -QString KeyboardConfig::getSwitchingPolicyString(SwitchingPolicy switchingPolicy) { - return SWITCHING_POLICIES[switchingPolicy]; -} - -static int findStringIndex(const char* const strings[], const QString& toFind, int defaultIndex) -{ - for(int i=0; strings[i] != NULL; i++) { - if( toFind == strings[i] ) { - return i; - } - } - return defaultIndex; -} - -void KeyboardConfig::setDefaults() -{ - keyboardModel = DEFAULT_MODEL; - resetOldXkbOptions = false; - xkbOptions.clear(); - - // init layouts options - configureLayouts = false; - layouts.clear(); -// layouts.append(LayoutUnit(DEFAULT_LAYOUT)); - layoutLoopCount = NO_LOOPING; - - // switch cotrol options - switchingPolicy = SWITCH_POLICY_GLOBAL; -// stickySwitching = false; -// stickySwitchingDepth = 2; - - // display options - showIndicator = true; - indicatorType = SHOW_LABEL; - showSingle = false; -} - -static -KeyboardConfig::IndicatorType getIndicatorType(bool showFlag, bool showLabel) -{ - if( showFlag ) { - if( showLabel ) - return KeyboardConfig::SHOW_LABEL_ON_FLAG; - else - return KeyboardConfig::SHOW_FLAG; - } - else { - return KeyboardConfig::SHOW_LABEL; - } -} - - -void KeyboardConfig::load() -{ - KConfigGroup config(KSharedConfig::openConfig( CONFIG_FILENAME, KConfig::NoGlobals ), CONFIG_GROUPNAME); - - keyboardModel = config.readEntry("Model", ""); - - resetOldXkbOptions = config.readEntry("ResetOldOptions", false); - QString options = config.readEntry("Options", ""); - xkbOptions = options.split(LIST_SEPARATOR, QString::SkipEmptyParts); - - configureLayouts = config.readEntry("Use", false); - QString layoutsString = config.readEntry("LayoutList", ""); - QStringList layoutStrings = layoutsString.split(LIST_SEPARATOR, QString::SkipEmptyParts); -// if( layoutStrings.isEmpty() ) { -// layoutStrings.append(DEFAULT_LAYOUT); -// } - layouts.clear(); - foreach(const QString& layoutString, layoutStrings) { - layouts.append(LayoutUnit(layoutString)); - } - if( layouts.isEmpty() ) { - configureLayouts = false; - } - - layoutLoopCount = config.readEntry("LayoutLoopCount", NO_LOOPING); - - QString layoutMode = config.readEntry("SwitchMode", "Global"); - switchingPolicy = static_cast(findStringIndex(SWITCHING_POLICIES, layoutMode, SWITCH_POLICY_GLOBAL)); - - showIndicator = config.readEntry("ShowLayoutIndicator", true); - - bool showFlag = config.readEntry("ShowFlag", false); - bool showLabel = config.readEntry("ShowLabel", true); - indicatorType = getIndicatorType(showFlag, showLabel); - - showSingle = config.readEntry("ShowSingle", false); - - QString labelsStr = config.readEntry("DisplayNames", ""); - QStringList labels = labelsStr.split(LIST_SEPARATOR, QString::KeepEmptyParts); - for(int i=0; i KeyboardConfig::getDefaultLayouts() const -{ - QList defaultLayoutList; - int i = 0; - foreach(const LayoutUnit& layoutUnit, layouts) { - defaultLayoutList.append(layoutUnit); - if( layoutLoopCount != KeyboardConfig::NO_LOOPING && i >= layoutLoopCount-1 ) - break; - i++; - } - return defaultLayoutList; -} - -QList KeyboardConfig::getExtraLayouts() const -{ - if( layoutLoopCount == KeyboardConfig::NO_LOOPING ) - return QList(); - - return layouts.mid(layoutLoopCount, layouts.size()); -} diff --git a/kcms/keyboard/keyboard_daemon.cpp b/kcms/keyboard/keyboard_daemon.cpp deleted file mode 100644 --- a/kcms/keyboard/keyboard_daemon.cpp +++ /dev/null @@ -1,249 +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. - */ - -#include "keyboard_daemon.h" -#include "debug.h" - -#include -#include -#include -#include -#include -#include - -#include - -#include "x11_helper.h" -#include "xinput_helper.h" -#include "xkb_helper.h" -#include "keyboard_dbus.h" -#include "xkb_rules.h" -#include "bindings.h" -#include "keyboard_hardware.h" -#include "layout_tray_icon.h" -#include "layout_memory_persister.h" -#include "layouts_menu.h" - -K_PLUGIN_FACTORY_WITH_JSON(KeyboardFactory, - "keyboard.json", - registerPlugin();) - -KeyboardDaemon::KeyboardDaemon(QObject *parent, const QList&) - : KDEDModule(parent), - actionCollection(NULL), - xEventNotifier(NULL), - layoutTrayIcon(NULL), - layoutMemory(keyboardConfig), - rules(Rules::readRules(Rules::READ_EXTRAS)) -{ - if( ! X11Helper::xkbSupported(NULL) ) - return; //TODO: shut down the daemon? - - QDBusConnection dbus = QDBusConnection::sessionBus(); - dbus.registerService(KEYBOARD_DBUS_SERVICE_NAME); - dbus.registerObject(KEYBOARD_DBUS_OBJECT_PATH, this, QDBusConnection::ExportScriptableSlots | QDBusConnection::ExportScriptableSignals); - dbus.connect(QString(), KEYBOARD_DBUS_OBJECT_PATH, KEYBOARD_DBUS_SERVICE_NAME, KEYBOARD_DBUS_CONFIG_RELOAD_MESSAGE, this, SLOT(configureKeyboard())); - - configureKeyboard(); - registerListeners(); - - LayoutMemoryPersister layoutMemoryPersister(layoutMemory); - if( layoutMemoryPersister.restore() ) { - if( layoutMemoryPersister.getGlobalLayout().isValid() ) { - X11Helper::setLayout(layoutMemoryPersister.getGlobalLayout()); - } - } -} - -KeyboardDaemon::~KeyboardDaemon() -{ - LayoutMemoryPersister layoutMemoryPersister(layoutMemory); - layoutMemoryPersister.setGlobalLayout(currentLayout); - layoutMemoryPersister.save(); - - QDBusConnection dbus = QDBusConnection::sessionBus(); - dbus.disconnect(QString(), KEYBOARD_DBUS_OBJECT_PATH, KEYBOARD_DBUS_SERVICE_NAME, KEYBOARD_DBUS_CONFIG_RELOAD_MESSAGE, this, SLOT(configureKeyboard())); - dbus.unregisterObject(KEYBOARD_DBUS_OBJECT_PATH); - dbus.unregisterService(KEYBOARD_DBUS_SERVICE_NAME); - - unregisterListeners(); - unregisterShortcut(); - - delete xEventNotifier; - delete layoutTrayIcon; - delete rules; -} - -void KeyboardDaemon::configureKeyboard() -{ - qCDebug(KCM_KEYBOARD) << "Configuring keyboard"; - init_keyboard_hardware(); - - keyboardConfig.load(); - XkbHelper::initializeKeyboardLayouts(keyboardConfig); - layoutMemory.configChanged(); - - setupTrayIcon(); - - unregisterShortcut(); - registerShortcut(); -} - -void KeyboardDaemon::configureMouse() -{ - QStringList modules; - modules << QStringLiteral("mouse"); - QProcess::startDetached(QStringLiteral("kcminit"), modules); -} - -void KeyboardDaemon::setupTrayIcon() -{ - bool show = keyboardConfig.showIndicator - && ( keyboardConfig.showSingle || X11Helper::getLayoutsList().size() > 1 ); - - if( show && ! layoutTrayIcon ) { - layoutTrayIcon = new LayoutTrayIcon(rules, keyboardConfig); - } - else if( ! show && layoutTrayIcon ) { - delete layoutTrayIcon; - layoutTrayIcon = NULL; - } -} - -void KeyboardDaemon::registerShortcut() -{ - if( actionCollection == NULL ) { - actionCollection = new KeyboardLayoutActionCollection(this, false); - - QAction* toggleLayoutAction = actionCollection->getToggleAction(); - connect(toggleLayoutAction, &QAction::triggered, this, &KeyboardDaemon::switchToNextLayout); - actionCollection->loadLayoutShortcuts(keyboardConfig.layouts, rules); - connect(actionCollection, SIGNAL(actionTriggered(QAction*)), this, SLOT(setLayout(QAction*))); - } -} - -void KeyboardDaemon::unregisterShortcut() -{ - // register KDE keyboard shortcut for switching layouts - if( actionCollection != NULL ) { - disconnect(actionCollection, SIGNAL(actionTriggered(QAction*)), this, SLOT(setLayout(QAction*))); - disconnect(actionCollection->getToggleAction(), &QAction::triggered, this, &KeyboardDaemon::switchToNextLayout); - - delete actionCollection; - actionCollection = NULL; - } -} - -void KeyboardDaemon::registerListeners() -{ - if( xEventNotifier == NULL ) { - xEventNotifier = new XInputEventNotifier(); - } - connect(xEventNotifier, &XInputEventNotifier::newPointerDevice, this, &KeyboardDaemon::configureMouse); - connect(xEventNotifier, &XInputEventNotifier::newKeyboardDevice, this, &KeyboardDaemon::configureKeyboard); - connect(xEventNotifier, &XEventNotifier::layoutMapChanged, this, &KeyboardDaemon::layoutMapChanged); - connect(xEventNotifier, &XEventNotifier::layoutChanged, this, &KeyboardDaemon::layoutChanged); - xEventNotifier->start(); -} - -void KeyboardDaemon::unregisterListeners() -{ - if( xEventNotifier != NULL ) { - xEventNotifier->stop(); - disconnect(xEventNotifier, &XInputEventNotifier::newPointerDevice, this, &KeyboardDaemon::configureMouse); - disconnect(xEventNotifier, &XInputEventNotifier::newKeyboardDevice, this, &KeyboardDaemon::configureKeyboard); - disconnect(xEventNotifier, &XEventNotifier::layoutChanged, this, &KeyboardDaemon::layoutChanged); - disconnect(xEventNotifier, &XEventNotifier::layoutMapChanged, this, &KeyboardDaemon::layoutMapChanged); - } -} - -void KeyboardDaemon::layoutChanged() -{ - //TODO: pass newLayout into layoutTrayIcon? - LayoutUnit newLayout = X11Helper::getCurrentLayout(); - - layoutMemory.layoutChanged(); - if( layoutTrayIcon != NULL ) { - layoutTrayIcon->layoutChanged(); - } - - if( newLayout != currentLayout ) { - currentLayout = newLayout; - emit currentLayoutChanged(newLayout.toString()); - } -} - -void KeyboardDaemon::layoutMapChanged() -{ - keyboardConfig.load(); - layoutMemory.layoutMapChanged(); - emit layoutListChanged(); - if( layoutTrayIcon != NULL ) { - layoutTrayIcon->layoutMapChanged(); - } -} - -void KeyboardDaemon::switchToNextLayout() -{ - qCDebug(KCM_KEYBOARD) << "Toggling layout"; - X11Helper::switchToNextLayout(); - - LayoutUnit newLayout = X11Helper::getCurrentLayout(); - - QDBusMessage msg = QDBusMessage::createMethodCall( - QStringLiteral("org.kde.plasmashell"), - QStringLiteral("/org/kde/osdService"), - QStringLiteral("org.kde.osdService"), - QStringLiteral("kbdLayoutChanged")); - - msg << Flags::getShortText(newLayout, keyboardConfig); - - QDBusConnection::sessionBus().asyncCall(msg); -} - -bool KeyboardDaemon::setLayout(QAction* action) -{ - if( action == actionCollection->getToggleAction() ) - return false; - - LayoutUnit layoutUnit(action->data().toString()); - return LayoutsMenu::switchToLayout(layoutUnit, keyboardConfig); // need this to be able to switch to spare layouts -// return X11Helper::setLayout(LayoutUnit(action->data().toString())); -} - -bool KeyboardDaemon::setLayout(const QString& layout) -{ - return X11Helper::setLayout(LayoutUnit(layout)); -} - -QString KeyboardDaemon::getCurrentLayout() -{ - return X11Helper::getCurrentLayout().toString(); -} - -QStringList KeyboardDaemon::getLayoutsList() -{ - return X11Helper::getLayoutsListAsString( X11Helper::getLayoutsList() ); -} - -QString KeyboardDaemon::getLayoutDisplayName(const QString &layout) -{ - return Flags::getShortText(LayoutUnit(layout), keyboardConfig); -} - -#include "keyboard_daemon.moc" diff --git a/kcms/keyboard/keyboard_hardware.cpp b/kcms/keyboard/keyboard_hardware.cpp deleted file mode 100644 --- a/kcms/keyboard/keyboard_hardware.cpp +++ /dev/null @@ -1,103 +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. - */ - -#include -#include -#include - -#include -#include - -#include - -#include "x11_helper.h" -#include "kcmmisc.h" -#include "debug.h" - -#include -#include -#include - -// This code is taken from xset utility from XFree 4.3 (http://www.xfree86.org/) - -static -void set_repeatrate(int delay, double rate) -{ - if( !X11Helper::xkbSupported(NULL) ) { - qCCritical(KCM_KEYBOARD) << "Failed to set keyboard repeat rate: xkb is not supported"; - return; - } - - XkbDescPtr xkb = XkbAllocKeyboard(); - if (xkb) { - Display* dpy = QX11Info::display(); - //int res = - XkbGetControls(dpy, XkbRepeatKeysMask, xkb); - xkb->ctrls->repeat_delay = delay; - xkb->ctrls->repeat_interval = (int)floor(1000/rate + 0.5); - //res = - XkbSetControls(dpy, XkbRepeatKeysMask, xkb); - XkbFreeKeyboard(xkb, 0, true); - return; - } -} - -static -int set_repeat_mode(TriState keyboardRepeatMode) -{ - XKeyboardState kbd; - XKeyboardControl kbdc; - - XGetKeyboardControl(QX11Info::display(), &kbd); - - int flags = 0; - if( keyboardRepeatMode != STATE_UNCHANGED ) { - flags |= KBAutoRepeatMode; - kbdc.auto_repeat_mode = (keyboardRepeatMode==STATE_ON ? AutoRepeatModeOn : AutoRepeatModeOff); - } - - return XChangeKeyboardControl(QX11Info::display(), flags, &kbdc); -} - -void init_keyboard_hardware() -{ - KConfigGroup config(KSharedConfig::openConfig( QStringLiteral("kcminputrc") ), "Keyboard"); - - QString keyRepeatStr = config.readEntry("KeyboardRepeating", TriStateHelper::getString(STATE_ON)); - TriState keyRepeat = STATE_UNCHANGED; - if( keyRepeatStr == QLatin1String("true") || keyRepeatStr == TriStateHelper::getString(STATE_ON) ) { - keyRepeat = STATE_ON; - } - else if( keyRepeatStr == QLatin1String("false") || keyRepeatStr == TriStateHelper::getString(STATE_OFF) ) { - keyRepeat = STATE_OFF; - } - - if( keyRepeat == STATE_ON ) { - int delay_ = config.readEntry("RepeatDelay", DEFAULT_REPEAT_DELAY); - double rate_ = config.readEntry("RepeatRate", DEFAULT_REPEAT_RATE); - set_repeatrate(delay_, rate_); - } - - set_repeat_mode(keyRepeat); - - TriState numlockState = TriStateHelper::getTriState( config.readEntry( "NumLock", TriStateHelper::getInt(STATE_UNCHANGED) ) ); - if( numlockState != STATE_UNCHANGED ) { - KModifierKeyInfo keyInfo; - keyInfo.setKeyLocked(Qt::Key_NumLock, numlockState == STATE_ON); - } -} diff --git a/kcms/keyboard/layout_memory.h b/kcms/keyboard/layout_memory.h deleted file mode 100644 --- a/kcms/keyboard/layout_memory.h +++ /dev/null @@ -1,66 +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. - */ - - -#ifndef LAYOUT_MEMORY_H_ -#define LAYOUT_MEMORY_H_ - -#include -#include -#include //For WId - -#include "x11_helper.h" -#include "keyboard_config.h" - -class LayoutMemoryPersister; - -class LayoutMemory : public QObject -{ - Q_OBJECT - - // if there's some transient windows coming up we'll need to either ignore it - // or in case of layout switcher popup menu to apply new layout to previous key - QString previousLayoutMapKey; - QList prevLayoutList; - const KeyboardConfig& keyboardConfig; - - void registerListeners(); - void unregisterListeners(); - QString getCurrentMapKey(); - void setCurrentLayoutFromMap(); - -public Q_SLOTS: - void layoutMapChanged(); - void layoutChanged(); - void windowChanged(WId wId); - void desktopChanged(int desktop); - -public: - LayoutMemory(const KeyboardConfig& keyboardConfig); - ~LayoutMemory() override; - - void configChanged(); - -protected: - //QVariant does not support long for WId so we'll use QString for key instead - QMap layoutMap; - - friend class LayoutMemoryPersister; -}; - -#endif /* LAYOUT_MEMORY_H_ */ diff --git a/kcms/keyboard/layout_memory_persister.h b/kcms/keyboard/layout_memory_persister.h deleted file mode 100644 --- a/kcms/keyboard/layout_memory_persister.h +++ /dev/null @@ -1,52 +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. - */ - -#ifndef LAYOUT_MEMORY_PERSISTER_H_ -#define LAYOUT_MEMORY_PERSISTER_H_ - -#include - -#include "x11_helper.h" - -class LayoutMemory; -class QFile; - -class LayoutMemoryPersister { -public: - LayoutMemoryPersister(LayoutMemory& layoutMemory_): - layoutMemory(layoutMemory_) {} - - bool saveToFile(const QFile& file); - bool restoreFromFile(const QFile& file); - - bool save(); - bool restore(); - - LayoutUnit getGlobalLayout() const { return globalLayout; } - void setGlobalLayout(const LayoutUnit& layout) { globalLayout = layout; } - -private: - LayoutMemory& layoutMemory; - LayoutUnit globalLayout; - - QString getLayoutMapAsString(); - - bool canPersist(); -}; - -#endif /* LAYOUT_MEMORY_PERSISTER_H_ */ diff --git a/kcms/keyboard/layout_memory_persister.cpp b/kcms/keyboard/layout_memory_persister.cpp deleted file mode 100644 --- a/kcms/keyboard/layout_memory_persister.cpp +++ /dev/null @@ -1,269 +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 "layout_memory_persister.h" -#include "debug.h" - -#include -#include - -#include -#include -#include -#include -#include - -#include "keyboard_config.h" -#include "layout_memory.h" - - -static const char VERSION[] = "1.0"; -static const char DOC_NAME[] = "LayoutMap"; -static const char ROOT_NODE[] = "LayoutMap"; -static const char VERSION_ATTRIBUTE[] = "version"; -static const char SWITCH_MODE_ATTRIBUTE[] = "SwitchMode"; -static const char ITEM_NODE[] = "item"; -static const QString CURRENT_LAYOUT_ATTRIBUTE(QStringLiteral("currentLayout")); -static const char OWNER_KEY_ATTRIBUTE[] = "ownerKey"; -static const char LAYOUTS_ATTRIBUTE[] = "layouts"; - -static const char LIST_SEPARATOR_LM[] = ","; - -static const char REL_SESSION_FILE_PATH[] = "/keyboard/session/layout_memory.xml"; - -static bool isDefaultLayoutConfig(const LayoutSet &layout, const QList &defaultLayouts) -{ - if (defaultLayouts.isEmpty() || layout.layouts != defaultLayouts || layout.currentLayout != defaultLayouts.first()) { - return false; - } - return true; -} - -QString LayoutMemoryPersister::getLayoutMapAsString() -{ - if( ! canPersist() ) - return QLatin1String(""); - - QDomDocument doc(DOC_NAME); - QDomElement root = doc.createElement(ROOT_NODE); - root.setAttribute(VERSION_ATTRIBUTE, VERSION); - root.setAttribute(SWITCH_MODE_ATTRIBUTE, KeyboardConfig::getSwitchingPolicyString(layoutMemory.keyboardConfig.switchingPolicy)); - doc.appendChild(root); - - if( layoutMemory.keyboardConfig.switchingPolicy == KeyboardConfig::SWITCH_POLICY_GLOBAL ) { - if( ! globalLayout.isValid() ) - return QLatin1String(""); - - QDomElement item = doc.createElement(ITEM_NODE); - item.setAttribute(CURRENT_LAYOUT_ATTRIBUTE, globalLayout.toString()); - root.appendChild(item); - } - else { - foreach(const QString& key , layoutMemory.layoutMap.keys()) { - if (isDefaultLayoutConfig(layoutMemory.layoutMap[key], layoutMemory.keyboardConfig.getDefaultLayouts())) { - continue; - } - - QDomElement item = doc.createElement(ITEM_NODE); - item.setAttribute(OWNER_KEY_ATTRIBUTE, key); - item.setAttribute(CURRENT_LAYOUT_ATTRIBUTE, layoutMemory.layoutMap[key].currentLayout.toString()); - - QString layoutSetString; - foreach(const LayoutUnit& layoutUnit, layoutMemory.layoutMap[key].layouts) { - if( ! layoutSetString.isEmpty() ) { - layoutSetString += LIST_SEPARATOR_LM; - } - layoutSetString += layoutUnit.toString(); - } - item.setAttribute(LAYOUTS_ATTRIBUTE, layoutSetString); - root.appendChild(item); - } - } - - return doc.toString(); -} - -bool LayoutMemoryPersister::save() -{ - QFileInfo fileInfo(QStandardPaths::writableLocation(QStandardPaths::DataLocation) + REL_SESSION_FILE_PATH); - - QDir baseDir(fileInfo.absoluteDir()); - if( ! baseDir.exists() ) { - if( ! QDir().mkpath(baseDir.absolutePath()) ) { - qCWarning(KCM_KEYBOARD) << "Failed to create directory" << baseDir.absolutePath(); - } - } - - QFile file(fileInfo.absoluteFilePath()); - return saveToFile(file); -} - -bool LayoutMemoryPersister::restore() -{ - QFile file(QStandardPaths::writableLocation(QStandardPaths::DataLocation) + REL_SESSION_FILE_PATH); - if (!file.exists()) { - return false; - } - return restoreFromFile(file); -} - - -bool LayoutMemoryPersister::saveToFile(const QFile& file_) -{ - QString xml = getLayoutMapAsString(); - if( xml.isEmpty() ) - return false; - - QFile file(file_.fileName()); // so we don't expose the file we open/close to the caller - if( ! file.open( QIODevice::WriteOnly | QIODevice::Truncate | QIODevice::Text) ) { - qCWarning(KCM_KEYBOARD) << "Failed to open layout memory xml file for writing" << file.fileName(); - return false; - } - - QTextStream out(&file); - out << xml; - out.flush(); - - if( file.error() != QFile::NoError ) { - qCWarning(KCM_KEYBOARD) << "Failed to store keyboard layout memory, error" << file.error(); - file.close(); - file.remove(); - return false; - } - else { - qCDebug(KCM_KEYBOARD) << "Keyboard layout memory stored into" << file.fileName() << "written" << file.pos(); - return true; - } -} - - -class MapHandler : public QXmlDefaultHandler -{ -public: - MapHandler(const KeyboardConfig::SwitchingPolicy& switchingPolicy_): - verified(false), - switchingPolicy(switchingPolicy_) {} - - bool startElement(const QString &/*namespaceURI*/, const QString &/*localName*/, - const QString &qName, const QXmlAttributes &attributes) override { - - if( qName == ROOT_NODE ) { - if( attributes.value(VERSION_ATTRIBUTE) != VERSION ) - return false; - if( attributes.value(SWITCH_MODE_ATTRIBUTE) != KeyboardConfig::getSwitchingPolicyString(switchingPolicy) ) - return false; - - verified = true; - } - if( qName == ITEM_NODE ) { - if( ! verified ) - return false; - - if( switchingPolicy == KeyboardConfig::SWITCH_POLICY_GLOBAL ) { - globalLayout = LayoutUnit(attributes.value(CURRENT_LAYOUT_ATTRIBUTE)); - } - else { - QStringList layoutStrings = attributes.value(LAYOUTS_ATTRIBUTE).split(LIST_SEPARATOR_LM); - LayoutSet layoutSet; - foreach(const QString& layoutString, layoutStrings) { - layoutSet.layouts.append(LayoutUnit(layoutString)); - } - layoutSet.currentLayout = LayoutUnit(attributes.value(CURRENT_LAYOUT_ATTRIBUTE)); - QString ownerKey = attributes.value(OWNER_KEY_ATTRIBUTE); - - if( ownerKey.trimmed().isEmpty() || ! layoutSet.isValid() ) - return false; - - layoutMap[ownerKey] = layoutSet; - } - } - return verified; - } - - bool verified; - QMap layoutMap; - LayoutUnit globalLayout; - -private: - const KeyboardConfig::SwitchingPolicy& switchingPolicy; -}; - -template -static -bool containsAll(QList set1, QList set2) -{ - foreach(const T& t, set2) { - if( ! set1.contains(t) ) - return false; - } - return true; -} - -bool LayoutMemoryPersister::restoreFromFile(const QFile& file_) -{ - globalLayout = LayoutUnit(); - - if( ! canPersist() ) - return false; - - QFile file(file_.fileName()); // so we don't expose the file we open/close to the caller - if( ! file.open( QIODevice::ReadOnly | QIODevice::Text ) ) { - qCWarning(KCM_KEYBOARD) << "Failed to open layout memory xml file for reading" << file.fileName() << "error:" << file.error(); - return false; - } - - MapHandler mapHandler(layoutMemory.keyboardConfig.switchingPolicy); - - QXmlSimpleReader reader; - reader.setContentHandler(&mapHandler); - reader.setErrorHandler(&mapHandler); - - QXmlInputSource xmlInputSource(&file); - qCDebug(KCM_KEYBOARD) << "Restoring keyboard layout map from" << file.fileName(); - - if( ! reader.parse(xmlInputSource) ) { - qCWarning(KCM_KEYBOARD) << "Failed to parse the layout memory file" << file.fileName(); - return false; - } - - if( layoutMemory.keyboardConfig.switchingPolicy == KeyboardConfig::SWITCH_POLICY_GLOBAL ) { - if( mapHandler.globalLayout.isValid() && layoutMemory.keyboardConfig.layouts.contains(mapHandler.globalLayout)) { - globalLayout = mapHandler.globalLayout; - qCDebug(KCM_KEYBOARD) << "Restored global layout" << globalLayout.toString(); - } - } - else { - layoutMemory.layoutMap.clear(); - foreach(const QString& key, mapHandler.layoutMap.keys()) { - if( containsAll(layoutMemory.keyboardConfig.layouts, mapHandler.layoutMap[key].layouts) ) { - layoutMemory.layoutMap.insert(key, mapHandler.layoutMap[key]); - } - } - qCDebug(KCM_KEYBOARD) << "Restored layouts for" << layoutMemory.layoutMap.size() << "containers"; - } - return true; -} - -bool LayoutMemoryPersister::canPersist() { - // we can't persist per window - as we're using window id which is not preserved between sessions - bool windowMode = layoutMemory.keyboardConfig.switchingPolicy == KeyboardConfig::SWITCH_POLICY_WINDOW; - if( windowMode ) { - qCDebug(KCM_KEYBOARD) << "Not saving session for window mode"; - } - return !windowMode; -} diff --git a/kcms/keyboard/layout_tray_icon.h b/kcms/keyboard/layout_tray_icon.h deleted file mode 100644 --- a/kcms/keyboard/layout_tray_icon.h +++ /dev/null @@ -1,66 +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. - */ - - -#ifndef LAYOUT_TRAY_ICON_H_ -#define LAYOUT_TRAY_ICON_H_ - - -#include "flags.h" -#include "x11_helper.h" - -class KeyboardConfig; -class LayoutsMenu; - -/** - * System tray icon to show layouts - */ -class KStatusNotifierItem; -struct Rules; -class Flags; -class LayoutTrayIcon : public QObject -{ - Q_OBJECT - -public: - LayoutTrayIcon(const Rules* rules, const KeyboardConfig& keyboardConfig); - ~LayoutTrayIcon(); - - void layoutMapChanged(); - -public Q_SLOTS: - void layoutChanged(); - -private Q_SLOTS: - void toggleLayout(); - void scrollRequested(int, Qt::Orientation); - -private: - void init(); - void destroy(); - const QIcon getFlag(const QString& layout) const; - - const KeyboardConfig& keyboardConfig; - const Rules* rules; - Flags* flags; - KStatusNotifierItem *m_notifierItem; - LayoutsMenu* layoutsMenu; -}; - - -#endif /* LAYOUT_WIDGET_H_ */ diff --git a/kcms/keyboard/layout_tray_icon.cpp b/kcms/keyboard/layout_tray_icon.cpp deleted file mode 100644 --- a/kcms/keyboard/layout_tray_icon.cpp +++ /dev/null @@ -1,126 +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. - */ - -#include "layout_tray_icon.h" - -#include -#include - -#include - -#include "xkb_rules.h" -#include "x11_helper.h" -#include "xkb_helper.h" -#include "keyboard_config.h" -#include "flags.h" -#include "layouts_menu.h" - - -// -// Layout Tray Icon -// -LayoutTrayIcon::LayoutTrayIcon(const Rules* rules_, const KeyboardConfig& keyboardConfig_): - keyboardConfig(keyboardConfig_), - rules(rules_), - flags(new Flags()), - layoutsMenu(new LayoutsMenu(keyboardConfig_, *rules, *flags)) -{ - m_notifierItem = new KStatusNotifierItem(this); - m_notifierItem->setCategory(KStatusNotifierItem::Hardware); - m_notifierItem->setStatus(KStatusNotifierItem::Active); - m_notifierItem->setToolTipTitle(i18nc("tooltip title", "Keyboard Layout")); - m_notifierItem->setTitle(i18nc("tooltip title", "Keyboard Layout")); - m_notifierItem->setToolTipIconByName(QStringLiteral("preferences-desktop-keyboard")); - - QMenu* menu = new QMenu(QLatin1String("")); - m_notifierItem->setContextMenu(menu); - m_notifierItem->setStandardActionsEnabled(false); - - layoutMapChanged(); - - m_notifierItem->setStatus(KStatusNotifierItem::Active); - - init(); -} - -LayoutTrayIcon::~LayoutTrayIcon() -{ - destroy(); - delete flags; - delete layoutsMenu; -} - -void LayoutTrayIcon::init() -{ - connect(m_notifierItem, &KStatusNotifierItem::activateRequested, this, &LayoutTrayIcon::toggleLayout); - connect(m_notifierItem, &KStatusNotifierItem::scrollRequested, this, &LayoutTrayIcon::scrollRequested); - connect(flags, &Flags::pixmapChanged, this, &LayoutTrayIcon::layoutChanged); -} - -void LayoutTrayIcon::destroy() -{ - disconnect(flags, &Flags::pixmapChanged, this, &LayoutTrayIcon::layoutChanged); - disconnect(m_notifierItem, &KStatusNotifierItem::scrollRequested, this, &LayoutTrayIcon::scrollRequested); - disconnect(m_notifierItem, &KStatusNotifierItem::activateRequested, this, &LayoutTrayIcon::toggleLayout); -} - -void LayoutTrayIcon::layoutMapChanged() -{ - flags->clearCache(); - - QMenu* menu = m_notifierItem->contextMenu(); - menu->clear(); - QList actions = layoutsMenu->contextualActions(); - menu->addActions(actions); - - layoutChanged(); -} - -void LayoutTrayIcon::layoutChanged() -{ - LayoutUnit layoutUnit = X11Helper::getCurrentLayout(); - if( layoutUnit.isEmpty() ) - return; - -// QString shortText = Flags::getShortText(layoutUnit, *keyboardConfig); -// qDebug() << "systray: LayoutChanged" << layoutUnit.toString() << shortText; - QString longText = Flags::getLongText(layoutUnit, rules); - - m_notifierItem->setToolTipSubTitle(longText); - - const QIcon icon(getFlag(layoutUnit.layout)); - m_notifierItem->setToolTipIconByPixmap(icon); - - QIcon textOrIcon = flags->getIconWithText(layoutUnit, keyboardConfig); - m_notifierItem->setIconByPixmap( textOrIcon ); -} - -void LayoutTrayIcon::toggleLayout() -{ - X11Helper::switchToNextLayout(); -} - -void LayoutTrayIcon::scrollRequested(int delta, Qt::Orientation /*orientation*/) -{ - X11Helper::scrollLayouts(delta > 0 ? 1 : -1); -} - -const QIcon LayoutTrayIcon::getFlag(const QString& layout) const -{ - return keyboardConfig.isFlagShown() ? flags->getIcon(layout) : QIcon::fromTheme(QStringLiteral("preferences-desktop-keyboard")); -} diff --git a/kcms/keyboard/layoutmodel/CMakeLists.txt b/kcms/keyboard/layoutmodel/CMakeLists.txt new file mode 100644 --- /dev/null +++ b/kcms/keyboard/layoutmodel/CMakeLists.txt @@ -0,0 +1,62 @@ + +set(kcm_keyboard_layoutmodel_SRCS + layout_list_models.cpp + layout_list_model_base.cpp + layout_list_model_xkb.cpp + layout_list_sort_by_priority_proxy_model.cpp + layout_list_filter_duplicates_proxy_model.cpp + layout_list_xkb_expand_proxy_model.cpp + layout_list_model_fcitx.cpp + layout_list_concat_proxy_model.cpp + layout_list_filter_source_proxy_model.cpp + layout_list_model_selected.cpp + layout_list_sort_filter_proxy_model.cpp + layout_list_filter_disabled_proxy_model.cpp + layout_list_current_proxy_model.cpp + + input_sources.cpp + + xkb_layout_config_model.cpp + fcitx_im_config_model.cpp + + ../fcitx/fcitxqtinputmethodproxy.cpp + ../fcitx/fcitxqtinputmethoditem.cpp + ../xkb_rules.cpp +) + +ecm_qt_declare_logging_category(kcm_keyboard_layoutmodel_SRCS + HEADER debug.h + IDENTIFIER KCM_KEYBOARD + CATEGORY_NAME org.kde.kcm_keyboard + DEFAULT_SEVERITY Warning) + +add_library(kcm_keyboard_layoutmodel STATIC ${kcm_keyboard_layoutmodel_SRCS}) + +target_link_libraries(kcm_keyboard_layoutmodel + KF5::ConfigCore + KF5::CoreAddons + KF5::QuickAddons + KF5::Declarative + KF5::KCMUtils + KF5::I18n + KF5::GlobalAccel + KF5::WindowSystem + KF5::IconThemes + KF5::XmlGui + KF5::Plasma + KF5::ItemModels + KF5::GuiAddons + Qt5::Quick + Qt5::Concurrent + Qt5::X11Extras + Qt5::DBus + XCB::XCB + XCB::XKB + ${X11_LIBRARIES} + ${X11_Xkbfile_LIB} +) + +target_include_directories(kcm_keyboard_layoutmodel PRIVATE + ${CMAKE_CURRENT_BINARY_DIR}) + +configure_file(../config-keyboard.h.cmake ${CMAKE_CURRENT_BINARY_DIR}/config-keyboard.h) diff --git a/kcms/keyboard/layoutmodel/fcitx_im_config_model.h b/kcms/keyboard/layoutmodel/fcitx_im_config_model.h new file mode 100644 --- /dev/null +++ b/kcms/keyboard/layoutmodel/fcitx_im_config_model.h @@ -0,0 +1,107 @@ +#ifndef FCITXIMCONFIGMODEL_H +#define FCITXIMCONFIGMODEL_H + +#include +#include "layout_list_sort_filter_proxy_model.h" + +class FcitxIMListModel : public LayoutListSortFilterProxyModel +{ + Q_OBJECT + +public: + FcitxIMListModel(QObject* parent); + QHash roleNames() const override; + + bool filterAcceptsRow(int source_row, const QModelIndex &source_parent) const override; +}; + +class FcitxIMConfigModel : public QAbstractListModel +{ + Q_OBJECT + Q_PROPERTY(bool isRealIM READ isRealIM NOTIFY isRealIMChanged) + Q_PROPERTY(bool isLatinSwitchingEnabled READ isLatinSwitchingEnabled WRITE setIsLatinSwitchingEnabled NOTIFY isLatinSwitchingEnabledChanged) + Q_PROPERTY(FcitxIMListModel* latinModeLayoutList READ latinModeLayoutList NOTIFY latinModeLayoutListChanged) + Q_PROPERTY(int selectedLatinLayoutIndex READ selectedLatinLayoutIndex WRITE setSelectedLatinLayoutIndex NOTIFY selectedLatinLayoutIndexChanged) + +public: + explicit FcitxIMConfigModel(QString imName, QObject *parent = nullptr); + + // Basic functionality: + int rowCount(const QModelIndex &parent = QModelIndex()) const override; + + QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override; + bool setData(const QModelIndex &index, const QVariant &value, int role) override; + + struct Roles { + enum { + NameRole = Qt::UserRole + 1, + GroupRole, + TypeRole, + DescriptionRole, + DataRole, + CurrentValueRole + }; + }; + + QHash roleNames() const override; + + Q_INVOKABLE void save() const; + + enum ConfigType { + IntegerType, + ColorType, + CharType, + StringType, + I18NStringType, + BooleanType, + FileType, + FontType, + HotkeyType, + EnumType + }; + Q_ENUM(ConfigType) + + FcitxIMListModel* latinModeLayoutList() const; + + bool isLatinSwitchingEnabled() const; + void setIsLatinSwitchingEnabled(bool isLatinSwitchingEnabled); + + int selectedLatinLayoutIndex() const; + void setSelectedLatinLayoutIndex(int selectedLatinLayoutIndex); + + QString selectedLatinLayoutId() const; + void setSelectedLatinLayoutId(const QString &selectedLatinLayoutId); + + bool isRealIM() const; + +Q_SIGNALS: + void isLatinSwitchingEnabledChanged(); + void selectedLatinLayoutIndexChanged(); + void latinModeLayoutListChanged(); + void isRealIMChanged(); + +private: + + QString m_imName; + QString m_addonName; + + struct ConfigItem { + QString group; + QString name; + ConfigType type; + QString description; + QVariant default_value; + QVariant current_value; + QVariant data; + }; + + QList m_configs; + + FcitxIMListModel* m_latinModeLayoutList; + QString m_selectedLatinLayoutId; + bool m_isLatinSwitchingEnabled; +}; + +Q_DECLARE_METATYPE(FcitxIMConfigModel*) + +#endif // FCITXIMCONFIGMODEL_H diff --git a/kcms/keyboard/layoutmodel/fcitx_im_config_model.cpp b/kcms/keyboard/layoutmodel/fcitx_im_config_model.cpp new file mode 100644 --- /dev/null +++ b/kcms/keyboard/layoutmodel/fcitx_im_config_model.cpp @@ -0,0 +1,308 @@ +#include "fcitx_im_config_model.h" + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "../fcitx/fcitxqtinputmethodproxy.h" +#include "layout_list_model_fcitx.h" +#include "../keyboard_dbus.h" + +FcitxIMListModel::FcitxIMListModel(QObject* parent) + : LayoutListSortFilterProxyModel(parent) +{ + setSourceModel(new LayoutListModelFcitx(this)); + setSortRole(Roles::DescriptionRole); + sort(0); +} + +QHash FcitxIMListModel::roleNames() const +{ + return LayoutListModelBase::roleNames(); +} + +bool FcitxIMListModel::filterAcceptsRow(int source_row, const QModelIndex &) const +{ + QString name = sourceModel()->data(sourceModel()->index(source_row, 0), Roles::NameRole).toString(); + return name.startsWith("fcitx-keyboard-"); +} + +FcitxIMConfigModel::FcitxIMConfigModel(QString imName, QObject* parent) + : QAbstractListModel(parent) + , m_imName(imName) +{ + QDBusInterface interface("org.fcitx.Fcitx", "/inputmethod", "org.fcitx.Fcitx.InputMethod"); + QDBusMessage reply = interface.call("GetIMAddon", imName); + m_addonName = reply.arguments().first().toString(); + + QString config_desc_path = QString("/usr/share/fcitx/configdesc/%1.desc").arg(m_addonName); + + // determine order of config items + QFile config_desc_file(config_desc_path); + config_desc_file.open(QIODevice::ReadOnly); + if (!config_desc_file.isOpen()) { + qWarning() << "Cannot open config description file"; + return; + } + QTextStream stream(&config_desc_file); + QString line; + QStringList order; + while (stream.readLineInto(&line)) { + if (line.startsWith('[')) { + order << line; + } + } + config_desc_file.close(); + + // read description + QSettings config_desc(config_desc_path, QSettings::IniFormat); + for (QString group : config_desc.childGroups()) { + if (group == "DescriptionFile") { + continue; + } + config_desc.beginGroup(group); + for (QString name : config_desc.childGroups()) { + config_desc.beginGroup(name); + + ConfigItem item; + item.group = group; + item.name = name; + item.description = config_desc.value("Description").toString(); + item.default_value = config_desc.value("DefaultValue").toString(); + + QString type_string = config_desc.value("Type").toString(); + if (type_string == "Integer") { + item.type = ConfigType::IntegerType; + } else if (type_string == "Char") { + item.type = ConfigType::CharType; + } else if (type_string == "String") { + item.type = ConfigType::StringType; + } else if (type_string == "I18NString") { + item.type = ConfigType::I18NStringType; + } else if (type_string == "Boolean") { + item.type = ConfigType::BooleanType; + } else if (type_string == "File") { + item.type = ConfigType::FileType; + } else if (type_string == "Font") { + item.type = ConfigType::FontType; + } else if (type_string == "Hotkey") { + item.type = ConfigType::HotkeyType; + } else if (type_string == "Enum") { + item.type = ConfigType::EnumType; + int num = config_desc.value("EnumCount").toInt(); + QStringList list; + for (int i = 0; i < num; ++i) { + list << config_desc.value(QString("Enum%1").arg(i)).toString(); + } + item.data = list; + } + + m_configs << item; + + config_desc.endGroup(); + } + config_desc.endGroup(); + } + + std::sort(m_configs.begin(), m_configs.end(), [&](ConfigItem const& l, ConfigItem const& r) { + int left = order.indexOf(QString("[%1/%2]").arg(l.group, l.name)); + int right = order.indexOf(QString("[%1/%2]").arg(r.group, r.name)); + Q_ASSERT(left != -1 && right != -1); + return left < right; + }); + + // read config values + auto config_path = QString("fcitx/conf/%1.config").arg(m_addonName); + KSharedConfigPtr config = KSharedConfig::openConfig(config_path, KConfig::SimpleConfig); + + for (auto& item : m_configs) { + KConfigGroup group(config, item.group); + + switch (item.type) { + case ConfigType::IntegerType: + item.current_value = group.readEntry(item.name, item.default_value.toInt()); + break; + case ConfigType::BooleanType: + item.current_value = group.readEntry(item.name, item.default_value.toBool()); + break; + case ConfigType::EnumType: + item.current_value = group.readEntry(item.name, item.default_value.toString()); + break; + case ConfigType::CharType: + case ConfigType::StringType: + case ConfigType::HotkeyType: + item.current_value = group.readEntry(item.name, item.default_value.toString()); + break; + } + } + + if (isRealIM()) { + m_latinModeLayoutList = new FcitxIMListModel(this); + + KConfigGroup kxkbrc( + KSharedConfig::openConfig(QStringLiteral("kxkbrc"), KConfig::NoGlobals), + QStringLiteral("Layout")); + + setIsLatinSwitchingEnabled(kxkbrc.readEntry(QString("Fcitx%1LatinFallBackEnabled").arg(m_imName), false)); + setSelectedLatinLayoutId(kxkbrc.readEntry(QString("Fcitx%1LatinFallBack").arg(m_imName), QString("us"))); + } +} + +int FcitxIMConfigModel::rowCount(const QModelIndex& parent) const +{ + // For list models only the root node (an invalid parent) should return the list's size. For all + // other (valid) parents, rowCount() should return 0 so that it does not become a tree model. + if (parent.isValid()) + return 0; + + return m_configs.size(); +} + +QVariant FcitxIMConfigModel::data(const QModelIndex& index, int role) const +{ + if (!index.isValid()) + return QVariant(); + + auto const& item = m_configs[index.row()]; + switch (role) { + case Roles::NameRole: + return item.name; + case Roles::GroupRole: + return item.group; + case Roles::TypeRole: + return QMetaEnum::fromType().valueToKey(item.type); + case Roles::DescriptionRole: + return item.description; + case Roles::DataRole: + return item.data; + case Roles::CurrentValueRole: + return item.current_value; + } + + return QVariant(); +} + +bool FcitxIMConfigModel::setData(const QModelIndex& index, const QVariant& value, int role) +{ + qDebug() << "setData"; + if (role == Roles::CurrentValueRole) { + m_configs[index.row()].current_value = value; + } + return false; +} + +QHash FcitxIMConfigModel::roleNames() const +{ + return { + { Roles::NameRole, "name" }, + { Roles::GroupRole, "group" }, + { Roles::TypeRole, "type" }, + { Roles::DescriptionRole, "description" }, + { Roles::DataRole, "data" }, + { Roles::CurrentValueRole, "current_value" } + }; +} + +void FcitxIMConfigModel::save() const +{ + qDebug() << "save"; + if (isRealIM()) { + KConfigGroup kxkbrc( + KSharedConfig::openConfig(QStringLiteral("kxkbrc"), KConfig::NoGlobals), + QStringLiteral("Layout")); + kxkbrc.writeEntry(QString("Fcitx%1LatinFallBackEnabled").arg(m_imName), isLatinSwitchingEnabled()); + kxkbrc.writeEntry(QString("Fcitx%1LatinFallBack").arg(m_imName), m_selectedLatinLayoutId); + kxkbrc.sync(); + } + + auto config_path = QString("fcitx/conf/%1.config").arg(m_addonName); + KSharedConfigPtr config = KSharedConfig::openConfig(config_path, KConfig::SimpleConfig); + + for (auto const& item : m_configs) { + KConfigGroup group(config, item.group); + + switch (item.type) { + case ConfigType::IntegerType: + group.writeEntry(item.name, item.current_value.toInt()); + break; + case ConfigType::BooleanType: + group.writeEntry(item.name, item.current_value.toBool()); + break; + case ConfigType::EnumType: + group.writeEntry(item.name, item.current_value.toString()); + break; + case ConfigType::CharType: + case ConfigType::StringType: + case ConfigType::HotkeyType: + group.writeEntry(item.name, item.current_value.toString()); + break; + } + + group.sync(); + } + + // dbus call to the kded (in X11) / kwin (in Wayland) to apply the config changes + QDBusMessage message = QDBusMessage::createSignal( + KEYBOARD_DBUS_OBJECT_PATH, + KEYBOARD_DBUS_SERVICE_NAME, + KEYBOARD_DBUS_CONFIG_RELOAD_MESSAGE); + QDBusConnection::sessionBus().send(message); +} + +FcitxIMListModel* FcitxIMConfigModel::latinModeLayoutList() const +{ + return m_latinModeLayoutList; +} + +bool FcitxIMConfigModel::isLatinSwitchingEnabled() const +{ + return m_isLatinSwitchingEnabled; +} + +void FcitxIMConfigModel::setIsLatinSwitchingEnabled(bool isLatinSwitchingEnabled) +{ + if (m_isLatinSwitchingEnabled != isLatinSwitchingEnabled) { + m_isLatinSwitchingEnabled = isLatinSwitchingEnabled; + } +} + +int FcitxIMConfigModel::selectedLatinLayoutIndex() const +{ + for (int row = 0; row < m_latinModeLayoutList->rowCount(); ++row) { + if (m_latinModeLayoutList->data(m_latinModeLayoutList->index(row, 0), Roles::NameRole) == m_selectedLatinLayoutId) { + return row; + } + } + return -1; +} + +void FcitxIMConfigModel::setSelectedLatinLayoutIndex(int index) +{ + if (selectedLatinLayoutIndex() != index) { + m_selectedLatinLayoutId = m_latinModeLayoutList->data(m_latinModeLayoutList->index(index, 0), Roles::NameRole).toString(); + emit selectedLatinLayoutIndexChanged(); + } +} + +QString FcitxIMConfigModel::selectedLatinLayoutId() const +{ + return m_selectedLatinLayoutId; +} + +void FcitxIMConfigModel::setSelectedLatinLayoutId(const QString &selectedLatinLayoutId) +{ + if (m_selectedLatinLayoutId != selectedLatinLayoutId) { + m_selectedLatinLayoutId = selectedLatinLayoutId; + emit selectedLatinLayoutIndexChanged(); + } +} + +bool FcitxIMConfigModel::isRealIM() const +{ + return !m_imName.startsWith("fcitx-keyboard-"); +} diff --git a/kcms/keyboard/layoutmodel/input_sources.h b/kcms/keyboard/layoutmodel/input_sources.h new file mode 100644 --- /dev/null +++ b/kcms/keyboard/layoutmodel/input_sources.h @@ -0,0 +1,34 @@ +#ifndef FCITXDETECTOR_H +#define FCITXDETECTOR_H + +#include + +class InputSources : public QObject { + Q_OBJECT + +public: + static InputSources* self(); + struct Sources { + enum { + UnknownSource = 0, + XkbSource = 1, + FcitxSource = 2, + }; + }; + int currentSource() const; + +Q_SIGNALS: + void currentSourceChanged(int newSource); + +private Q_SLOTS: + void serviceRegistered(QString const& name); + void serviceUnregistered(QString const& name); + +private: + InputSources(); + static InputSources m_self; + QDBusServiceWatcher *m_fcitxWatcher; + bool m_isFcitxRegistered; +}; + +#endif // FCITXDETECTOR_H diff --git a/kcms/keyboard/layoutmodel/input_sources.cpp b/kcms/keyboard/layoutmodel/input_sources.cpp new file mode 100644 --- /dev/null +++ b/kcms/keyboard/layoutmodel/input_sources.cpp @@ -0,0 +1,56 @@ +#include "input_sources.h" + +#include +#include +#include +#include + +InputSources InputSources::m_self{}; + +InputSources* InputSources::self() +{ + return &m_self; +} + +int InputSources::currentSource() const +{ + if (m_isFcitxRegistered) { + return Sources::FcitxSource; + } + else { + return Sources::XkbSource; + } +} + +void InputSources::serviceRegistered(const QString &name) +{ + // FIXME: why is this called twice?? + qDebug() << name << "registered" << this; + m_isFcitxRegistered = true; + emit currentSourceChanged(Sources::FcitxSource); +} + +void InputSources::serviceUnregistered(const QString &name) +{ + qDebug() << name << "unregistered" << this; + m_isFcitxRegistered = false; + emit currentSourceChanged(Sources::XkbSource); +} + +InputSources::InputSources() +{ + // This can cause fcitx to "wake up" + QDBusInterface interface("org.fcitx.Fcitx", "/", ""); + m_isFcitxRegistered = interface.isValid(); + + m_fcitxWatcher = new QDBusServiceWatcher( + "org.fcitx.Fcitx", + QDBusConnection::sessionBus(), + QDBusServiceWatcher::WatchForRegistration | QDBusServiceWatcher::WatchForUnregistration, + this); + + QObject::connect(m_fcitxWatcher, &QDBusServiceWatcher::serviceRegistered, + this, &InputSources::serviceRegistered); + QObject::connect(m_fcitxWatcher, &QDBusServiceWatcher::serviceUnregistered, + this, &InputSources::serviceUnregistered); +} diff --git a/kcms/keyboard/layoutmodel/layout_list_concat_proxy_model.h b/kcms/keyboard/layoutmodel/layout_list_concat_proxy_model.h new file mode 100644 --- /dev/null +++ b/kcms/keyboard/layoutmodel/layout_list_concat_proxy_model.h @@ -0,0 +1,16 @@ +#ifndef LAYOUT_LIST_CONCAT_PROXY_MODEL_H +#define LAYOUT_LIST_CONCAT_PROXY_MODEL_H + +#include + +#include "layout_list_model_base.h" + +class LayoutListConcatProxyModel : public KConcatenateRowsProxyModel, public LayoutListModelBase { + Q_OBJECT +public: + LayoutListConcatProxyModel(QObject* parent); + + QHash roleNames() const override; +}; + +#endif // LAYOUT_LIST_CONCAT_PROXY_MODEL_H diff --git a/kcms/keyboard/layoutmodel/layout_list_concat_proxy_model.cpp b/kcms/keyboard/layoutmodel/layout_list_concat_proxy_model.cpp new file mode 100644 --- /dev/null +++ b/kcms/keyboard/layoutmodel/layout_list_concat_proxy_model.cpp @@ -0,0 +1,13 @@ +#include "layout_list_concat_proxy_model.h" + +#include "layout_list_model_base.h" + +LayoutListConcatProxyModel::LayoutListConcatProxyModel(QObject* parent) + : KConcatenateRowsProxyModel(parent) +{ +} + +QHash LayoutListConcatProxyModel::roleNames() const +{ + return LayoutListModelBase::roleNames(); +} diff --git a/kcms/keyboard/layoutmodel/layout_list_current_proxy_model.h b/kcms/keyboard/layoutmodel/layout_list_current_proxy_model.h new file mode 100644 --- /dev/null +++ b/kcms/keyboard/layoutmodel/layout_list_current_proxy_model.h @@ -0,0 +1,19 @@ +#ifndef LAYOUT_LIST_CURRENT_PROXY_MODEL_H +#define LAYOUT_LIST_CURRENT_PROXY_MODEL_H + +#include "layout_list_model_base.h" +#include +#include + +class LayoutListCurrentProxyModel : public QSortFilterProxyModel, public LayoutListModelBase { + Q_OBJECT +public: + LayoutListCurrentProxyModel(QObject* parent); + + bool filterAcceptsRow(int source_row, const QModelIndex &source_parent) const override; + +private Q_SLOTS: + void currentInputSourceChanged(); +}; + +#endif // LAYOUT_LIST_CURRENT_PROXY_MODEL_H diff --git a/kcms/keyboard/layoutmodel/layout_list_current_proxy_model.cpp b/kcms/keyboard/layoutmodel/layout_list_current_proxy_model.cpp new file mode 100644 --- /dev/null +++ b/kcms/keyboard/layoutmodel/layout_list_current_proxy_model.cpp @@ -0,0 +1,22 @@ +#include "layout_list_current_proxy_model.h" +#include "input_sources.h" +#include + +LayoutListCurrentProxyModel::LayoutListCurrentProxyModel(QObject* parent) + : QSortFilterProxyModel(parent) +{ + connect(InputSources::self(), &InputSources::currentSourceChanged, this, &LayoutListCurrentProxyModel::currentInputSourceChanged); +} + +bool LayoutListCurrentProxyModel::filterAcceptsRow(int source_row, const QModelIndex &) const +{ + int source = sourceModel()->data( + sourceModel()->index(source_row, 0), + Roles::SourceRole).toInt(); + return source == InputSources::self()->currentSource(); +} + +void LayoutListCurrentProxyModel::currentInputSourceChanged() +{ + invalidateFilter(); +} diff --git a/kcms/keyboard/layoutmodel/layout_list_filter_disabled_proxy_model.h b/kcms/keyboard/layoutmodel/layout_list_filter_disabled_proxy_model.h new file mode 100644 --- /dev/null +++ b/kcms/keyboard/layoutmodel/layout_list_filter_disabled_proxy_model.h @@ -0,0 +1,15 @@ +#ifndef LAYOUT_LIST_FILTER_DISBLED_PROXYMODEL_H +#define LAYOUT_LIST_FILTER_DISBLED_PROXYMODEL_H + +#include +#include "layout_list_model_base.h" + +class LayoutListFilterDisabledProxyModel : public QSortFilterProxyModel, public LayoutListModelBase { + Q_OBJECT +public: + LayoutListFilterDisabledProxyModel(QObject* parent); + + bool filterAcceptsRow(int source_row, const QModelIndex &source_parent) const override; +}; + +#endif // LAYOUT_LIST_FILTER_DISBLED_PROXYMODEL_H diff --git a/kcms/keyboard/layoutmodel/layout_list_filter_disabled_proxy_model.cpp b/kcms/keyboard/layoutmodel/layout_list_filter_disabled_proxy_model.cpp new file mode 100644 --- /dev/null +++ b/kcms/keyboard/layoutmodel/layout_list_filter_disabled_proxy_model.cpp @@ -0,0 +1,12 @@ +#include "layout_list_filter_disabled_proxy_model.h" + +LayoutListFilterDisabledProxyModel::LayoutListFilterDisabledProxyModel(QObject* parent) + : QSortFilterProxyModel(parent) +{ + setFilterRole(Roles::EnabledRole); +} + +bool LayoutListFilterDisabledProxyModel::filterAcceptsRow(int source_row, const QModelIndex &) const +{ + return sourceModel()->data(sourceModel()->index(source_row, 0), Roles::EnabledRole).toBool(); +} diff --git a/kcms/keyboard/layoutmodel/layout_list_filter_duplicates_proxy_model.h b/kcms/keyboard/layoutmodel/layout_list_filter_duplicates_proxy_model.h new file mode 100644 --- /dev/null +++ b/kcms/keyboard/layoutmodel/layout_list_filter_duplicates_proxy_model.h @@ -0,0 +1,30 @@ +#ifndef LAYOUTLISTREMOVEDUPLICATESPROXYMODEL_H +#define LAYOUTLISTREMOVEDUPLICATESPROXYMODEL_H + +#include "layout_list_model_base.h" +#include +#include + +class LayoutListFilterDuplicatesProxyModel : public QSortFilterProxyModel, public LayoutListModelBase { + Q_OBJECT +public: + explicit LayoutListFilterDuplicatesProxyModel(QObject* parent = nullptr); + + bool filterAcceptsRow(int source_row, const QModelIndex& source_parent) const override; + + QVariant data(const QModelIndex& index, int role) const override; + Q_INVOKABLE void add(int idx); + +public Q_SLOTS: + void updateFilter(); + void updateEnabled(); + +Q_SIGNALS: + void missingCountChanged(); + void itemAdded(QString const& name); + +private: + int getGhostItemRow(const QModelIndex& index) const; +}; + +#endif // LAYOUTLISTREMOVEDUPLICATESPROXYMODEL_H diff --git a/kcms/keyboard/layoutmodel/layout_list_filter_duplicates_proxy_model.cpp b/kcms/keyboard/layoutmodel/layout_list_filter_duplicates_proxy_model.cpp new file mode 100644 --- /dev/null +++ b/kcms/keyboard/layoutmodel/layout_list_filter_duplicates_proxy_model.cpp @@ -0,0 +1,78 @@ +#include "layout_list_filter_duplicates_proxy_model.h" + +#include "input_sources.h" + +#include + +LayoutListFilterDuplicatesProxyModel::LayoutListFilterDuplicatesProxyModel(QObject* parent) + : QSortFilterProxyModel(parent) +{ +} + +bool LayoutListFilterDuplicatesProxyModel::filterAcceptsRow(int source_row, const QModelIndex&) const +{ + int source = sourceModel()->data(sourceModel()->index(source_row, 0), Roles::SourceRole).toInt(); + QString name = sourceModel()->data(sourceModel()->index(source_row, 0), Roles::SaveNameRole).toString(); + + if (source != InputSources::Sources::UnknownSource) + return true; + + if ((source_row > 0 && name == sourceModel()->data(sourceModel()->index(source_row - 1, 0), Roles::SaveNameRole).toString()) + || (source_row < sourceModel()->rowCount() - 1 && name == sourceModel()->data(sourceModel()->index(source_row + 1, 0), Roles::SaveNameRole).toString())) { + return false; + } + return true; +} + +QVariant LayoutListFilterDuplicatesProxyModel::data(const QModelIndex& idx, int role) const +{ + if (!idx.isValid()) { + return QVariant(); + } + + if (role == Roles::EnabledRole) { + if (data(idx, Roles::SourceRole).toInt() == InputSources::Sources::UnknownSource) { + return true; + } + return getGhostItemRow(idx) >= 0; + } + if ((role == Roles::PriorityRole || + role == Roles::IsLatinModeEnabledRole || + role == Roles::LatinModeLayoutRole) && data(idx, Roles::SourceRole).toInt() != InputSources::Sources::UnknownSource) { + int source_row = getGhostItemRow(idx); + return sourceModel()->data(sourceModel()->index(source_row, 0), role); + } + return QSortFilterProxyModel::data(idx, role); +} + +void LayoutListFilterDuplicatesProxyModel::add(int idx) +{ + QString name = data(index(idx, 0), Roles::SaveNameRole).toString(); + emit itemAdded(name); +} + +int LayoutListFilterDuplicatesProxyModel::getGhostItemRow(const QModelIndex& idx) const +{ + int source_row = mapToSource(idx).row(); + if (data(idx, Roles::SourceRole).toInt() == InputSources::Sources::UnknownSource) { + return source_row; + } + QString name = data(idx, Roles::SaveNameRole).toString(); + if (source_row > 0 && name == sourceModel()->data(sourceModel()->index(source_row - 1, 0), Roles::SaveNameRole).toString()) { + return source_row - 1; + } + if (source_row < sourceModel()->rowCount() - 1 && name == sourceModel()->data(sourceModel()->index(source_row + 1, 0), Roles::SaveNameRole).toString()) { + return source_row + 1; + } + return -1; +} + +void LayoutListFilterDuplicatesProxyModel::updateFilter() +{ + invalidateFilter(); +} + +void LayoutListFilterDuplicatesProxyModel::updateEnabled() +{ + emit dataChanged(index(0, 0), index(rowCount() - 1, 0), { Roles::EnabledRole }); +} diff --git a/kcms/keyboard/layoutmodel/layout_list_filter_source_proxy_model.h b/kcms/keyboard/layoutmodel/layout_list_filter_source_proxy_model.h new file mode 100644 --- /dev/null +++ b/kcms/keyboard/layoutmodel/layout_list_filter_source_proxy_model.h @@ -0,0 +1,18 @@ +#ifndef LAYOUTLISTFILTERSOURCEPROXYMODEL_H +#define LAYOUTLISTFILTERSOURCEPROXYMODEL_H + +#include "layout_list_model_base.h" +#include + +class LayoutListFilterSourceProxyModel : public QSortFilterProxyModel, public LayoutListModelBase { + Q_OBJECT + +public: + LayoutListFilterSourceProxyModel(QObject *parent = nullptr); + + bool filterAcceptsRow(int sourceRow, const QModelIndex& sourceParent) const override; + +private: +}; + +#endif // LAYOUTLISTFILTERSOURCEPROXYMODEL_H diff --git a/kcms/keyboard/layoutmodel/layout_list_filter_source_proxy_model.cpp b/kcms/keyboard/layoutmodel/layout_list_filter_source_proxy_model.cpp new file mode 100644 --- /dev/null +++ b/kcms/keyboard/layoutmodel/layout_list_filter_source_proxy_model.cpp @@ -0,0 +1,22 @@ +#include "layout_list_filter_source_proxy_model.h" + +#include "input_sources.h" +#include "layout_list_concat_proxy_model.h" + +#include + +LayoutListFilterSourceProxyModel::LayoutListFilterSourceProxyModel(QObject* parent) + : QSortFilterProxyModel(parent) +{ + QObject::connect(InputSources::self(), &InputSources::currentSourceChanged, + [&] { invalidateFilter(); }); +} + +bool LayoutListFilterSourceProxyModel::filterAcceptsRow(int sourceRow, const QModelIndex&) const +{ + int src = sourceModel()->data(sourceModel()->index(sourceRow, 0), Roles::SourceRole).toInt(); + if (src == InputSources::Sources::UnknownSource) { + return true; + } + return (src == InputSources::self()->currentSource()); +} diff --git a/kcms/keyboard/layoutmodel/layout_list_model_base.h b/kcms/keyboard/layoutmodel/layout_list_model_base.h new file mode 100644 --- /dev/null +++ b/kcms/keyboard/layoutmodel/layout_list_model_base.h @@ -0,0 +1,33 @@ +#ifndef LAYOUTLISTMODELBASE_H +#define LAYOUTLISTMODELBASE_H + +#include +#include +#include + +class LayoutListModelBase { +public: + virtual ~LayoutListModelBase() = default; + + struct Roles { + enum { + NameRole = Qt::UserRole + 1, + DescriptionRole, + LanguagesRole, + EnabledRole, + IsConfigurableRole, + SourceRole, + ConfigModelRole, + PriorityRole, + SaveNameRole, + IsLatinModeEnabledRole, + LatinModeLayoutRole, + ShortNameRole, + }; + }; + + QHash roleNames() const; + int role(QString const& roleName) const; +}; + +#endif // LAYOUTLISTMODELBASE_H diff --git a/kcms/keyboard/layoutmodel/layout_list_model_base.cpp b/kcms/keyboard/layoutmodel/layout_list_model_base.cpp new file mode 100644 --- /dev/null +++ b/kcms/keyboard/layoutmodel/layout_list_model_base.cpp @@ -0,0 +1,34 @@ +#include "layout_list_model_base.h" + +#include +#include +#include +#include + +QHash LayoutListModelBase::roleNames() const +{ + return { + { Roles::NameRole, "name" }, + { Roles::DescriptionRole, "description" }, + { Roles::LanguagesRole, "languages" }, + { Roles::EnabledRole, "enabled" }, + { Roles::IsConfigurableRole, "is_configurable" }, + { Roles::ConfigModelRole, "config_model" }, + { Roles::SourceRole, "source" }, + { Roles::PriorityRole, "priority" }, + { Roles::SaveNameRole, "save_name" }, + { Roles::IsLatinModeEnabledRole, "is_latin_mode_enabled" }, + { Roles::LatinModeLayoutRole, "latin_mode_layout" }, + }; +} + +int LayoutListModelBase::role(QString const& roleName) const +{ + auto roles = roleNames(); + for (auto it = roles.keyValueBegin(); it != roles.keyValueEnd(); ++it) { + if ((*it).second == roleName) { + return (*it).first; + } + } + return -1; +} diff --git a/kcms/keyboard/layoutmodel/layout_list_model_fcitx.h b/kcms/keyboard/layoutmodel/layout_list_model_fcitx.h new file mode 100644 --- /dev/null +++ b/kcms/keyboard/layoutmodel/layout_list_model_fcitx.h @@ -0,0 +1,44 @@ +#ifndef LAYOUTLISTMODELFCITX_H +#define LAYOUTLISTMODELFCITX_H + +#include +#include + +#include "layout_list_model_base.h" + +class LayoutListModelFcitx : public QAbstractItemModel, public LayoutListModelBase { + Q_OBJECT + +public: + explicit LayoutListModelFcitx(QObject* parent = nullptr); + + int rowCount(const QModelIndex& parent = QModelIndex()) const override; + + int columnCount(const QModelIndex& parent = QModelIndex()) const override; + + Qt::ItemFlags flags(const QModelIndex& index) const override; + + QModelIndex index(int row, int column = 0, + const QModelIndex& parent = QModelIndex()) const override; + + QModelIndex parent(const QModelIndex& index) const override; + + QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const override; + +private: + void load(); + +private: + struct Layout { + QString save_name; + QString layout_id; + QString description; + QString language; + bool enabled; + }; + + QScopedPointer> m_layouts; + int m_numEnabled = 0; +}; + +#endif diff --git a/kcms/keyboard/layoutmodel/layout_list_model_fcitx.cpp b/kcms/keyboard/layoutmodel/layout_list_model_fcitx.cpp new file mode 100644 --- /dev/null +++ b/kcms/keyboard/layoutmodel/layout_list_model_fcitx.cpp @@ -0,0 +1,149 @@ +#include "layout_list_model_fcitx.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "input_sources.h" + +#include "../fcitx/fcitxqtinputmethodproxy.h" +#include "fcitx_im_config_model.h" + +LayoutListModelFcitx::LayoutListModelFcitx(QObject* parent) + : QAbstractItemModel(parent), + m_layouts(new QVector) +{ + FcitxQtInputMethodItem::registerMetaType(); + + if (InputSources::self()->currentSource() == InputSources::Sources::FcitxSource) { + load(); + } + + // Listen for fcitx dying or becoming alive + QObject::connect(InputSources::self(), &InputSources::currentSourceChanged, + [&](int newSource) { + if (newSource == InputSources::Sources::FcitxSource) { + load(); + } else { + beginResetModel(); + m_layouts->clear(); + endResetModel(); + } + }); +} + +void LayoutListModelFcitx::load() +{ + if (InputSources::self()->currentSource() == InputSources::Sources::FcitxSource) { + beginResetModel(); + FcitxQtInputMethodProxy proxy("org.fcitx.Fcitx", "/inputmethod", + QDBusConnection::sessionBus()); + auto im_list = proxy.iMList(); + + m_layouts->clear(); + m_numEnabled = 0; + for (auto const& im : im_list) { + Layout layout; + layout.save_name = FcitxQtInputMethodItem::saveName(im.uniqueName()); + layout.description = im.name(); + layout.layout_id = im.uniqueName(); + layout.language = im.langCode(); + layout.enabled = im.enabled(); + if (layout.enabled) { + m_numEnabled++; + } + + *m_layouts << layout; + } + endResetModel(); + } +} + +int LayoutListModelFcitx::rowCount(const QModelIndex& parent) const +{ + if (!parent.isValid()) { + return m_layouts->count(); + } + + return 0; +} + +int LayoutListModelFcitx::columnCount(const QModelIndex& parent) const +{ + Q_UNUSED(parent); + return 1; +} + +Qt::ItemFlags LayoutListModelFcitx::flags(const QModelIndex& index) const +{ + if (!index.isValid()) { + return Qt::NoItemFlags; + } + + return QAbstractItemModel::flags(index); +} + +QModelIndex LayoutListModelFcitx::index(int row, + int column, + const QModelIndex& parent) const +{ + if (!hasIndex(row, column, parent)) { + return QModelIndex(); + } + + if (!parent.isValid()) { + if (0 <= row && row < m_layouts->count()) { + return createIndex(row, column, &(*m_layouts)[row]); + } + } + + return QModelIndex(); +} + +QModelIndex LayoutListModelFcitx::parent(const QModelIndex& index) const +{ + Q_UNUSED(index); + return QModelIndex(); +} + +QVariant LayoutListModelFcitx::data(const QModelIndex& index, int role) const +{ + if (!index.isValid()) { + return QVariant(); + } + + Layout* layout = static_cast(index.internalPointer()); + switch (role) { + case Roles::NameRole: + return layout->layout_id; + case Roles::DescriptionRole: + return layout->description; + case Roles::EnabledRole: + return layout->enabled; + case Roles::LanguagesRole: + return layout->language; + case Roles::IsConfigurableRole: + return true; + case Roles::SourceRole: + return InputSources::Sources::FcitxSource; + case Roles::ConfigModelRole: + // TODO: manage memory? + return QVariant::fromValue(new FcitxIMConfigModel(layout->layout_id, nullptr)); + case Qt::DisplayRole: + case Roles::SaveNameRole: + return layout->save_name; + case Roles::ShortNameRole: + if (layout->layout_id.startsWith("fcitx-keyboard-")) { + return layout->layout_id.right(layout->layout_id.size() - 15); + } + return layout->layout_id; + } + + return QVariant(); +} diff --git a/kcms/keyboard/layoutmodel/layout_list_model_selected.h b/kcms/keyboard/layoutmodel/layout_list_model_selected.h new file mode 100644 --- /dev/null +++ b/kcms/keyboard/layoutmodel/layout_list_model_selected.h @@ -0,0 +1,38 @@ +#ifndef LAYOUTLISTMODELSELECTED_H +#define LAYOUTLISTMODELSELECTED_H + +#include + +#include "layout_list_model_base.h" + +class LayoutListModelSelected : public QAbstractListModel, public LayoutListModelBase { + Q_OBJECT + +public: + struct EnabledLayout + { + QString saveName; + bool isLatinModeEnabled; + QString latinModeLayout; + }; + + explicit LayoutListModelSelected(QObject* parent = nullptr); + + // Basic functionality: + int rowCount(const QModelIndex& parent = QModelIndex()) const override; + + QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const override; + + QList enabledLayouts() const; + void setEnabledLayouts(const QList &enabledLayouts); + + void add(QString const& saveName); + void remove(int row); + + void setOrder(QVector const& order); + +private: + QList m_enabledLayouts; +}; + +#endif // LAYOUTLISTMODELSELECTED_H diff --git a/kcms/keyboard/layoutmodel/layout_list_model_selected.cpp b/kcms/keyboard/layoutmodel/layout_list_model_selected.cpp new file mode 100644 --- /dev/null +++ b/kcms/keyboard/layoutmodel/layout_list_model_selected.cpp @@ -0,0 +1,92 @@ +#include "layout_list_model_selected.h" + +#include "input_sources.h" + +#include + +LayoutListModelSelected::LayoutListModelSelected(QObject* parent) + : QAbstractListModel(parent) +{ +} + +int LayoutListModelSelected::rowCount(const QModelIndex& parent) const +{ + if (parent.isValid()) + return 0; + + return m_enabledLayouts.size(); +} + +QVariant LayoutListModelSelected::data(const QModelIndex& index, int role) const +{ + if (!index.isValid()) + return QVariant(); + + switch (role) { + case Roles::EnabledRole: + return true; + + case Roles::SourceRole: + return InputSources::Sources::UnknownSource; + + case Roles::IsConfigurableRole: + return false; + + case Roles::PriorityRole: + return index.row(); + + case Qt::DisplayRole: + case Roles::SaveNameRole: + case Roles::NameRole: + case Roles::DescriptionRole: + return m_enabledLayouts[index.row()].saveName; + + case Roles::IsLatinModeEnabledRole: + return m_enabledLayouts[index.row()].isLatinModeEnabled; + + case Roles::LatinModeLayoutRole: + return m_enabledLayouts[index.row()].latinModeLayout; + } + + return QVariant(); +} + +QList LayoutListModelSelected::enabledLayouts() const +{ + return m_enabledLayouts; +} + +void LayoutListModelSelected::setEnabledLayouts(const QList& enabledLayouts) +{ + beginResetModel(); + m_enabledLayouts = enabledLayouts; + endResetModel(); +} + +void LayoutListModelSelected::add(const QString &saveName) +{ + beginInsertRows(QModelIndex(), rowCount(), rowCount()); + EnabledLayout layout; + layout.saveName = saveName; + layout.isLatinModeEnabled = false; + m_enabledLayouts << layout; + endInsertRows(); +} + +void LayoutListModelSelected::remove(int row) +{ + beginRemoveRows(QModelIndex(), row, row); + m_enabledLayouts.removeAt(row); + endRemoveRows(); +} + +void LayoutListModelSelected::setOrder(const QVector &order) +{ + //emit layoutAboutToBeChanged(QList(), VerticalSortHint); + auto copy = m_enabledLayouts; + for (int i = 0; i < order.size(); ++i) { + m_enabledLayouts[i] = copy[order[i]]; + } + //emit layoutChanged(QList(), VerticalSortHint); + emit dataChanged(index(0), index(rowCount() - 1), {}); +} diff --git a/kcms/keyboard/layoutmodel/layout_list_model_xkb.h b/kcms/keyboard/layoutmodel/layout_list_model_xkb.h new file mode 100644 --- /dev/null +++ b/kcms/keyboard/layoutmodel/layout_list_model_xkb.h @@ -0,0 +1,53 @@ +#ifndef LAYOUTLISTMODEL_H +#define LAYOUTLISTMODEL_H + +#include + +#include "layout_list_model_base.h" +#include "../xkb_rules.h" + +class LayoutListModelXkb : public QAbstractItemModel, public LayoutListModelBase { + Q_OBJECT + +public: + explicit LayoutListModelXkb(QObject* parent = nullptr); + + int rowCount(const QModelIndex& parent = QModelIndex()) const override; + + int columnCount(const QModelIndex& parent = QModelIndex()) const override; + + Qt::ItemFlags flags(const QModelIndex& index) const override; + + QModelIndex index(int row, int column, + const QModelIndex& parent = QModelIndex()) const override; + + QModelIndex parent(const QModelIndex& index) const override; + + QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const override; + +private: + struct Item { + virtual ~Item() = default; + }; + + struct Layout; + struct LayoutVariant : Item { + QString id; + QString description; + QVariantList languages; + int parent_index; + }; + + struct Layout : Item { + QString id; + QString description; + QVariantList languages; + QList variants; + }; + + using LayoutList = QList; + + QScopedPointer m_layouts; +}; + +#endif // LAYOUTLISTMODEL_H diff --git a/kcms/keyboard/layoutmodel/layout_list_model_xkb.cpp b/kcms/keyboard/layoutmodel/layout_list_model_xkb.cpp new file mode 100644 --- /dev/null +++ b/kcms/keyboard/layoutmodel/layout_list_model_xkb.cpp @@ -0,0 +1,152 @@ +#include "layout_list_model_xkb.h" + +#include "../xkb_rules.h" +#include "xkb_layout_config_model.h" +#include "input_sources.h" +#include +#include + +LayoutListModelXkb::LayoutListModelXkb(QObject* parent) + : QAbstractItemModel(parent), + m_layouts(new LayoutList) +{ + for (int i = 0; i < XkbRules::self()->layoutInfos.count(); ++i) { + auto const& layout_info = XkbRules::self()->layoutInfos[i]; + + Layout layout; + layout.id = layout_info->name; + layout.description = layout_info->description; + + for (auto const& lang : layout_info->languages) + layout.languages << lang; + + // add rest of the variants in + for (auto const& var_info : layout_info->variantInfos) { + LayoutVariant var; + var.id = var_info->name; + var.description = var_info->description; + var.parent_index = i; + + for (auto const& lang : var_info->languages) { + var.languages << lang; + } + + layout.variants << var; + } + + *m_layouts << layout; + } +} + +int LayoutListModelXkb::rowCount(const QModelIndex& parent) const +{ + if (parent.column() > 0) { + return 0; + } + + if (!parent.isValid()) { + return m_layouts->count(); + } + + Item* item = static_cast(parent.internalPointer()); + if (Layout* layout = dynamic_cast(item)) { + return layout->variants.count(); + } + + return 0; +} + +int LayoutListModelXkb::columnCount(const QModelIndex& parent) const +{ + Q_UNUSED(parent); + return 1; +} + +Qt::ItemFlags LayoutListModelXkb::flags(const QModelIndex& index) const +{ + if (!index.isValid()) { + return Qt::NoItemFlags; + } + + return QAbstractItemModel::flags(index); +} + +QModelIndex LayoutListModelXkb::index(int row, int column, const QModelIndex& parent) const +{ + if (!hasIndex(row, column, parent)) { + return QModelIndex(); + } + + if (!parent.isValid()) { // it is referring to the top-level element + if (0 <= row && row < m_layouts->count()) { + return createIndex(row, column, &(*m_layouts)[row]); + } + } else { + Layout* parent_item = static_cast(parent.internalPointer()); + if (0 <= row && row < parent_item->variants.count()) { + return createIndex(row, column, &parent_item->variants[row]); + } + } + + return QModelIndex(); +} + +QModelIndex LayoutListModelXkb::parent(const QModelIndex& index) const +{ + if (!index.isValid()) { + return QModelIndex(); + } + + Item* item = static_cast(index.internalPointer()); + if (LayoutVariant* variant = dynamic_cast(item)) { + return createIndex(variant->parent_index, 0, &(*m_layouts)[variant->parent_index]); + } + + return QModelIndex(); +} + +QVariant LayoutListModelXkb::data(const QModelIndex& index, int role) const +{ + if (!index.isValid()) { + return QVariant(); + } + + Item* item = static_cast(index.internalPointer()); + if (LayoutVariant* variant = dynamic_cast(item)) { + switch (role) { + case Roles::ShortNameRole: + case Roles::NameRole: + case Roles::SaveNameRole: + case Qt::DisplayRole: + return QString("%1(%2)").arg((*m_layouts)[variant->parent_index].id, variant->id); + case Roles::DescriptionRole: + return variant->description; + case Roles::LanguagesRole: + return variant->languages; + } + } else if (Layout* layout = dynamic_cast(item)) { + switch (role) { + case Roles::ShortNameRole: + case Roles::NameRole: + case Roles::SaveNameRole: + case Qt::DisplayRole: + return layout->id; + case Roles::DescriptionRole: + return layout->description; + case Roles::LanguagesRole: + return layout->languages; + } + } + + switch (role) { + case Roles::IsConfigurableRole: + return true; + case Roles::SourceRole: + return InputSources::Sources::XkbSource; + case Roles::ConfigModelRole: + // TODO: manage memory? + return QVariant::fromValue(new XkbLayoutConfigModel(XkbRules::self(), nullptr)); + } + + return QVariant(); +} diff --git a/kcms/keyboard/layoutmodel/layout_list_models.h b/kcms/keyboard/layoutmodel/layout_list_models.h new file mode 100644 --- /dev/null +++ b/kcms/keyboard/layoutmodel/layout_list_models.h @@ -0,0 +1,49 @@ +#ifndef LAYOUT_LIST_MODELS_H +#define LAYOUT_LIST_MODELS_H + +#include +#include +#include + +#include "layout_list_model_selected.h" +#include "layout_list_filter_duplicates_proxy_model.h" +#include "layout_list_sort_by_priority_proxy_model.h" +#include "layout_list_current_proxy_model.h" + +class LayoutListModels : public QObject +{ + Q_OBJECT + Q_PROPERTY(int currentLayoutIndex READ currentLayoutIndex WRITE setCurrentLayoutIndex NOTIFY currentLayoutIndexChanged) + + LayoutListModelSelected* m_selected; + LayoutListFilterDuplicatesProxyModel* m_layoutListModel; + LayoutListSortByPriorityProxyModel* m_configuredLayoutListModel; + LayoutListCurrentProxyModel* m_currentLayoutListModel; + QDBusInterface* m_kdedIface, *m_fcitxIface; + int m_currentLayoutIndex; + +public: + LayoutListModels(QObject *parent); + + LayoutListFilterDuplicatesProxyModel *entireLayoutListModel() const; + LayoutListSortByPriorityProxyModel *configuredLayoutListModel() const; + LayoutListCurrentProxyModel *currentLayoutListModel() const; + + int currentLayoutIndex(); + void setCurrentLayoutIndex(int new_index); + Q_INVOKABLE void switchLayout(int new_index); + Q_INVOKABLE void openConfigDialog(); + QString currentIconName(); + + void loadConfig(); + void saveConfig(); + +Q_SIGNALS: + void currentLayoutIndexChanged(); + +public Q_SLOTS: + void setCurrentLayoutByName(QString const& saveName); + void fcitxPropertyChanged(QString const& ifaceName, QVariantMap const& map, QStringList const& invalidated); +}; + +#endif // LAYOUT_LIST_MODELS_H diff --git a/kcms/keyboard/layoutmodel/layout_list_models.cpp b/kcms/keyboard/layoutmodel/layout_list_models.cpp new file mode 100644 --- /dev/null +++ b/kcms/keyboard/layoutmodel/layout_list_models.cpp @@ -0,0 +1,223 @@ +#include "layout_list_models.h" + +#include +#include +#include +#include +#include + +#include "layout_list_concat_proxy_model.h" +#include "layout_list_filter_disabled_proxy_model.h" +#include "layout_list_filter_duplicates_proxy_model.h" +#include "layout_list_filter_source_proxy_model.h" +#include "layout_list_model_fcitx.h" +#include "layout_list_model_selected.h" +#include "layout_list_model_xkb.h" +#include "layout_list_sort_by_priority_proxy_model.h" +#include "layout_list_sort_filter_proxy_model.h" +#include "layout_list_xkb_expand_proxy_model.h" +#include "layout_list_current_proxy_model.h" +#include "input_sources.h" + +LayoutListModels::LayoutListModels(QObject* parent) + : QObject(parent) + , m_kdedIface(new QDBusInterface("org.kde.keyboard", "/Layouts", "org.kde.KeyboardLayouts")) + , m_fcitxIface(new QDBusInterface("org.fcitx.Fcitx", "/inputmethod", "org.freedesktop.DBus.Properties")) +{ + // Setup models + auto xkbModel = new LayoutListModelXkb(this); + auto expanded_xkb = new LayoutListXkbExpandProxyModel(this); + expanded_xkb->setSourceModel(xkbModel); + + auto fcitxModel = new LayoutListModelFcitx(this); + m_selected = new LayoutListModelSelected(this); + + auto concat = new LayoutListConcatProxyModel(this); + concat->addSourceModel(expanded_xkb); + concat->addSourceModel(fcitxModel); + concat->addSourceModel(m_selected); + + auto filterSourceModel = new LayoutListFilterSourceProxyModel(this); + filterSourceModel->setSourceModel(concat); + + auto sortBySaveNameModel = new LayoutListSortFilterProxyModel(this); + sortBySaveNameModel->setSourceModel(filterSourceModel); + sortBySaveNameModel->setSortRole(LayoutListModelBase::Roles::SaveNameRole); + sortBySaveNameModel->sort(0); + sortBySaveNameModel->setDynamicSortFilter(true); + + auto removeDuplicatesModel = new LayoutListFilterDuplicatesProxyModel(this); + m_layoutListModel = removeDuplicatesModel; + removeDuplicatesModel->setSourceModel(sortBySaveNameModel); + + connect(removeDuplicatesModel, &LayoutListFilterDuplicatesProxyModel::itemAdded, + m_selected, &LayoutListModelSelected::add); + + connect(removeDuplicatesModel, &LayoutListFilterDuplicatesProxyModel::itemAdded, + removeDuplicatesModel, &LayoutListFilterDuplicatesProxyModel::invalidate); + + connect(m_selected, &LayoutListModelSelected::modelReset, + removeDuplicatesModel, &LayoutListFilterDuplicatesProxyModel::updateEnabled); + + connect(m_selected, &LayoutListModelSelected::modelReset, + removeDuplicatesModel, &LayoutListFilterDuplicatesProxyModel::missingCountChanged); + + // TODO: make it update without including fcitxdetector here for extensibility + // TODO: make it work without updating the entire model + connect(InputSources::self(), &InputSources::currentSourceChanged, + removeDuplicatesModel, &LayoutListFilterDuplicatesProxyModel::invalidate); + + connect(InputSources::self(), &InputSources::currentSourceChanged, + removeDuplicatesModel, &LayoutListFilterDuplicatesProxyModel::missingCountChanged); + + auto filterDisabledModel = new LayoutListFilterDisabledProxyModel(this); + filterDisabledModel->setSourceModel(removeDuplicatesModel); + + m_configuredLayoutListModel = new LayoutListSortByPriorityProxyModel(this); + m_configuredLayoutListModel->setSourceModel(filterDisabledModel); + + connect(m_configuredLayoutListModel, &LayoutListSortByPriorityProxyModel::enabledOrderChanged, + m_selected, &LayoutListModelSelected::setOrder); + + connect(m_configuredLayoutListModel, &LayoutListSortByPriorityProxyModel::itemRemoved, + m_selected, &LayoutListModelSelected::remove); + + connect(m_configuredLayoutListModel, &LayoutListSortByPriorityProxyModel::itemRemoved, + removeDuplicatesModel, &LayoutListFilterDuplicatesProxyModel::invalidate); + + m_currentLayoutListModel = new LayoutListCurrentProxyModel(this); + m_currentLayoutListModel->setSourceModel(m_configuredLayoutListModel); + + connect(m_kdedIface, SIGNAL(currentLayoutChanged(QString)), this, SLOT(setCurrentLayoutByName(QString))); + connect(m_fcitxIface, SIGNAL(PropertiesChanged(QString, QVariantMap, QStringList)), this, SLOT(fcitxPropertyChanged(QString, QVariantMap, QStringList))); +} + +LayoutListFilterDuplicatesProxyModel *LayoutListModels::entireLayoutListModel() const +{ + return m_layoutListModel; +} + +LayoutListSortByPriorityProxyModel *LayoutListModels::configuredLayoutListModel() const +{ + return m_configuredLayoutListModel; +} + +LayoutListCurrentProxyModel *LayoutListModels::currentLayoutListModel() const +{ + return m_currentLayoutListModel; +} + +int LayoutListModels::currentLayoutIndex() +{ + return m_currentLayoutIndex; +} + +void LayoutListModels::setCurrentLayoutIndex(int new_index) +{ + qDebug() << new_index; + + if (m_currentLayoutIndex != new_index) { + m_currentLayoutIndex = new_index; + emit currentLayoutIndexChanged(); + } +} + +void LayoutListModels::switchLayout(int new_index) +{ + QString name = m_currentLayoutListModel->data( + m_currentLayoutListModel->index(new_index, 0), + LayoutListModelBase::Roles::SaveNameRole).toString(); + m_kdedIface->call("setLayout", name); +} + +void LayoutListModels::openConfigDialog() +{ + KProcess dialog; + dialog << "kcmshell5" << "kcm_keyboard"; + dialog.startDetached(); +} + +QString LayoutListModels::currentIconName() +{ + QDBusMessage msg = QDBusMessage::createMethodCall( + "org.fcitx.Fcitx", + "/StatusNotifierItem", + QLatin1String("org.freedesktop.DBus.Properties"), + QLatin1String("Get")); + msg.setArguments(QVariantList() << "org.kde.StatusNotifierItem" << "IconName"); + QDBusMessage reply = QDBusConnection::sessionBus().call(msg); + QDBusVariant dbusArgs = reply.arguments().first().value(); + return dbusArgs.variant().toString(); +} + +void LayoutListModels::setCurrentLayoutByName(const QString &saveName) +{ + qDebug() << saveName; + int count = m_currentLayoutListModel->rowCount(); + for (int i = 0; i < count; ++i) { + QString name = m_currentLayoutListModel->data( + m_currentLayoutListModel->index(i, 0), + LayoutListModelBase::Roles::SaveNameRole).toString(); + if (name == saveName) { + setCurrentLayoutIndex(i); + return; + } + } + qWarning() << "Cannot set layout" << saveName; +} + +void LayoutListModels::fcitxPropertyChanged(QString const&, QVariantMap const&, QStringList const& invalidated) +{ + qDebug() << invalidated; + if (invalidated.contains("CurrentIM")) { + emit currentLayoutIndexChanged(); + } +} + +void LayoutListModels::loadConfig() +{ + KConfigGroup config( + KSharedConfig::openConfig(QStringLiteral("kxkbrc"), KConfig::NoGlobals), + QStringLiteral("Layout")); + + QString layoutsString = config.readEntry("LayoutList", ""); + QList list; + + for (QString layout : layoutsString.split(',')) { + LayoutListModelSelected::EnabledLayout l; + l.saveName = layout; + l.isLatinModeEnabled = false; + l.latinModeLayout = ""; + + if (layout.startsWith("fcitx:")) { + QString origName = layout.split(":")[1]; + + l.isLatinModeEnabled = config.readEntry(QString("Fcitx%1LatinFallBackEnabled").arg(origName), false); + if (l.isLatinModeEnabled) { + l.latinModeLayout = config.readEntry(QString("Fcitx%1LatinFallBack").arg(origName), "us"); + } + } + + qDebug() << l.saveName << l.isLatinModeEnabled << l.latinModeLayout; + + list << l; + } + + m_selected->setEnabledLayouts(list); + + QDBusMessage reply = m_kdedIface->call("getCurrentLayout"); + setCurrentLayoutByName(reply.arguments().first().toString()); +} + +void LayoutListModels::saveConfig() +{ + KConfigGroup config( + KSharedConfig::openConfig(QStringLiteral("kxkbrc"), KConfig::NoGlobals), + QStringLiteral("Layout")); + + QStringList layouts; + for (LayoutListModelSelected::EnabledLayout enabledLayout : m_selected->enabledLayouts()) { + layouts << enabledLayout.saveName; + } + config.writeEntry("LayoutList", layouts.join(",")); +} diff --git a/kcms/keyboard/layoutmodel/layout_list_sort_by_priority_proxy_model.h b/kcms/keyboard/layoutmodel/layout_list_sort_by_priority_proxy_model.h new file mode 100644 --- /dev/null +++ b/kcms/keyboard/layoutmodel/layout_list_sort_by_priority_proxy_model.h @@ -0,0 +1,27 @@ +#ifndef LAYOUTLISTENABLEDPROXYMODEL_H +#define LAYOUTLISTENABLEDPROXYMODEL_H + +#include +#include + +class LayoutListSortByPriorityProxyModel : public QSortFilterProxyModel, public LayoutListModelBase { + Q_OBJECT +public: + LayoutListSortByPriorityProxyModel(QObject* parent); + + Q_INVOKABLE void applyOrderChanges(); + Q_INVOKABLE void simulateMove(int src, int dst); + Q_INVOKABLE void remove(int idx); + + //bool lessThan(const QModelIndex &source_left, const QModelIndex &source_right) const override; + +Q_SIGNALS: + void enabledOrderChanged(QVector const& newOrder); + void itemRemoved(int idx); + void itemAdded(QString const& saveName); + +private: + QVector m_tempMapping; +}; + +#endif // LAYOUTLISTENABLEDPROXYMODEL_H diff --git a/kcms/keyboard/layoutmodel/layout_list_sort_by_priority_proxy_model.cpp b/kcms/keyboard/layoutmodel/layout_list_sort_by_priority_proxy_model.cpp new file mode 100644 --- /dev/null +++ b/kcms/keyboard/layoutmodel/layout_list_sort_by_priority_proxy_model.cpp @@ -0,0 +1,69 @@ +#include "layout_list_sort_by_priority_proxy_model.h" + +#include + +LayoutListSortByPriorityProxyModel::LayoutListSortByPriorityProxyModel(QObject* parent) + : QSortFilterProxyModel(parent) +{ + setSortRole(Roles::PriorityRole); + sort(0); +} + +void LayoutListSortByPriorityProxyModel::applyOrderChanges() +{ + if (!m_tempMapping.empty()) { + qDebug() << "applyorderchanges" << m_tempMapping; + emit enabledOrderChanged(m_tempMapping); + m_tempMapping.clear(); + } +} + +void LayoutListSortByPriorityProxyModel::simulateMove(int src, int dst) +{ + qDebug() << src << dst; + if (src < 0 || src >= rowCount() || dst < 0 || dst >= rowCount()) { + return; + } + + int const modelTo = dst + (dst > src); + if (beginMoveRows(QModelIndex(), src, src, QModelIndex(), modelTo)) { + if (m_tempMapping.empty()) { + m_tempMapping.resize(sourceModel()->rowCount()); + std::iota(m_tempMapping.begin(), m_tempMapping.end(), 0); + } + m_tempMapping.move(src, dst); + qDebug() << m_tempMapping; + endMoveRows(); + } +} + +void LayoutListSortByPriorityProxyModel::remove(int idx) +{ + emit itemRemoved(idx); +} +/* +bool LayoutListSortByPriorityProxyModel::lessThan(const QModelIndex &source_left, const QModelIndex &source_right) const +{ + bool result; + if (m_tempMapping.empty()) { + int left = sourceModel()->data(source_left, Roles::PriorityRole).toInt(); + int right = sourceModel()->data(source_right, Roles::PriorityRole).toInt(); + result = left < right; + } + else { + result = m_tempMapping[source_left.row()] < m_tempMapping[source_right.row()]; + } + + QString left, right; + left = sourceModel()->data(source_left, Roles::NameRole).toString(); + right = sourceModel()->data(source_right, Roles::NameRole).toString(); + if (result) { + qDebug() << left << "<" << right; + } + else { + qDebug() << right << "<" << left; + } + + return result; +} +*/ diff --git a/kcms/keyboard/layoutmodel/layout_list_sort_filter_proxy_model.h b/kcms/keyboard/layoutmodel/layout_list_sort_filter_proxy_model.h new file mode 100644 --- /dev/null +++ b/kcms/keyboard/layoutmodel/layout_list_sort_filter_proxy_model.h @@ -0,0 +1,14 @@ +#ifndef LAYOUT_LIST_SORT_FILTER_PROXY_MODEL_H +#define LAYOUT_LIST_SORT_FILTER_PROXY_MODEL_H + +#include "layout_list_model_base.h" +#include +#include + +class LayoutListSortFilterProxyModel : public QSortFilterProxyModel, public LayoutListModelBase { + Q_OBJECT +public: + LayoutListSortFilterProxyModel(QObject* parent); +}; + +#endif // LAYOUT_LIST_SORT_FILTER_PROXY_MODEL_H diff --git a/kcms/keyboard/layoutmodel/layout_list_sort_filter_proxy_model.cpp b/kcms/keyboard/layoutmodel/layout_list_sort_filter_proxy_model.cpp new file mode 100644 --- /dev/null +++ b/kcms/keyboard/layoutmodel/layout_list_sort_filter_proxy_model.cpp @@ -0,0 +1,6 @@ +#include "layout_list_sort_filter_proxy_model.h" + +LayoutListSortFilterProxyModel::LayoutListSortFilterProxyModel(QObject* parent) + : QSortFilterProxyModel(parent) +{ +} diff --git a/kcms/keyboard/layoutmodel/layout_list_xkb_expand_proxy_model.h b/kcms/keyboard/layoutmodel/layout_list_xkb_expand_proxy_model.h new file mode 100644 --- /dev/null +++ b/kcms/keyboard/layoutmodel/layout_list_xkb_expand_proxy_model.h @@ -0,0 +1,14 @@ +#ifndef EXPAND_LAYOUT_LIST_PROXY_MODEL_H +#define EXPAND_LAYOUT_LIST_PROXY_MODEL_H + +#include + +#include "layout_list_model_xkb.h" + +class LayoutListXkbExpandProxyModel : public KDescendantsProxyModel, public LayoutListModelBase { + Q_OBJECT +public: + explicit LayoutListXkbExpandProxyModel(QObject* parent = nullptr); +}; + +#endif // EXPAND_LAYOUT_LIST_PROXY_MODEL_H diff --git a/kcms/keyboard/layoutmodel/layout_list_xkb_expand_proxy_model.cpp b/kcms/keyboard/layoutmodel/layout_list_xkb_expand_proxy_model.cpp new file mode 100644 --- /dev/null +++ b/kcms/keyboard/layoutmodel/layout_list_xkb_expand_proxy_model.cpp @@ -0,0 +1,7 @@ +#include "layout_list_xkb_expand_proxy_model.h" + +LayoutListXkbExpandProxyModel::LayoutListXkbExpandProxyModel(QObject *parent) + : KDescendantsProxyModel(parent) +{ + setDisplayAncestorData(true); +} diff --git a/kcms/keyboard/layoutmodel/xkb_layout_config_model.h b/kcms/keyboard/layoutmodel/xkb_layout_config_model.h new file mode 100644 --- /dev/null +++ b/kcms/keyboard/layoutmodel/xkb_layout_config_model.h @@ -0,0 +1,36 @@ +#ifndef XKB_LAYOUT_CONFIG_MODEL_H +#define XKB_LAYOUT_CONFIG_MODEL_H + +#include + +class XkbRules; + +class XkbLayoutConfigModel : public QAbstractItemModel +{ + Q_OBJECT +public: + XkbLayoutConfigModel(XkbRules* rules, QObject* parent); + + QModelIndex index(int row, int column, const QModelIndex &parent) const override; + QModelIndex parent(const QModelIndex &child) const override; + int rowCount(const QModelIndex &parent) const override; + int columnCount(const QModelIndex &parent) const override; + QVariant data(const QModelIndex &index, int role) const override; + + QHash roleNames() const override; + + Q_INVOKABLE void save() const; + +private: + XkbRules* m_rules; + + struct Roles { + enum { + DescriptionRole = Qt::UserRole + 1, + }; + }; +}; + +Q_DECLARE_METATYPE(XkbLayoutConfigModel*) + +#endif // XKB_LAYOUT_CONFIG_MODEL_H diff --git a/kcms/keyboard/layoutmodel/xkb_layout_config_model.cpp b/kcms/keyboard/layoutmodel/xkb_layout_config_model.cpp new file mode 100644 --- /dev/null +++ b/kcms/keyboard/layoutmodel/xkb_layout_config_model.cpp @@ -0,0 +1,60 @@ +#include "xkb_layout_config_model.h" + +#include "../xkb_rules.h" +#include + +XkbLayoutConfigModel::XkbLayoutConfigModel(XkbRules* rules, QObject* parent) + : QAbstractItemModel(parent) + , m_rules(rules) +{ +} + +QModelIndex XkbLayoutConfigModel::index(int row, int column, const QModelIndex&) const +{ + return createIndex(row, column, quintptr(row)); +} + +QModelIndex XkbLayoutConfigModel::parent(const QModelIndex&) const +{ + return QModelIndex(); +} + +int XkbLayoutConfigModel::rowCount(const QModelIndex& parent) const +{ + if (parent.isValid()) { + return 0; + } + return m_rules->optionGroupInfos.size(); +} + +int XkbLayoutConfigModel::columnCount(const QModelIndex& parent) const +{ + if (parent.isValid()) { + return 0; + } + return m_rules->optionGroupInfos.size(); +} + +QVariant XkbLayoutConfigModel::data(const QModelIndex& index, int role) const +{ + if (!index.isValid()) { + return QVariant(); + } + + if (role == Roles::DescriptionRole) { + return m_rules->optionGroupInfos[index.row()]->description; + } + return QVariant(); +} + +QHash XkbLayoutConfigModel::roleNames() const +{ + return { + { Roles::DescriptionRole, "description" } + }; +} + +void XkbLayoutConfigModel::save() const +{ + qDebug() << "save"; +} diff --git a/kcms/keyboard/layouts_menu.h b/kcms/keyboard/layouts_menu.h deleted file mode 100644 --- a/kcms/keyboard/layouts_menu.h +++ /dev/null @@ -1,56 +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. - */ - -#ifndef LAYOUTS_MENU_H_ -#define LAYOUTS_MENU_H_ - -#include -#include - -class QAction; -class KeyboardConfig; -class Flags; -struct Rules; -class QActionGroup; -struct LayoutUnit; - -class LayoutsMenu : public QObject -{ - Q_OBJECT - -public: - LayoutsMenu(const KeyboardConfig& keyboardConfig, const Rules& rules, Flags& flags); - ~LayoutsMenu() override; - - QList contextualActions(); - static int switchToLayout(const LayoutUnit& layoutUnit, const KeyboardConfig& keyboardConfig); - -private Q_SLOTS: - void actionTriggered(QAction* action); - -private: - const QIcon getFlag(const QString& layout) const; - QAction* createAction(const LayoutUnit& layoutUnit) const; - - const KeyboardConfig& keyboardConfig; - const Rules& rules; - Flags& flags; - QActionGroup* actionGroup; -}; - -#endif /* LAYOUTS_MENU_H_ */ diff --git a/kcms/keyboard/layouts_menu.cpp b/kcms/keyboard/layouts_menu.cpp deleted file mode 100644 --- a/kcms/keyboard/layouts_menu.cpp +++ /dev/null @@ -1,140 +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. - */ - -#include "layouts_menu.h" -#include "debug.h" - -#include -#include - -#include - -#include "keyboard_config.h" -#include "x11_helper.h" -#include "xkb_helper.h" -#include "flags.h" - - -LayoutsMenu::LayoutsMenu(const KeyboardConfig& keyboardConfig_, const Rules& rules_, Flags& flags_): - keyboardConfig(keyboardConfig_), - rules(rules_), - flags(flags_), - actionGroup(NULL) -{ -} - -LayoutsMenu::~LayoutsMenu() -{ - delete actionGroup; -} - -const QIcon LayoutsMenu::getFlag(const QString& layout) const -{ - return keyboardConfig.isFlagShown() ? flags.getIcon(layout) : QIcon(); -} - -void LayoutsMenu::actionTriggered(QAction* action) -{ - QString data = action->data().toString(); - if( data == QLatin1String("config") ) { - QStringList args; - args << QStringLiteral("--args=--tab=layouts"); - args << QStringLiteral("kcm_keyboard"); - KToolInvocation::kdeinitExec(QStringLiteral("kcmshell5"), args); - } - else { - LayoutUnit layoutUnit(LayoutUnit(action->data().toString())); - switchToLayout(layoutUnit, keyboardConfig); - } -} - -int LayoutsMenu::switchToLayout(const LayoutUnit& layoutUnit, const KeyboardConfig& keyboardConfig) -{ - QList layouts = X11Helper::getCurrentLayouts().layouts; - - bool res; - if( layouts.contains(layoutUnit) ) { - res = X11Helper::setLayout(layoutUnit); - } - else if ( keyboardConfig.layouts.contains(layoutUnit) ) { - QList layouts(keyboardConfig.getDefaultLayouts()); - layouts.removeLast(); - layouts.append(layoutUnit); - XkbHelper::initializeKeyboardLayouts(layouts); - res = X11Helper::setLayout(layoutUnit); - } - else { - qCWarning(KCM_KEYBOARD) << "switchToLayout with unknown layout" << layoutUnit.toString(); - res = -1; - } - return res; -} - -QAction* LayoutsMenu::createAction(const LayoutUnit& layoutUnit) const -{ - QString menuText = Flags::getFullText(layoutUnit, keyboardConfig, &rules); - QAction* action = new QAction(getFlag(layoutUnit.layout), menuText, actionGroup); - action->setData(layoutUnit.toString()); - //FIXME: tooltips don't work on dbusmenus??? -// if( ! layoutUnit.getShortcut().isEmpty() ) { -// action->setToolTip(layoutUnit.getShortcut().toString()); -// } - return action; -} - -QList LayoutsMenu::contextualActions() -{ - if( actionGroup ) { - disconnect(actionGroup, &QActionGroup::triggered, this, &LayoutsMenu::actionTriggered); - delete actionGroup; - } - actionGroup = new QActionGroup(this); - - X11Helper::getLayoutsList(); //UGLY: seems to be more reliable with extra call - QList currentLayouts = X11Helper::getLayoutsList(); - foreach(const LayoutUnit& layoutUnit, currentLayouts) { - QAction* action = createAction(layoutUnit); - actionGroup->addAction(action); - } - - if( keyboardConfig.configureLayouts ) { - QList extraLayouts = keyboardConfig.layouts; - foreach(const LayoutUnit& layoutUnit, currentLayouts) { - extraLayouts.removeOne(layoutUnit); - } - if( extraLayouts.size() > 0 ) { - QAction* separator = new QAction(actionGroup); - separator->setSeparator(true); - actionGroup->addAction(separator); - - foreach(const LayoutUnit& layoutUnit, extraLayouts) { - QAction* action = createAction(layoutUnit); - actionGroup->addAction(action); - } - } - } - - QAction* separator = new QAction(actionGroup); - separator->setSeparator(true); - actionGroup->addAction(separator); - QAction* configAction = new QAction(QIcon::fromTheme(QStringLiteral("configure")), i18n("Configure Layouts..."), actionGroup); - actionGroup->addAction(configAction); - configAction->setData("config"); - connect(actionGroup, &QActionGroup::triggered, this, &LayoutsMenu::actionTriggered); - return actionGroup->actions(); -} diff --git a/kcms/keyboard/pics/CMakeLists.txt b/kcms/keyboard/pics/CMakeLists.txt deleted file mode 100644 --- a/kcms/keyboard/pics/CMakeLists.txt +++ /dev/null @@ -1 +0,0 @@ -install( FILES epo.png DESTINATION ${KDE_INSTALL_DATADIR}/kcmkeyboard/pics ) diff --git a/kcms/keyboard/pics/epo.png b/kcms/keyboard/pics/epo.png deleted file mode 100644 index a8ed2943810dcbdf62c3456b115bae749b6dfe8c..0000000000000000000000000000000000000000 GIT binary patch literal 0 Hc$@VLY)c(Zq*cP4k1@cQ|kjg5{i&P)C}{cb+be@lN$cR|O5oc$KlcUbM;rL$c} zoO`;(atqI2lK&xqJzh@Zlh(ceHSvw^jT0wM{P7`qiNPO9$uyzYA!`~sH%torYjTC3 Y!E3Kt@gFHAkXINyUHx3vIVCg!0Bep~LI3~& 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-temrminals - qi::rulename; - qi::ruledescription; - qi::ruleinput; - - //non-teminals for shape - qi::ruleshape; - qi::ruleshapeDef; - qi::ruleshapeC; - qi::ruleset; - qi::rulesetap; - qi::ruleseta; - qi::rulecornerRadius; - qi::rulecordinatea; - qi::rulecordinates; - - //non-teminals for key - qi::rulekeygap; - qi::rulekeyName; - qi::rulekeyShape; - qi::rulekeyColor; - qi::rulekeyDesc; - qi::rulekeys; - - qi::rulerow; - - qi::rulesection; - - //non-teminals 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(); - - //functionsfor geometry - void setGeomShape(std::string n); - void getName(std::string n); - void getDescription(std::string n); - - //functions for alingment - 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(QStringLiteral("\n")); - int includeLine = -1; - QString includeLineStr; - QString startLine = lines[0]; - for (int i = 0; i < lines.size(); i++) { - includeLineStr = lines[i]; - lines[i] = lines[i].remove(QStringLiteral(" ")); - lines[i] = lines[i].remove(QStringLiteral("\r")); - if (lines[i].startsWith(QLatin1String("include"))) { - includeLine = i; - break; - } - } - if (includeLine == -1) { - return geometry; - } - geometry = geometry.remove(includeLineStr); - lines[includeLine] = lines[includeLine].remove(QStringLiteral("include")); - lines[includeLine] = lines[includeLine].remove(QStringLiteral("\"")); - lines[includeLine] = lines[includeLine].remove(QStringLiteral(")")); - if (lines[includeLine].contains(QStringLiteral("("))) { - QString includeFile = lines[includeLine].split(QStringLiteral("("))[0]; - QString includeGeom = lines[includeLine].split(QStringLiteral("("))[1]; - qCDebug(KEYBOARD_PREVIEW) << "looking to include " << "geometryName" << includeGeom << "in" << includeFile; - QString includeStr = getGeometry(includeFile, includeGeom); - includeStr = getGeometryStrContent(includeStr); - geometry = geometry.remove(startLine); - geometry = geometry.prepend(includeStr); - geometry = geometry.prepend(startLine); - includeGeometry(geometry); - - } - return geometry; -} - -QString getGeometryStrContent(QString geometryStr) -{ - int k = geometryStr.indexOf(QStringLiteral("{")); - 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 = 0); - ~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 give 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 = temp.remove(QStringLiteral(" ")); - temp = temp.remove(QStringLiteral("\n")); - temp = temp.remove(QStringLiteral("\"")); - temp = temp.remove(QStringLiteral(">")); - temp = temp.remove(QStringLiteral("<")); - temp = temp.remove(QStringLiteral(";")); - temp = temp.remove(QStringLiteral("}")); - temp = 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(QStringLiteral("=")); - - 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(QStringLiteral("=")); - - 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(QStringLiteral("=")); - - 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(); - 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 = 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 + " "; - } - -// 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(QStringLiteral("\"")); - symbolCont = symbolCont.mid(index); - index = symbolCont.indexOf(QStringLiteral("{")); - symbolCont = symbolCont.left(index); - symbolCont = 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(QStringLiteral("(")); - 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/tests/CMakeLists.txt b/kcms/keyboard/tests/CMakeLists.txt deleted file mode 100644 --- a/kcms/keyboard/tests/CMakeLists.txt +++ /dev/null @@ -1,107 +0,0 @@ -macro(KEYBOARD_DAEMON_UNIT_TESTS _testname) - add_executable(${_testname}_test ${_testname}_test.cpp ../${_testname}.cpp ../debug.cpp) - 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::KDELibs4Support - ${X11_Xkbfile_LIB} - ${X11_LIBRARIES} -) -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::KDELibs4Support - ${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) -add_test(NAME kcm-keyboard-flags_test COMMAND flags_test) -target_link_libraries(flags_test - Qt5::Concurrent - Qt5::X11Extras - Qt5::Xml - Qt5::Test - KF5::I18n - KF5::Plasma - KF5::KDELibs4Support - XCB::XCB - XCB::XKB - ${X11_Xkbfile_LIB} - ${X11_LIBRARIES} -) - -configure_file(${CMAKE_CURRENT_SOURCE_DIR}/config/base.1.1.xml ${CMAKE_CURRENT_BINARY_DIR}/config/base.1.1.xml COPYONLY) -configure_file(${CMAKE_CURRENT_SOURCE_DIR}/config/base.bad.xml ${CMAKE_CURRENT_BINARY_DIR}/config/base.bad.xml COPYONLY) -configure_file(${CMAKE_CURRENT_SOURCE_DIR}/config/base.xml ${CMAKE_CURRENT_BINARY_DIR}/config/base.xml COPYONLY) - -if( X11_XTest_FOUND ) - add_executable(keyboard_daemon_test keyboard_daemon_test.cpp ../keyboard_daemon.cpp ../layout_memory.cpp ../layout_memory_persister.cpp ../flags.cpp ../udev_helper.cpp ../x11_helper.cpp ../xkb_helper.cpp ../xinput_helper.cpp ../layout_tray_icon.cpp ../keyboard_config.cpp ../xkb_rules.cpp ../keyboard_hardware.cpp ../bindings.cpp ../layouts_menu.cpp ../debug.cpp) - add_test(NAME kcm-keyboard-keyboard_daemon_test COMMAND keyboard_daemon_test) - add_dependencies(keyboard_daemon_test kded_keyboard) - ecm_mark_nongui_executable(keyboard_daemon_test) - ecm_mark_as_test(keyboard_daemon_test) - target_link_libraries(keyboard_daemon_test - Qt5::Concurrent - Qt5::X11Extras - Qt5::Xml - Qt5::Test - KF5::ConfigCore - KF5::CoreAddons - KF5::DBusAddons - KF5::Plasma - KF5::KDELibs4Support - KF5::GlobalAccel - XCB::XCB - XCB::XKB - ${X11_Xkbfile_LIB} - ${X11_XTest_LIB} - ${X11_LIBRARIES} -) - if (HAVE_XINPUT) - target_link_libraries(keyboard_daemon_test ${X11_Xinput_LIB}) - endif() - - if (HAVE_UDEV) - target_link_libraries(keyboard_daemon_test ${UDEV_LIBS}) - endif() -endif() diff --git a/kcms/keyboard/tests/config/base.1.1.xml b/kcms/keyboard/tests/config/base.1.1.xml deleted file mode 100644 --- a/kcms/keyboard/tests/config/base.1.1.xml +++ /dev/null @@ -1,68 +0,0 @@ - - - - - - - pc101 - Generic 101-key PC - Generic - - - - - - - us - USA - USA - eng - - - - - chr - Cherokee - chr - - - chr - Cherokee2 - - - - bad - Bad Variant Missing configItem tag - chr - - - - - - tw - - zh - Taiwanese - - fox - - - - - - - - - grp - Key(s) to change layout - - - - - - \ No newline at end of file diff --git a/kcms/keyboard/tests/config/base.bad.xml b/kcms/keyboard/tests/config/base.bad.xml deleted file mode 100644 --- a/kcms/keyboard/tests/config/base.bad.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/kcms/keyboard/tests/config/base.xml b/kcms/keyboard/tests/config/base.xml deleted file mode 100644 --- a/kcms/keyboard/tests/config/base.xml +++ /dev/null @@ -1,48 +0,0 @@ - - - - - - - pc101 - Generic 101-key PC - Generic - - - - - - - us - USA - USA - eng - - - - - chr - Cherokee - chr - - - - - - - - - - grp - Key(s) to change layout - - - - - - \ No newline at end of file diff --git a/kcms/keyboard/tests/flags_test.cpp b/kcms/keyboard/tests/flags_test.cpp deleted file mode 100644 --- a/kcms/keyboard/tests/flags_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 - -#include "../flags.h" -#include "../xkb_rules.h" -#include "../keyboard_config.h" - - -static QImage image(const QIcon& icon) { - return icon.pixmap(QSize(16,16), QIcon::Normal, QIcon::On).toImage(); -} - -class FlagsTest : public QObject -{ - Q_OBJECT - - Flags* flags; - const Rules* rules; - -private Q_SLOTS: - void initTestCase() { - flags = new Flags(); - rules = NULL; - } - - void cleanupTestCase() { - delete flags; - delete rules; - } - - void testRules() { - QVERIFY( flags != NULL ); - - QVERIFY( ! flags->getTransparentPixmap().isNull() ); - - const QIcon iconUs(flags->getIcon(QStringLiteral("us"))); - QVERIFY( ! iconUs.isNull() ); - QVERIFY( flags->getIcon("--").isNull() ); - - KeyboardConfig keyboardConfig; - LayoutUnit layoutUnit(QStringLiteral("us")); - LayoutUnit layoutUnit1(QStringLiteral("us"), QStringLiteral("intl")); - layoutUnit1.setDisplayName(QStringLiteral("usi")); - LayoutUnit layoutUnit2(QStringLiteral("us"), QStringLiteral("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)") ); - QCOMPARE( flags->getLongText(layoutUnit2, rules), QString("other") ); - - rules = NULL; // when no rules found - QCOMPARE( flags->getLongText(layoutUnit1, rules), QString("us - intl") ); - - flags->clearCache(); - } - -// void loadRulesBenchmark() { -// QBENCHMARK { -// Flags* flags = new Flags(); -// delete flags; -// } -// } - -}; - -// need GUI for xkb protocol in xkb_rules.cpp -QTEST_MAIN(FlagsTest) - -#include "flags_test.moc" 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/tests/iso_codes_test.cpp b/kcms/keyboard/tests/iso_codes_test.cpp deleted file mode 100644 --- a/kcms/keyboard/tests/iso_codes_test.cpp +++ /dev/null @@ -1,74 +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 "../iso_codes.h" - -class IsoCodesTest : public QObject -{ - Q_OBJECT - - IsoCodes* isoCodes; - -private Q_SLOTS: - void initTestCase() { -// isoCodes = new IsoCodes(IsoCodes::iso_639); - isoCodes = new IsoCodes(IsoCodes::iso_639_3); - } - - void cleanupTestCase() { - delete isoCodes; - } - - void testIsoCodes() { - QVERIFY( isoCodes != NULL ); - QVERIFY( ! isoCodes->getEntryList().isEmpty() ); -// const IsoCodeEntry* isoEntry = isoCodes->getEntry(IsoCodes::attr_iso_639_2T_code, "eng"); - const IsoCodeEntry* isoEntry = isoCodes->getEntry(IsoCodes::attr_iso_639_3_id, QStringLiteral("eng")); - QVERIFY( isoEntry != NULL ); - QVERIFY( ! isoEntry->empty() ); -// QCOMPARE( isoEntry->value(IsoCodes::attr_iso_639_2T_code), QString("eng") ); -// QCOMPARE( isoEntry->value(IsoCodes::attr_iso_639_2B_code), QString("eng") ); -// QCOMPARE( isoEntry->value(IsoCodes::attr_iso_639_1_code), QString("en") ); - QCOMPARE( isoEntry->value("name"), QString("English") ); -// QCOMPARE( isoEntry->value("status"), QString("Active") ); - } - - void testIso639_3_Codes() { - QVERIFY( isoCodes != NULL ); - QVERIFY( ! isoCodes->getEntryList().isEmpty() ); - const IsoCodeEntry* isoEntry = isoCodes->getEntry(IsoCodes::attr_iso_639_3_id, QStringLiteral("ant")); - QVERIFY( isoEntry != NULL ); - QVERIFY( ! isoEntry->empty() ); - QVERIFY( isoEntry->value("name") != QString("ant") ); - QCOMPARE( isoEntry->value("name"), QString("Antakarinya") ); - } - - void loadIsoCodesBenchmark() { - QBENCHMARK { - IsoCodes* isoCodes = new IsoCodes(IsoCodes::iso_639_3); - delete isoCodes; - } - } - -}; - -QTEST_MAIN(IsoCodesTest) - -#include "iso_codes_test.moc" diff --git a/kcms/keyboard/tests/keyboard_daemon_test.cpp b/kcms/keyboard/tests/keyboard_daemon_test.cpp deleted file mode 100644 --- a/kcms/keyboard/tests/keyboard_daemon_test.cpp +++ /dev/null @@ -1,100 +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 -#include - -#include "../flags.h" -#include "../xkb_rules.h" -#include "../keyboard_config.h" -#include "../keyboard_daemon.h" - - -class KeyboardDaemonTest : public QObject -{ - Q_OBJECT - - KeyboardDaemon* keyboardDaemon; -// KApplication* kapplication; - -private Q_SLOTS: - void initTestCase() { -// kapplication = new KApplication(); -// const KAboutData* kAboutData = new KAboutData(i18n("a").toLatin1(), i18n("a").toLatin1(), KLocalizedString(), i18n("a").toLatin1()); -// KCmdLineArgs::init(kAboutData); - keyboardDaemon = new KeyboardDaemon(this, QList()); - } - - void cleanupTestCase() { - delete keyboardDaemon; -// delete kapplication; - } - - void testDaemon() { - QVERIFY( keyboardDaemon != 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.showFlag = true; -// const QIcon iconUsFlag = flags->getIconWithText(layoutUnit, keyboardConfig); -// QVERIFY( ! iconUsFlag.isNull() ); -// QCOMPARE( image(iconUsFlag), image(iconUs) ); -// -// keyboardConfig.showFlag = false; -// 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(); -// QCOMPARE( flags->getLongText(layoutUnit, rules), QString("USA") ); -// QVERIFY( flags->getLongText(layoutUnit1, rules).startsWith("USA - International") ); -// QCOMPARE( flags->getLongText(layoutUnit2, rules), QString("USA - other") ); -// -// flags->clearCache(); - } - -// void loadRulesBenchmark() { -// QBENCHMARK { -// Flags* flags = new Flags(); -// delete flags; -// } -// } - -}; - -// need GUI for xkb protocol in xkb_rules.cpp -QTEST_MAIN(KeyboardDaemonTest) - -#include "keyboard_daemon_test.moc" diff --git a/kcms/keyboard/tests/layout_memory_persister_test.cpp b/kcms/keyboard/tests/layout_memory_persister_test.cpp deleted file mode 100644 --- a/kcms/keyboard/tests/layout_memory_persister_test.cpp +++ /dev/null @@ -1,158 +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 - -#include "../layout_memory_persister.h" -#include "../layout_memory.h" -#include "../keyboard_config.h" - - -class TestLayoutMemory: public LayoutMemory { -public: - TestLayoutMemory(const KeyboardConfig& keyboardConfig): - LayoutMemory(keyboardConfig) {} - QMap& getLayoutMap() { return layoutMap; } -}; - -class LayoutMemoryPersisterTest : public QObject -{ - Q_OBJECT - - QString path; - KeyboardConfig keyboardConfig; - TestLayoutMemory* layoutMemory; - LayoutMemoryPersister* layoutMemoryPersister; - - const LayoutUnit layoutUnit1; - const LayoutUnit layoutUnit2; - const LayoutUnit layoutUnit3; - - -public: - LayoutMemoryPersisterTest(): - layoutUnit1("xx"), - layoutUnit2("yy", "var1"), - layoutUnit3("zz", "var2") - {} - -private Q_SLOTS: - void initTestCase() { - path = "keyboard_memory_test.xml"; - QFile(path).remove(); - - layoutMemory = new TestLayoutMemory(keyboardConfig); - layoutMemoryPersister = new LayoutMemoryPersister(*layoutMemory); - -// QFile(path).remove(); - } - - void cleanupTestCase() { - delete layoutMemoryPersister; - delete layoutMemory; - } - - void testSaveNA() { - QFile file(path); - - keyboardConfig.switchingPolicy = KeyboardConfig::SWITCH_POLICY_WINDOW; - QVERIFY( ! layoutMemoryPersister->saveToFile(file) ); - QVERIFY(QFile(path).size() == 0); - - QVERIFY( ! layoutMemoryPersister->restoreFromFile(file) ); - } - - void testSaveGlobal() { - QFile file(path); - - keyboardConfig.switchingPolicy = KeyboardConfig::SWITCH_POLICY_GLOBAL; - layoutMemoryPersister->setGlobalLayout(layoutUnit1); - QVERIFY( layoutMemoryPersister->saveToFile(file) ); - QVERIFY(QFile(path).size() > 0); -// file.close(); - - keyboardConfig.layouts.clear(); - - QVERIFY( layoutMemoryPersister->restoreFromFile(file) ); - QVERIFY( !layoutMemoryPersister->getGlobalLayout().isValid() ); - -// file.close(); - keyboardConfig.layouts << layoutUnit1; - QVERIFY( layoutMemoryPersister->restoreFromFile(file) ); - QVERIFY( layoutUnit1.isValid() ); - QVERIFY( layoutMemoryPersister->getGlobalLayout().isValid() ); - QCOMPARE( layoutMemoryPersister->getGlobalLayout(), layoutUnit1); - } - - void testSaveByApp() { - QFile file(path); - - keyboardConfig.switchingPolicy = KeyboardConfig::SWITCH_POLICY_APPLICATION; - - layoutMemoryPersister->setGlobalLayout(LayoutUnit()); - layoutMemory->getLayoutMap().clear(); - - keyboardConfig.layouts.clear(); - keyboardConfig.layouts << layoutUnit1 << layoutUnit2; - - LayoutSet layoutSet1; - layoutSet1.layouts << layoutUnit1 << layoutUnit2; - layoutSet1.currentLayout = layoutUnit1; - layoutMemory->getLayoutMap().insert(QString("app1"), layoutSet1); - - LayoutSet layoutSet2; - layoutSet2.layouts << layoutUnit2 << layoutUnit1 << layoutUnit3; - layoutSet2.currentLayout = layoutUnit2; - layoutMemory->getLayoutMap().insert(QString("app2"), layoutSet2); - - QVERIFY( layoutMemoryPersister->saveToFile(file) ); - QVERIFY(QFile(path).size() > 0); - file.close(); - - layoutMemory->getLayoutMap().clear(); - QVERIFY( ! layoutMemory->getLayoutMap().value("app1").isValid() ); - QVERIFY( ! layoutMemory->getLayoutMap().value("app2").isValid() ); - - QVERIFY( layoutMemoryPersister->restoreFromFile(file) ); - QVERIFY( ! layoutMemoryPersister->getGlobalLayout().isValid() ); - QCOMPARE( layoutMemory->getLayoutMap().value("app1"), layoutSet1 ); - QVERIFY( ! layoutMemory->getLayoutMap().value("app2").isValid() ); - - keyboardConfig.layouts << layoutUnit3; - - file.close(); - QVERIFY( layoutMemoryPersister->restoreFromFile(file) ); - QVERIFY( ! layoutMemoryPersister->getGlobalLayout().isValid() ); - QCOMPARE( layoutMemory->getLayoutMap().value("app1"), layoutSet1 ); - QCOMPARE( layoutMemory->getLayoutMap().value("app2"), layoutSet2 ); - } - -// void layoutMemroyPersisterBenchmark() { -// QBENCHMARK { -// //TODO: generate big map -// layoutMemoryPersister->save(); -// layoutMemoryPersister->restore(); -// } -// } - -}; - -QTEST_MAIN(LayoutMemoryPersisterTest) - -#include "layout_memory_persister_test.moc" diff --git a/kcms/keyboard/tests/xkb_rules_test.cpp b/kcms/keyboard/tests/xkb_rules_test.cpp deleted file mode 100644 --- a/kcms/keyboard/tests/xkb_rules_test.cpp +++ /dev/null @@ -1,237 +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 "../xkb_rules.h" - -#include -#include - -static const Rules::ExtrasFlag readExtras = Rules::NO_EXTRAS; - -class RulesTest : public QObject -{ - Q_OBJECT - - Rules* rules; - -private Q_SLOTS: - void initTestCase() { - rules = Rules::readRules(readExtras); - } - - void cleanupTestCase() { - delete rules; - } - - void testRules() { - QVERIFY( rules != NULL ); - QVERIFY( rules->modelInfos.size() > 0 ); - QVERIFY( rules->layoutInfos.size() > 0 ); - QVERIFY( rules->optionGroupInfos.size() > 0 ); - } - - void testModel() { - foreach(const ModelInfo* modelInfo, rules->modelInfos) { - QVERIFY( modelInfo != NULL); - QVERIFY( modelInfo->name.length() > 0 ); - QVERIFY( modelInfo->description.length() > 0 ); -// QVERIFY( ! modelInfo->vendor.isEmpty() ); - } - } - - void testLayouts() { - foreach(const LayoutInfo* layoutInfo, rules->layoutInfos) { - QVERIFY( layoutInfo != NULL); - QVERIFY( ! layoutInfo->name.isEmpty() ); -// const char* desc = layoutInfo->name.toUtf8() ; -// qDebug() << layoutInfo->name; - QVERIFY( ! layoutInfo->description.isEmpty() ); - - foreach(const VariantInfo* variantInfo, layoutInfo->variantInfos) { - QVERIFY( variantInfo != NULL ); - QVERIFY( ! variantInfo->name.isEmpty() ); - QVERIFY( ! variantInfo->description.isEmpty() ); - } - foreach(const QString& language, layoutInfo->languages) { - QVERIFY( ! language.isEmpty() ); - } - } - } - - void testOptionGroups() { - foreach(const OptionGroupInfo* optionGroupInfo, rules->optionGroupInfos) { - QVERIFY( optionGroupInfo != NULL); - QVERIFY( ! optionGroupInfo->name.isEmpty() ); - QVERIFY( ! optionGroupInfo->description.isEmpty() ); - // optionGroupInfo->exclusive - - foreach(const OptionInfo* optionInfo, optionGroupInfo->optionInfos) { - QVERIFY( optionInfo != NULL ); - QVERIFY( ! optionInfo->name.isEmpty() ); - QVERIFY( ! optionInfo->description.isEmpty() ); - } - } - } - - void testExtras() { - Rules* rulesWithExtras = Rules::readRules(Rules::READ_EXTRAS); - QVERIFY2(rulesWithExtras->layoutInfos.size() > rules->layoutInfos.size(), "Rules with extras should have more layouts"); - - foreach(const LayoutInfo* layoutInfo, rules->layoutInfos) { - QVERIFY( ! layoutInfo->fromExtras ); - } - - bool foundFromExtras = false, foundNonExtras = false; - foreach(const LayoutInfo* layoutInfo, rulesWithExtras->layoutInfos) { - if( layoutInfo->fromExtras ) foundFromExtras = true; - if( ! layoutInfo->fromExtras ) foundNonExtras = true; - layoutInfo->languages.size(); // make sure we can access all merged objects - layoutInfo->variantInfos.size(); // make sure we can access all merged objects - } - QVERIFY( foundNonExtras ); - QVERIFY( foundFromExtras ); - } - - void testWriteNewXml() { - QDomDocument doc(QStringLiteral("xkbConfigRegistry")); - QDomElement root = doc.createElement(QStringLiteral("xkbConfigRegistry")); - root.setAttribute(QStringLiteral("version"), QStringLiteral("2.0")); - doc.appendChild(root); - - QDomElement modelList = doc.createElement(QStringLiteral("modelList")); - root.appendChild(modelList); - foreach(const ModelInfo* modelInfo, rules->modelInfos) { - QDomElement model = doc.createElement(QStringLiteral("model")); - model.setAttribute(QStringLiteral("name"), modelInfo->name); - model.setAttribute(QStringLiteral("description"), modelInfo->description); - model.setAttribute(QStringLiteral("vendor"), modelInfo->vendor); - modelList.appendChild(model); - } - - QDomElement layoutList = doc.createElement(QStringLiteral("layoutList")); - foreach(const LayoutInfo* layoutInfo, rules->layoutInfos) { - QDomElement layout = doc.createElement(QStringLiteral("layout")); - layout.setAttribute(QStringLiteral("name"), layoutInfo->name); - layout.setAttribute(QStringLiteral("description"), layoutInfo->description); - - QDomElement langList = doc.createElement(QStringLiteral("languageList")); - foreach(const QString& lang, layoutInfo->languages) { - QDomElement langNode = doc.createElement(QStringLiteral("lang")); - langNode.setAttribute(QStringLiteral("iso639Id"), lang); - langList.appendChild(langNode); - } - if( langList.hasChildNodes() ) { - layout.appendChild(langList); - } - - QDomElement variantList = doc.createElement(QStringLiteral("variantList")); - foreach(const VariantInfo* variantInfo, layoutInfo->variantInfos) { - QDomElement variant = doc.createElement(QStringLiteral("variant")); - variant.setAttribute(QStringLiteral("name"), variantInfo->name); - variant.setAttribute(QStringLiteral("description"), variantInfo->description); - - QDomElement langList = doc.createElement(QStringLiteral("languageList")); - foreach(const QString& lang, variantInfo->languages) { - QDomElement langNode = doc.createElement(QStringLiteral("lang")); - langNode.setAttribute(QStringLiteral("iso639Id"), lang); - langList.appendChild(langNode); - } - if( langList.hasChildNodes() ) { - variant.appendChild(langList); - } - - variantList.appendChild(variant); - } - if( variantList.hasChildNodes() ) { - layout.appendChild(variantList); - } - - layoutList.appendChild(layout); - } - root.appendChild(layoutList); - - QDomElement optionGroupList = doc.createElement(QStringLiteral("optionList")); - foreach(const OptionGroupInfo* optionGroupInfo, rules->optionGroupInfos) { - QDomElement optionGroup = doc.createElement(QStringLiteral("optionGroup")); - optionGroup.setAttribute(QStringLiteral("name"), optionGroupInfo->name); - optionGroup.setAttribute(QStringLiteral("description"), optionGroupInfo->description); - optionGroup.setAttribute(QStringLiteral("exclusive"), optionGroupInfo->exclusive); - - foreach(const OptionInfo* optionGroupInfo, optionGroupInfo->optionInfos) { - QDomElement option = doc.createElement(QStringLiteral("option")); - option.setAttribute(QStringLiteral("name"), optionGroupInfo->name); - option.setAttribute(QStringLiteral("description"), optionGroupInfo->description); - optionGroup.appendChild(option); - } - - optionGroupList.appendChild(optionGroup); - } - root.appendChild(optionGroupList); - - QFile file(QStringLiteral("base2.xml")); - if( ! file.open( QIODevice::WriteOnly | QIODevice::Truncate | QIODevice::Text) ) { - qWarning() << "Failed to open layout memory xml file for writing" << file.fileName(); - QFAIL("failed"); - } - - QTextStream out(&file); - out << doc.toString(); - } - - void testRulesVersion() { - QVERIFY(!rules->version.isEmpty()); - - Rules* rules10 = new Rules(); - Rules::readRules(rules10, QStringLiteral("config/base.xml"), false); - QCOMPARE(rules10->version, QString("1.0")); - delete rules10; - - Rules* rules11 = new Rules(); - Rules::readRules(rules11, QStringLiteral("config/base.1.1.xml"), false); - QCOMPARE(rules11->version, QString("1.1")); - - foreach(const LayoutInfo* layoutInfo, rules11->layoutInfos) { - QVERIFY( layoutInfo != NULL); - QVERIFY( ! layoutInfo->name.isEmpty() ); - QVERIFY( ! layoutInfo->description.isEmpty() ); - - foreach(const VariantInfo* variantInfo, layoutInfo->variantInfos) { - QVERIFY( variantInfo != NULL ); - QVERIFY( ! variantInfo->name.isEmpty() ); - QVERIFY( ! variantInfo->description.isEmpty() ); - } - } - - delete rules11; - } - - void loadRulesBenchmark() { - QBENCHMARK { - Rules* rules = Rules::readRules(readExtras); - delete rules; - } - } - -}; - -// need kde libs for config-workspace.h used in xkb_rules.cpp -QTEST_MAIN(RulesTest) - -#include "xkb_rules_test.moc" diff --git a/kcms/keyboard/udev_helper.h b/kcms/keyboard/udev_helper.h deleted file mode 100644 --- a/kcms/keyboard/udev_helper.h +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Copyright (C) 2015 David Rosca (nowrep@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 UDEV_HELPER_H_ -#define UDEV_HELPER_H_ - -#include - -class UdevDeviceNotifier : public QObject -{ - Q_OBJECT - -public: - explicit UdevDeviceNotifier(QObject *parent = nullptr); - ~UdevDeviceNotifier(); - -Q_SIGNALS: - void newKeyboardDevice(); - void newPointerDevice(); - -private: - void init(); - void socketActivated(); - - struct udev *m_udev; - struct udev_monitor *m_monitor; -}; - -#endif // UDEV_HELPER_H_ diff --git a/kcms/keyboard/udev_helper.cpp b/kcms/keyboard/udev_helper.cpp deleted file mode 100644 --- a/kcms/keyboard/udev_helper.cpp +++ /dev/null @@ -1,133 +0,0 @@ -/* - * Copyright (C) 2015 David Rosca (nowrep@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 "udev_helper.h" -#include "debug.h" - -#include - -#include - -#ifdef HAVE_UDEV -#include -#endif - -// Based on qtbase: src/platformsupport/devicediscovery/qdevicediscovery_udev.cpp - -UdevDeviceNotifier::UdevDeviceNotifier(QObject *parent) - : QObject(parent) - , m_udev(nullptr) - , m_monitor(nullptr) -{ - init(); -} - -#ifdef HAVE_UDEV -UdevDeviceNotifier::~UdevDeviceNotifier() -{ - if (m_monitor) { - udev_monitor_unref(m_monitor); - } - if (m_udev) { - udev_unref(m_udev); - } -} - -void UdevDeviceNotifier::init() -{ - m_udev = udev_new(); - if (!m_udev) { - return; - } - - m_monitor = udev_monitor_new_from_netlink(m_udev, "udev"); - if (!m_monitor) { - return; - } - - udev_monitor_filter_add_match_subsystem_devtype(m_monitor, "input", 0); - udev_monitor_enable_receiving(m_monitor); - - int monitor_fd = udev_monitor_get_fd(m_monitor); - QSocketNotifier *notifier = new QSocketNotifier(monitor_fd, QSocketNotifier::Read, this); - connect(notifier, &QSocketNotifier::activated, this, &UdevDeviceNotifier::socketActivated); -} - -void UdevDeviceNotifier::socketActivated() -{ - static const char *keyboardDevice[] = { - "ID_INPUT_KEYBOARD", - "ID_INPUT_KEY" - }; - - static const char *pointerDevice[] = { - "ID_INPUT_MOUSE", - "ID_INPUT_TOUCHPAD", - "ID_INPUT_TABLET" - }; - - struct udev_device *dev = udev_monitor_receive_device(m_monitor); - if (!dev) { - return; - } - - const char *action = udev_device_get_action(dev); - if (!action || qstrcmp(action, "add") != 0) { - udev_device_unref(dev); - return; - } - - // Skip devices with empty name - if (!udev_device_get_property_value(dev, "NAME")) { - udev_device_unref(dev); - return; - } - - for (unsigned i = 0; i < sizeof(keyboardDevice) / sizeof(keyboardDevice[0]); ++i) { - if (qstrcmp(udev_device_get_property_value(dev, keyboardDevice[i]), "1") == 0) { - qCDebug(KCM_KEYBOARD) << "New Udev keyboard device"; - Q_EMIT newKeyboardDevice(); - break; - } - } - - for (unsigned i = 0; i < sizeof(pointerDevice) / sizeof(pointerDevice[0]); ++i) { - if (qstrcmp(udev_device_get_property_value(dev, pointerDevice[i]), "1") == 0) { - qCDebug(KCM_KEYBOARD) << "New Udev pointer device"; - Q_EMIT newPointerDevice(); - break; - } - } - - udev_device_unref(dev); -} - -#else -UdevDeviceNotifier::~UdevDeviceNotifier() -{ -} - -void UdevDeviceNotifier::init() -{ -} - -void UdevDeviceNotifier::socketActivated() -{ -} -#endif - diff --git a/kcms/keyboard/x11_helper.cpp b/kcms/keyboard/x11_helper.cpp deleted file mode 100644 --- a/kcms/keyboard/x11_helper.cpp +++ /dev/null @@ -1,452 +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. - */ - -#include "x11_helper.h" -#include "debug.h" - -#define explicit explicit_is_keyword_in_cpp -#include -#undef explicit - - -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include - -// more information about the limit https://bugs.freedesktop.org/show_bug.cgi?id=19501 -const int X11Helper::MAX_GROUP_COUNT = 4; -const int X11Helper::ARTIFICIAL_GROUP_LIMIT_COUNT = 8; - -const char X11Helper::LEFT_VARIANT_STR[] = "("; -const char X11Helper::RIGHT_VARIANT_STR[] = ")"; - -bool X11Helper::xkbSupported(int* xkbOpcode) -{ - if (!QX11Info::isPlatformX11()) { - return false; - } - // Verify the Xlib has matching XKB extension. - - int major = XkbMajorVersion; - int minor = XkbMinorVersion; - - if (!XkbLibraryVersion(&major, &minor)) - { - qCWarning(KCM_KEYBOARD) << "Xlib XKB extension " << major << '.' << minor << - " != " << XkbMajorVersion << '.' << XkbMinorVersion; - return false; - } - - // Verify the X server has matching XKB extension. - - int opcode_rtrn; - int error_rtrn; - int xkb_opcode; - if( ! XkbQueryExtension(QX11Info::display(), &opcode_rtrn, &xkb_opcode, &error_rtrn, &major, &minor)) { - qCWarning(KCM_KEYBOARD) << "X server XKB extension " << major << '.' << minor << - " != " << XkbMajorVersion << '.' << XkbMinorVersion; - return false; - } - - if( xkbOpcode != NULL ) { - *xkbOpcode = xkb_opcode; - } - - return true; -} - -void X11Helper::switchToNextLayout() -{ - int size = getLayoutsList().size(); //TODO: could optimize a bit as we don't need the layouts - just count - int group = (X11Helper::getGroup() + 1) % size; - X11Helper::setGroup(group); -} - -void X11Helper::scrollLayouts(int delta) -{ - int size = getLayoutsList().size(); //TODO: could optimize a bit as we don't need the layouts - just count - int group = X11Helper::getGroup() + delta; - group = group < 0 ? size - ((-group) % size) : group % size; - - X11Helper::setGroup(group); -} - -QStringList X11Helper::getLayoutsListAsString(const QList& layoutsList) -{ - QStringList stringList; - foreach(const LayoutUnit& layoutUnit, layoutsList) { - stringList << layoutUnit.toString(); - } - return stringList; -} - -bool X11Helper::setLayout(const LayoutUnit& layout) -{ - QList currentLayouts = getLayoutsList(); - int idx = currentLayouts.indexOf(layout); - if( idx == -1 || idx >= X11Helper::MAX_GROUP_COUNT ) { - qCWarning(KCM_KEYBOARD) << "Layout" << layout.toString() << "is not found in current layout list" - << getLayoutsListAsString(currentLayouts); - return false; - } - - return X11Helper::setGroup((unsigned int)idx); -} - -bool X11Helper::setDefaultLayout() { - return X11Helper::setGroup(0); -} - -bool X11Helper::isDefaultLayout() { - return X11Helper::getGroup() == 0; -} - -LayoutUnit X11Helper::getCurrentLayout() -{ - if (!QX11Info::isPlatformX11()) { - return LayoutUnit(); - } - QList currentLayouts = getLayoutsList(); - unsigned int group = X11Helper::getGroup(); - if( group < (unsigned int)currentLayouts.size() ) - return currentLayouts[group]; - - qCWarning(KCM_KEYBOARD) << "Current group number" << group << "is outside of current layout list" << - getLayoutsListAsString(currentLayouts); - return LayoutUnit(); -} - -LayoutSet X11Helper::getCurrentLayouts() -{ - LayoutSet layoutSet; - - QList currentLayouts = getLayoutsList(); - layoutSet.layouts = currentLayouts; - - unsigned int group = X11Helper::getGroup(); - if( group < (unsigned int)currentLayouts.size() ) { - layoutSet.currentLayout = currentLayouts[group]; - } - else { - qCWarning(KCM_KEYBOARD) << "Current group number" << group << "is outside of current layout list" << getLayoutsListAsString(currentLayouts); - layoutSet.currentLayout = LayoutUnit(); - } - - return layoutSet; -} - - -//static QString addNum(const QString& str, int n) -//{ -// QString format("%1%2"); -// if( str.length() >= 3 ) return format.arg(str.left(2)).arg(n); -// return format.arg(str).arg(n); -//} - -QList X11Helper::getLayoutsList() -{ - if (!QX11Info::isPlatformX11()) { - return QList(); - } - XkbConfig xkbConfig; - QList layouts; - if( X11Helper::getGroupNames(QX11Info::display(), &xkbConfig, X11Helper::LAYOUTS_ONLY) ) { - for(int i=0; ierror_code; - return false; - } - - return true; -} - -unsigned int X11Helper::getGroup() -{ - XkbStateRec xkbState; - XkbGetState( QX11Info::display(), XkbUseCoreKbd, &xkbState ); - return xkbState.group; -} - -bool X11Helper::getGroupNames(Display* display, XkbConfig* xkbConfig, FetchType fetchType) -{ - static const char OPTIONS_SEPARATOR[] = ","; - - Atom real_prop_type; - int fmt; - unsigned long nitems, extra_bytes; - char *prop_data = NULL; - Status ret; - - Atom rules_atom = XInternAtom(display, _XKB_RF_NAMES_PROP_ATOM, False); - - /* no such atom! */ - if (rules_atom == None) { /* property cannot exist */ - qCWarning(KCM_KEYBOARD) << "Failed to fetch layouts from server:" << "could not find the atom" << _XKB_RF_NAMES_PROP_ATOM; - return false; - } - - ret = XGetWindowProperty(display, - DefaultRootWindow(display), - rules_atom, 0L, _XKB_RF_NAMES_PROP_MAXLEN, - False, XA_STRING, &real_prop_type, &fmt, - &nitems, &extra_bytes, - (unsigned char **) (void *) &prop_data); - - /* property not found! */ - if (ret != Success) { - qCWarning(KCM_KEYBOARD) << "Failed to fetch layouts from server:" << "Could not get the property"; - return false; - } - - /* has to be array of strings */ - if ((extra_bytes > 0) || (real_prop_type != XA_STRING) || (fmt != 8)) { - if (prop_data) - XFree(prop_data); - qCWarning(KCM_KEYBOARD) << "Failed to fetch layouts from server:" << "Wrong property format"; - return false; - } - -// qCDebug(KCM_KEYBOARD) << "prop_data:" << nitems << prop_data; - QStringList names; - for(char* p=prop_data; p-prop_data < (long)nitems && p != NULL; p += strlen(p)+1) { - names.append( p ); -// qDebug() << " " << p; - } - - if( names.count() < 4 ) { //{ rules, model, layouts, variants, options } - XFree(prop_data); - return false; - } - - if( fetchType == ALL || fetchType == LAYOUTS_ONLY ) { - QStringList layouts = names[2].split(OPTIONS_SEPARATOR); - QStringList variants = names[3].split(OPTIONS_SEPARATOR); - - for(int ii=0; iilayouts << (layouts[ii] != NULL ? layouts[ii] : QLatin1String("")); - xkbConfig->variants << (ii < variants.count() && variants[ii] != NULL ? variants[ii] : QLatin1String("")); - } - qCDebug(KCM_KEYBOARD) << "Fetched layout groups from X server:" - << "\tlayouts:" << xkbConfig->layouts - << "\tvariants:" << xkbConfig->variants; - } - - if( fetchType == ALL || fetchType == MODEL_ONLY ) { - xkbConfig->keyboardModel = (names[1] != NULL ? names[1] : QLatin1String("")); - qCDebug(KCM_KEYBOARD) << "Fetched keyboard model from X server:" << xkbConfig->keyboardModel; - } - - if( fetchType == ALL ) { - if( names.count() >= 5 ) { - QString options = (names[4] != NULL ? names[4] : QLatin1String("")); - xkbConfig->options = options.split(OPTIONS_SEPARATOR); - qCDebug(KCM_KEYBOARD) << "Fetched xkbOptions from X server:" << options; - } - } - - XFree(prop_data); - return true; -} - -XEventNotifier::XEventNotifier(): - xkbOpcode(-1) -{ - if( QCoreApplication::instance() == NULL ) { - qCWarning(KCM_KEYBOARD) << "Layout Widget won't work properly without QCoreApplication instance"; - } -} - -void XEventNotifier::start() -{ - qCDebug(KCM_KEYBOARD) << "qCoreApp" << QCoreApplication::instance(); - if( QCoreApplication::instance() != NULL && X11Helper::xkbSupported(&xkbOpcode) ) { - registerForXkbEvents(QX11Info::display()); - - // start the event loop - QCoreApplication::instance()->installNativeEventFilter(this); - } -} - -void XEventNotifier::stop() -{ - if( QCoreApplication::instance() != NULL ) { - //TODO: unregister - // XEventNotifier::unregisterForXkbEvents(QX11Info::display()); - - // stop the event loop - QCoreApplication::instance()->removeNativeEventFilter(this); - } -} - - -bool XEventNotifier::isXkbEvent(xcb_generic_event_t* event) -{ -// qDebug() << "event response type:" << (event->response_type & ~0x80) << xkbOpcode << ((event->response_type & ~0x80) == xkbOpcode + XkbEventCode); - return (event->response_type & ~0x80) == xkbOpcode + XkbEventCode; -} - -bool XEventNotifier::processOtherEvents(xcb_generic_event_t* /*event*/) -{ - return true; -} - -bool XEventNotifier::processXkbEvents(xcb_generic_event_t* event) -{ - _xkb_event *xkbevt = reinterpret_cast<_xkb_event *>(event); - if( XEventNotifier::isGroupSwitchEvent(xkbevt) ) { -// qDebug() << "group switch event"; - emit(layoutChanged()); - } - else if( XEventNotifier::isLayoutSwitchEvent(xkbevt) ) { -// qDebug() << "layout switch event"; - emit(layoutMapChanged()); - } - return true; -} - -bool XEventNotifier::nativeEventFilter(const QByteArray &eventType, void *message, long *) -{ -// qDebug() << "event type:" << eventType; - if (eventType == "xcb_generic_event_t") { - xcb_generic_event_t* ev = static_cast(message); - if( isXkbEvent(ev) ) { - processXkbEvents(ev); - } - else { - processOtherEvents(ev); - } - } - return false; -} - -//bool XEventNotifier::x11Event(XEvent * event) -//{ -// // qApp->x11ProcessEvent ( event ); -// if( isXkbEvent(event) ) { -// processXkbEvents(event); -// } -// else { -// processOtherEvents(event); -// } -// return QWidget::x11Event(event); -//} - -bool XEventNotifier::isGroupSwitchEvent(_xkb_event* xkbEvent) -{ -// XkbEvent *xkbEvent = (XkbEvent*) event; -#define GROUP_CHANGE_MASK \ - ( XkbGroupStateMask | XkbGroupBaseMask | XkbGroupLatchMask | XkbGroupLockMask ) - - return xkbEvent->any.xkbType == XkbStateNotify && (xkbEvent->state_notify.changed & GROUP_CHANGE_MASK); -} - -bool XEventNotifier::isLayoutSwitchEvent(_xkb_event* xkbEvent) -{ -// XkbEvent *xkbEvent = (XkbEvent*) event; - - return //( (xkbEvent->any.xkb_type == XkbMapNotify) && (xkbEvent->map.changed & XkbKeySymsMask) ) || -/* || ( (xkbEvent->any.xkb_type == XkbNamesNotify) && (xkbEvent->names.changed & XkbGroupNamesMask) || )*/ - (xkbEvent->any.xkbType == XkbNewKeyboardNotify); -} - -int XEventNotifier::registerForXkbEvents(Display* display) -{ - int eventMask = XkbNewKeyboardNotifyMask | XkbStateNotifyMask; - if( ! XkbSelectEvents(display, XkbUseCoreKbd, eventMask, eventMask) ) { - qCWarning(KCM_KEYBOARD) << "Couldn't select desired XKB events"; - return false; - } - return true; -} - - -static const char LAYOUT_VARIANT_SEPARATOR_PREFIX[] = "("; -static const char LAYOUT_VARIANT_SEPARATOR_SUFFIX[] = ")"; - -static QString& stripVariantName(QString& variant) -{ - if( variant.endsWith(LAYOUT_VARIANT_SEPARATOR_SUFFIX) ) { - int suffixLen = strlen(LAYOUT_VARIANT_SEPARATOR_SUFFIX); - return variant.remove(variant.length()-suffixLen, suffixLen); - } - return variant; -} - -LayoutUnit::LayoutUnit(const QString& fullLayoutName) -{ - QStringList lv = fullLayoutName.split(LAYOUT_VARIANT_SEPARATOR_PREFIX); - layout = lv[0]; - variant = lv.size() > 1 ? stripVariantName(lv[1]) : QLatin1String(""); -} - -QString LayoutUnit::toString() const -{ - if( variant.isEmpty() ) - return layout; - - return layout + LAYOUT_VARIANT_SEPARATOR_PREFIX+variant+LAYOUT_VARIANT_SEPARATOR_SUFFIX; -} - -const int LayoutUnit::MAX_LABEL_LENGTH = 3; 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 @@ -37,7 +37,7 @@ if( info->name == name ) return info; } - return NULL; + return nullptr; } struct VariantInfo: public ConfigItem { @@ -86,7 +86,7 @@ } }; -struct Rules { +struct XkbRules { enum ExtrasFlag { NO_EXTRAS, READ_EXTRAS }; static const char XKB_OPTION_GROUP_SEPARATOR; @@ -96,47 +96,33 @@ QList optionGroupInfos; QString version; - Rules(); - - ~Rules() { - foreach(LayoutInfo* layoutInfo, layoutInfos) delete layoutInfo; - foreach(ModelInfo* modelInfo, modelInfos) delete modelInfo; - foreach(OptionGroupInfo* optionGroupInfo, optionGroupInfos) delete optionGroupInfo; - } - const LayoutInfo* getLayoutInfo(const QString& layoutName) const { return findByName(layoutInfos, layoutName); } const OptionGroupInfo* getOptionGroupInfo(const QString& optionGroupName) const { return findByName(optionGroupInfos, optionGroupName); } - static Rules* readRules(ExtrasFlag extrasFlag); - 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 QString& fileName_, const QString& geoName_): - fileName(fileName_), - geoName(geoName_) {} + static XkbRules* self() { + static QScopedPointer v(XkbRules::readRules(XkbRules::READ_EXTRAS)); + return v.get(); + } - GeometryId& operator=(const GeometryId& geoId) { - fileName = geoId.fileName; - geoName = geoId.geoName; - return *this; - } - }; + ~XkbRules() { + foreach(LayoutInfo* layoutInfo, layoutInfos) delete layoutInfo; + foreach(ModelInfo* modelInfo, modelInfos) delete modelInfo; + foreach(OptionGroupInfo* optionGroupInfo, optionGroupInfos) delete optionGroupInfo; + } - static GeometryId getGeometryId(const QString& model); -#endif +private: + XkbRules(); + static XkbRules* readRules(ExtrasFlag extrasFlag); + static XkbRules* readRules(XkbRules* rules, const QString& filename, bool fromExtras); }; #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 @@ -31,39 +31,38 @@ //#include //#include -#include "x11_helper.h" +//#include "x11_helper.h" // for findXkbRuleFile #include -#include -#include #include +#include +#include #include -#include #include +#include - - -class RulesHandler : public QXmlDefaultHandler -{ +class RulesHandler : public QXmlDefaultHandler { public: - RulesHandler(Rules* rules_, bool fromExtras_): - rules(rules_), - fromExtras(fromExtras_){} - - bool startElement(const QString &namespaceURI, const QString &localName, - const QString &qName, const QXmlAttributes &attributes) override; - bool endElement(const QString &namespaceURI, const QString &localName, - const QString &qName) override; - bool characters(const QString &str) override; -// bool fatalError(const QXmlParseException &exception); -// QString errorString() const; + RulesHandler(XkbRules* rules_, bool fromExtras_) + : rules(rules_) + , fromExtras(fromExtras_) + { + } + + bool startElement(const QString& namespaceURI, const QString& localName, + const QString& qName, const QXmlAttributes& attributes) override; + bool endElement(const QString& namespaceURI, const QString& localName, + const QString& qName) override; + bool characters(const QString& str) override; + // bool fatalError(const QXmlParseException &exception); + // QString errorString() const; private: -// QString getString(const QString& text); + // QString getString(const QString& text); QStringList path; - Rules* rules; + XkbRules* rules; const bool fromExtras; }; @@ -81,23 +80,24 @@ static QString translate_description(ConfigItem* item) { - return item->description.isEmpty() - ? item->name : translate_xml_item(item->description); + return item->description.isEmpty() + ? item->name + : translate_xml_item(item->description); } static bool notEmpty(const ConfigItem* item) { - return ! item->name.isEmpty(); + return !item->name.isEmpty(); } -template +template void removeEmptyItems(QList& list) { #ifdef __GNUC__ #if __GNUC__ == 4 && (__GNUC_MINOR__ == 8 && __GNUC_PATCHLEVEL__ < 3) || (__GNUC_MINOR__ == 7 && __GNUC_PATCHLEVEL__ < 4) #warning Compiling with a workaround for GCC < 4.8.3 || GCC < 4.7.4 http://gcc.gnu.org/bugzilla/show_bug.cgi?id=58800 - Q_FOREACH(T* x, list) { - ConfigItem *y = static_cast(x); + Q_FOREACH (T* x, list) { + ConfigItem* y = static_cast(x); if (y->name.isEmpty()) { list.removeAll(x); } @@ -108,388 +108,282 @@ #endif } -static -void postProcess(Rules* rules) +static void postProcess(XkbRules* rules) { - //TODO remove elements with empty names to safeguard us - removeEmptyItems(rules->layoutInfos); - removeEmptyItems(rules->modelInfos); - removeEmptyItems(rules->optionGroupInfos); - -// setlocale(LC_ALL, ""); -// bindtextdomain("xkeyboard-config", LOCALE_DIR); - foreach(ModelInfo* modelInfo, rules->modelInfos) { - modelInfo->vendor = translate_xml_item(modelInfo->vendor); - modelInfo->description = translate_description(modelInfo); - } - - foreach(LayoutInfo* layoutInfo, rules->layoutInfos) { - layoutInfo->description = translate_description(layoutInfo); - - removeEmptyItems(layoutInfo->variantInfos); - foreach(VariantInfo* variantInfo, layoutInfo->variantInfos) { - variantInfo->description = translate_description(variantInfo); - } - } - foreach(OptionGroupInfo* optionGroupInfo, rules->optionGroupInfos) { - optionGroupInfo->description = translate_description(optionGroupInfo); - - removeEmptyItems(optionGroupInfo->optionInfos); - foreach(OptionInfo* optionInfo, optionGroupInfo->optionInfos) { - optionInfo->description = translate_description(optionInfo); - } - } -} + //TODO remove elements with empty names to safeguard us + removeEmptyItems(rules->layoutInfos); + removeEmptyItems(rules->modelInfos); + removeEmptyItems(rules->optionGroupInfos); + + // setlocale(LC_ALL, ""); + // bindtextdomain("xkeyboard-config", LOCALE_DIR); + foreach (ModelInfo* modelInfo, rules->modelInfos) { + modelInfo->vendor = translate_xml_item(modelInfo->vendor); + modelInfo->description = translate_description(modelInfo); + } + foreach (LayoutInfo* layoutInfo, rules->layoutInfos) { + layoutInfo->description = translate_description(layoutInfo); -Rules::Rules(): - version(QStringLiteral("1.0")) + removeEmptyItems(layoutInfo->variantInfos); + foreach (VariantInfo* variantInfo, layoutInfo->variantInfos) { + variantInfo->description = translate_description(variantInfo); + } + } + foreach (OptionGroupInfo* optionGroupInfo, rules->optionGroupInfos) { + optionGroupInfo->description = translate_description(optionGroupInfo); + + removeEmptyItems(optionGroupInfo->optionInfos); + foreach (OptionInfo* optionInfo, optionGroupInfo->optionInfos) { + optionInfo->description = translate_description(optionInfo); + } + } +} + +XkbRules::XkbRules() + : version(QStringLiteral("1.0")) { } -QString Rules::getRulesName() +QString XkbRules::getRulesName() { if (!QX11Info::isPlatformX11()) { return QString(); } - XkbRF_VarDefsRec vd; - char *tmp = NULL; - - if (XkbRF_GetNamesProp(QX11Info::display(), &tmp, &vd) && tmp != NULL ) { - // qCDebug(KCM_KEYBOARD) << "namesprop" << tmp ; - const QString name(tmp); - XFree(tmp); - return name; - } + XkbRF_VarDefsRec vd; + char* tmp = nullptr; + + if (XkbRF_GetNamesProp(QX11Info::display(), &tmp, &vd) && tmp != nullptr) { + // qCDebug(KCM_KEYBOARD) << "namesprop" << tmp ; + const QString name(tmp); + XFree(tmp); + return name; + } return {}; } -QString Rules::findXkbDir() +QString XkbRules::findXkbDir() { - return QStringLiteral(XKBDIR); + return QStringLiteral(XKBDIR); } static QString findXkbRulesFile() { - QString rulesFile; - QString rulesName = Rules::getRulesName(); + QString rulesFile; + QString rulesName = XkbRules::getRulesName(); - const QString xkbDir = Rules::findXkbDir(); - if ( ! rulesName.isNull() ) { - rulesFile = QStringLiteral("%1/rules/%2.xml").arg(xkbDir, rulesName); - } else { + const QString xkbDir = XkbRules::findXkbDir(); + if (!rulesName.isNull()) { + rulesFile = QStringLiteral("%1/rules/%2.xml").arg(xkbDir, rulesName); + } else { // default to evdev rulesFile = QStringLiteral("%1/rules/evdev.xml").arg(xkbDir); } - return rulesFile; + return rulesFile; } -static -void mergeRules(Rules* rules, Rules* extraRules) +static void mergeRules(XkbRules* rules, XkbRules* extraRules) { - rules->modelInfos.append( extraRules->modelInfos ); - rules->optionGroupInfos.append( extraRules->optionGroupInfos ); // need to iterate and merge? - - QList layoutsToAdd; - foreach(LayoutInfo* extraLayoutInfo, extraRules->layoutInfos) { - LayoutInfo* layoutInfo = findByName(rules->layoutInfos, extraLayoutInfo->name); - if( layoutInfo != NULL ) { - layoutInfo->variantInfos.append( extraLayoutInfo->variantInfos ); - layoutInfo->languages.append( extraLayoutInfo->languages ); - } - else { - layoutsToAdd.append(extraLayoutInfo); - } - } - rules->layoutInfos.append(layoutsToAdd); - qCDebug(KCM_KEYBOARD) << "Merged from extra rules:" << extraRules->layoutInfos.size() << "layouts," << extraRules->modelInfos.size() << "models," << extraRules->optionGroupInfos.size() << "option groups"; - - // base rules now own the objects - remove them from extra rules so that it does not try to delete them - extraRules->layoutInfos.clear(); - extraRules->modelInfos.clear(); - extraRules->optionGroupInfos.clear(); -} + rules->modelInfos.append(extraRules->modelInfos); + rules->optionGroupInfos.append(extraRules->optionGroupInfos); // need to iterate and merge? + + QList layoutsToAdd; + foreach (LayoutInfo* extraLayoutInfo, extraRules->layoutInfos) { + LayoutInfo* layoutInfo = findByName(rules->layoutInfos, extraLayoutInfo->name); + if (layoutInfo != nullptr) { + layoutInfo->variantInfos.append(extraLayoutInfo->variantInfos); + layoutInfo->languages.append(extraLayoutInfo->languages); + } else { + layoutsToAdd.append(extraLayoutInfo); + } + } + rules->layoutInfos.append(layoutsToAdd); + qCDebug(KCM_KEYBOARD) << "Merged from extra rules:" << extraRules->layoutInfos.size() << "layouts," << extraRules->modelInfos.size() << "models," << extraRules->optionGroupInfos.size() << "option groups"; + // base rules now own the objects - remove them from extra rules so that it does not try to delete them + extraRules->layoutInfos.clear(); + extraRules->modelInfos.clear(); + extraRules->optionGroupInfos.clear(); +} -const char Rules::XKB_OPTION_GROUP_SEPARATOR = ':'; +const char XkbRules::XKB_OPTION_GROUP_SEPARATOR = ':'; -Rules* Rules::readRules(ExtrasFlag extrasFlag) +XkbRules* XkbRules::readRules(ExtrasFlag extrasFlag) { - Rules* rules = new Rules(); - QString rulesFile = findXkbRulesFile(); - if( ! readRules(rules, rulesFile, false) ) { - delete rules; - return NULL; - } - if( extrasFlag == Rules::READ_EXTRAS ) { - QRegExp regex(QStringLiteral("\\.xml$")); - Rules* rulesExtra = new Rules(); - QString extraRulesFile = rulesFile.replace(regex, QStringLiteral(".extras.xml")); - if( readRules(rulesExtra, extraRulesFile, true) ) { // not fatal if it fails - mergeRules(rules, rulesExtra); - } - delete rulesExtra; - } - return rules; + XkbRules* rules = new XkbRules(); + QString rulesFile = findXkbRulesFile(); + if (!readRules(rules, rulesFile, false)) { + delete rules; + return nullptr; + } + if (extrasFlag == XkbRules::READ_EXTRAS) { + QRegExp regex(QStringLiteral("\\.xml$")); + XkbRules* rulesExtra = new XkbRules(); + QString extraRulesFile = rulesFile.replace(regex, QStringLiteral(".extras.xml")); + if (readRules(rulesExtra, extraRulesFile, true)) { // not fatal if it fails + mergeRules(rules, rulesExtra); + } + delete rulesExtra; + } + return rules; } - -Rules* Rules::readRules(Rules* rules, const QString& filename, bool fromExtras) +XkbRules* XkbRules::readRules(XkbRules* rules, const QString& filename, bool fromExtras) { - QFile file(filename); - if( !file.open(QFile::ReadOnly | QFile::Text) ) { - qCCritical(KCM_KEYBOARD) << "Cannot open the rules file" << file.fileName(); - return NULL; - } + QFile file(filename); + if (!file.open(QFile::ReadOnly | QFile::Text)) { + qCCritical(KCM_KEYBOARD) << "Cannot open the rules file" << file.fileName(); + return nullptr; + } - RulesHandler rulesHandler(rules, fromExtras); + RulesHandler rulesHandler(rules, fromExtras); - QXmlSimpleReader reader; - reader.setContentHandler(&rulesHandler); - reader.setErrorHandler(&rulesHandler); + QXmlSimpleReader reader; + reader.setContentHandler(&rulesHandler); + reader.setErrorHandler(&rulesHandler); - QXmlInputSource xmlInputSource(&file); + QXmlInputSource xmlInputSource(&file); - qCDebug(KCM_KEYBOARD) << "Parsing xkb rules from" << file.fileName(); + qCDebug(KCM_KEYBOARD) << "Parsing xkb rules from" << file.fileName(); - if( ! reader.parse(xmlInputSource) ) { - qCCritical(KCM_KEYBOARD) << "Failed to parse the rules file" << file.fileName(); - return NULL; - } + if (!reader.parse(xmlInputSource)) { + qCCritical(KCM_KEYBOARD) << "Failed to parse the rules file" << file.fileName(); + return nullptr; + } - postProcess(rules); + postProcess(rules); - return rules; + return rules; } -bool RulesHandler::startElement(const QString &/*namespaceURI*/, const QString &/*localName*/, - const QString &qName, const QXmlAttributes &attributes) +bool RulesHandler::startElement(const QString& /*namespaceURI*/, const QString& /*localName*/, + const QString& qName, const QXmlAttributes& attributes) { - path << QString(qName); - - QString strPath = path.join(QStringLiteral("/")); - if( strPath.endsWith(QLatin1String("layoutList/layout/configItem")) ) { - rules->layoutInfos << new LayoutInfo(fromExtras); - } - else if( strPath.endsWith(QLatin1String("layoutList/layout/variantList/variant")) ) { - rules->layoutInfos.last()->variantInfos << new VariantInfo(fromExtras); - } - else if( strPath.endsWith(QLatin1String("modelList/model")) ) { - rules->modelInfos << new ModelInfo(); - } - else if( strPath.endsWith(QLatin1String("optionList/group")) ) { - rules->optionGroupInfos << new OptionGroupInfo(); - rules->optionGroupInfos.last()->exclusive = (attributes.value(QStringLiteral("allowMultipleSelection")) != QLatin1String("true")); - } - else if( strPath.endsWith(QLatin1String("optionList/group/option")) ) { - rules->optionGroupInfos.last()->optionInfos << new OptionInfo(); - } - else if( strPath == ("xkbConfigRegistry") && ! attributes.value(QStringLiteral("version")).isEmpty() ) { - rules->version = attributes.value(QStringLiteral("version")); - qCDebug(KCM_KEYBOARD) << "xkbConfigRegistry version" << rules->version; - } - return true; + path << QString(qName); + + QString strPath = path.join(QStringLiteral("/")); + if (strPath.endsWith(QLatin1String("layoutList/layout/configItem"))) { + rules->layoutInfos << new LayoutInfo(fromExtras); + } else if (strPath.endsWith(QLatin1String("layoutList/layout/variantList/variant"))) { + rules->layoutInfos.last()->variantInfos << new VariantInfo(fromExtras); + } else if (strPath.endsWith(QLatin1String("modelList/model"))) { + rules->modelInfos << new ModelInfo(); + } else if (strPath.endsWith(QLatin1String("optionList/group"))) { + rules->optionGroupInfos << new OptionGroupInfo(); + rules->optionGroupInfos.last()->exclusive = (attributes.value(QStringLiteral("allowMultipleSelection")) != QLatin1String("true")); + } else if (strPath.endsWith(QLatin1String("optionList/group/option"))) { + rules->optionGroupInfos.last()->optionInfos << new OptionInfo(); + } else if (strPath == ("xkbConfigRegistry") && !attributes.value(QStringLiteral("version")).isEmpty()) { + rules->version = attributes.value(QStringLiteral("version")); + qCDebug(KCM_KEYBOARD) << "xkbConfigRegistry version" << rules->version; + } + return true; } -bool RulesHandler::endElement(const QString &/*namespaceURI*/, const QString &/*localName*/, const QString &/*qName*/) +bool RulesHandler::endElement(const QString& /*namespaceURI*/, const QString& /*localName*/, const QString& /*qName*/) { - path.removeLast(); - return true; + path.removeLast(); + return true; } -bool RulesHandler::characters(const QString &str) +bool RulesHandler::characters(const QString& str) { - if( !str.trimmed().isEmpty() ) { - QString strPath = path.join(QStringLiteral("/")); - if( strPath.endsWith(QLatin1String("layoutList/layout/configItem/name")) ) { - if( rules->layoutInfos.last() != NULL ) { - rules->layoutInfos.last()->name = str.trimmed(); -// qCDebug(KCM_KEYBOARD) << "name:" << str; - } - // skipping invalid entry - } - else if( strPath.endsWith(QLatin1String("layoutList/layout/configItem/description")) ) { - rules->layoutInfos.last()->description = str.trimmed(); -// qCDebug(KCM_KEYBOARD) << "descr:" << str; - } - else if( strPath.endsWith(QLatin1String("layoutList/layout/configItem/languageList/iso639Id")) ) { - rules->layoutInfos.last()->languages << str.trimmed(); -// qCDebug(KCM_KEYBOARD) << "\tlang:" << str; - } - else if( strPath.endsWith(QLatin1String("layoutList/layout/variantList/variant/configItem/name")) ) { - rules->layoutInfos.last()->variantInfos.last()->name = str.trimmed(); -// qCDebug(KCM_KEYBOARD) << "\tvariant name:" << str; - } - else if( strPath.endsWith(QLatin1String("layoutList/layout/variantList/variant/configItem/description")) ) { - rules->layoutInfos.last()->variantInfos.last()->description = str.trimmed(); -// qCDebug(KCM_KEYBOARD) << "\tvariant descr:" << str; - } - else if( strPath.endsWith(QLatin1String("layoutList/layout/variantList/variant/configItem/languageList/iso639Id")) ) { - rules->layoutInfos.last()->variantInfos.last()->languages << str.trimmed(); -// qCDebug(KCM_KEYBOARD) << "\tvlang:" << str; - } - else if( strPath.endsWith(QLatin1String("modelList/model/configItem/name")) ) { - rules->modelInfos.last()->name = str.trimmed(); -// qCDebug(KCM_KEYBOARD) << "name:" << str; - } - else if( strPath.endsWith(QLatin1String("modelList/model/configItem/description")) ) { - rules->modelInfos.last()->description = str.trimmed(); -// qCDebug(KCM_KEYBOARD) << "\tdescr:" << str; - } - else if( strPath.endsWith(QLatin1String("modelList/model/configItem/vendor")) ) { - rules->modelInfos.last()->vendor = str.trimmed(); -// qCDebug(KCM_KEYBOARD) << "\tvendor:" << str; - } - else if( strPath.endsWith(QLatin1String("optionList/group/configItem/name")) ) { - rules->optionGroupInfos.last()->name = str.trimmed(); -// qCDebug(KCM_KEYBOARD) << "name:" << str; - } - else if( strPath.endsWith(QLatin1String("optionList/group/configItem/description")) ) { - rules->optionGroupInfos.last()->description = str.trimmed(); -// qCDebug(KCM_KEYBOARD) << "\tdescr:" << str; - } - else if( strPath.endsWith(QLatin1String("optionList/group/option/configItem/name")) ) { - rules->optionGroupInfos.last()->optionInfos.last()->name = str.trimmed(); -// qCDebug(KCM_KEYBOARD) << "name:" << str; - } - else if( strPath.endsWith(QLatin1String("optionList/group/option/configItem/description")) ) { - rules->optionGroupInfos.last()->optionInfos.last()->description = str.trimmed(); -// qCDebug(KCM_KEYBOARD) << "\tdescr:" << str; - } - } - return true; + if (!str.trimmed().isEmpty()) { + QString strPath = path.join(QStringLiteral("/")); + if (strPath.endsWith(QLatin1String("layoutList/layout/configItem/name"))) { + if (rules->layoutInfos.last() != nullptr) { + rules->layoutInfos.last()->name = str.trimmed(); + // qCDebug(KCM_KEYBOARD) << "name:" << str; + } + // skipping invalid entry + } else if (strPath.endsWith(QLatin1String("layoutList/layout/configItem/description"))) { + rules->layoutInfos.last()->description = str.trimmed(); + // qCDebug(KCM_KEYBOARD) << "descr:" << str; + } else if (strPath.endsWith(QLatin1String("layoutList/layout/configItem/languageList/iso639Id"))) { + rules->layoutInfos.last()->languages << str.trimmed(); + // qCDebug(KCM_KEYBOARD) << "\tlang:" << str; + } else if (strPath.endsWith(QLatin1String("layoutList/layout/variantList/variant/configItem/name"))) { + rules->layoutInfos.last()->variantInfos.last()->name = str.trimmed(); + // qCDebug(KCM_KEYBOARD) << "\tvariant name:" << str; + } else if (strPath.endsWith(QLatin1String("layoutList/layout/variantList/variant/configItem/description"))) { + rules->layoutInfos.last()->variantInfos.last()->description = str.trimmed(); + // qCDebug(KCM_KEYBOARD) << "\tvariant descr:" << str; + } else if (strPath.endsWith(QLatin1String("layoutList/layout/variantList/variant/configItem/languageList/iso639Id"))) { + rules->layoutInfos.last()->variantInfos.last()->languages << str.trimmed(); + // qCDebug(KCM_KEYBOARD) << "\tvlang:" << str; + } else if (strPath.endsWith(QLatin1String("modelList/model/configItem/name"))) { + rules->modelInfos.last()->name = str.trimmed(); + // qCDebug(KCM_KEYBOARD) << "name:" << str; + } else if (strPath.endsWith(QLatin1String("modelList/model/configItem/description"))) { + rules->modelInfos.last()->description = str.trimmed(); + // qCDebug(KCM_KEYBOARD) << "\tdescr:" << str; + } else if (strPath.endsWith(QLatin1String("modelList/model/configItem/vendor"))) { + rules->modelInfos.last()->vendor = str.trimmed(); + // qCDebug(KCM_KEYBOARD) << "\tvendor:" << str; + } else if (strPath.endsWith(QLatin1String("optionList/group/configItem/name"))) { + rules->optionGroupInfos.last()->name = str.trimmed(); + // qCDebug(KCM_KEYBOARD) << "name:" << str; + } else if (strPath.endsWith(QLatin1String("optionList/group/configItem/description"))) { + rules->optionGroupInfos.last()->description = str.trimmed(); + // qCDebug(KCM_KEYBOARD) << "\tdescr:" << str; + } else if (strPath.endsWith(QLatin1String("optionList/group/option/configItem/name"))) { + rules->optionGroupInfos.last()->optionInfos.last()->name = str.trimmed(); + // qCDebug(KCM_KEYBOARD) << "name:" << str; + } else if (strPath.endsWith(QLatin1String("optionList/group/option/configItem/description"))) { + rules->optionGroupInfos.last()->optionInfos.last()->description = str.trimmed(); + // qCDebug(KCM_KEYBOARD) << "\tdescr:" << str; + } + } + return true; } bool LayoutInfo::isLanguageSupportedByLayout(const QString& lang) const { - if( languages.contains(lang) || isLanguageSupportedByVariants(lang) ) - return true; - -// // return yes if no languages found in layout or its variants -// if( languages.empty() ) { -// foreach(const VariantInfo* info, variantInfos) { -// if( ! info->languages.empty() ) -// return false; -// } -// return true; -// } - - return false; + if (languages.contains(lang) || isLanguageSupportedByVariants(lang)) + return true; + + // // return yes if no languages found in layout or its variants + // if( languages.empty() ) { + // foreach(const VariantInfo* info, variantInfos) { + // if( ! info->languages.empty() ) + // return false; + // } + // return true; + // } + + return false; } bool LayoutInfo::isLanguageSupportedByVariants(const QString& lang) const { - foreach(const VariantInfo* info, variantInfos) { - if( info->languages.contains(lang) ) - return true; - } - return false; + foreach (const VariantInfo* info, variantInfos) { + if (info->languages.contains(lang)) + return true; + } + return false; } bool LayoutInfo::isLanguageSupportedByDefaultVariant(const QString& lang) const { - if( languages.contains(lang) ) - return true; + if (languages.contains(lang)) + return true; - if( languages.empty() && isLanguageSupportedByVariants(lang) ) - return true; + if (languages.empty() && isLanguageSupportedByVariants(lang)) + return true; - return false; + return false; } bool LayoutInfo::isLanguageSupportedByVariant(const VariantInfo* variantInfo, const QString& lang) const { - if( variantInfo->languages.contains(lang) ) - return true; - - // if variant has no languages try to "inherit" them from layout - if( variantInfo->languages.empty() && languages.contains(lang) ) - return true; - - return false; -} - -#ifdef NEW_GEOMETRY + if (variantInfo->languages.contains(lang)) + return true; -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); + // if variant has no languages try to "inherit" them from layout + if (variantInfo->languages.empty() && languages.contains(lang)) + return true; - 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; + return false; } - -#endif diff --git a/kcms/launch/CMakeLists.txt b/kcms/launch/CMakeLists.txt --- a/kcms/launch/CMakeLists.txt +++ b/kcms/launch/CMakeLists.txt @@ -15,6 +15,8 @@ KF5::I18n KF5::KCMUtils KF5::QuickAddons + KF5::Plasma + KF5::PlasmaQuick ) kcoreaddons_desktop_to_json(kcm_launchfeedback "kcm_launchfeedback.desktop") diff --git a/kcms/new-keyboard/CMakeLists.txt b/kcms/new-keyboard/CMakeLists.txt new file mode 100644 --- /dev/null +++ b/kcms/new-keyboard/CMakeLists.txt @@ -0,0 +1,57 @@ +cmake_minimum_required(VERSION 3.10) + +set(CMAKE_AUTOMOC ON) + +set(CMAKE_INSTALL_PREFIX /usr) + +# Find includes in corresponding build directories +set(CMAKE_INCLUDE_CURRENT_DIR ON) + +# Instruct CMake to run moc automatically when needed. +set(CMAKE_AUTOMOC ON) + +find_package(ECM REQUIRED NO_MODULE) +set(CMAKE_MODULE_PATH ${ECM_MODULE_PATH} ${ECM_KDE_MODULE_DIR}) + +find_package(Qt5 REQUIRED COMPONENTS + Core + Qml +) + +find_package(KF5 REQUIRED COMPONENTS + CoreAddons + KCMUtils + I18n + Plasma + PlasmaQuick + Declarative +) + +include(KDEInstallDirs) +include(KDECompilerSettings) +include(KDECMakeSettings) + +# KI18N Translation Domain for this library +add_definitions(-DTRANSLATION_DOMAIN=\"kcm_keyboard\") + +set(kcm_keyboard_SRCS + main.cpp +) + +add_library(kcm_keyboard MODULE ${kcm_keyboard_SRCS}) + +target_link_libraries(kcm_keyboard + KF5::ConfigCore + KF5::CoreAddons + KF5::QuickAddons + KF5::Declarative + Qt5::Quick + KF5::KCMUtils + KF5::I18n +) + +kcoreaddons_desktop_to_json(kcm_keyboard "kcm_keyboard.desktop" SERVICE_TYPES kcmodule.desktop) +install(FILES kcm_keyboard.desktop DESTINATION ${KDE_INSTALL_KSERVICES5DIR}) +install(TARGETS kcm_keyboard DESTINATION ${KDE_INSTALL_PLUGINDIR}/kcms) + +kpackage_install_package(package kcm_keyboard kcms) diff --git a/kcms/new-keyboard/kcm_new_keyboard.desktop b/kcms/new-keyboard/kcm_new_keyboard.desktop new file mode 100644 --- /dev/null +++ b/kcms/new-keyboard/kcm_new_keyboard.desktop @@ -0,0 +1,19 @@ +[Desktop Entry] +Exec=kcmshell5 kcm_new_keyboard +Icon=preferences-desktop-keyboard +Type=Service +X-KDE-ServiceTypes=KCModule +X-DocPath=kcontrol/new_keyboard/index.html +Categories=Qt;KDE;X-KDE-settings-hardware; + +X-KDE-Library=kcm_new_keyboard +X-KDE-Init-Symbol=new_keyboard +X-KDE-ParentApp=kcontrol + +X-KDE-System-Settings-Parent-Category=input-devices +X-KDE-Weight=50 +OnlyShowIn=KDE; + +Name=Keyboard and IME + +Comment=Keyboard Hardware and Layout diff --git a/kcms/new-keyboard/main.h b/kcms/new-keyboard/main.h new file mode 100644 --- /dev/null +++ b/kcms/new-keyboard/main.h @@ -0,0 +1,30 @@ +#ifndef NEW_KEYBOARD_MAIN_H +#define NEW_KEYBOARD_MAIN_H + +#include + +class KcmNewKeyboard : public KQuickAddons::ConfigModule { + Q_OBJECT + Q_PROPERTY(QString keyboardModel READ keyboardModel WRITE setKeyboarModel NOTIFY keyboardModelChanged) + +public: + KcmNewKeyboard(QObject* parent, const QVariantList& args); + virtual ~KcmNewKeyboard() override; + +public Q_SLOTS: + virtual void load() override; + virtual void save() override; + virtual void defaults() override; + +public: + void setKeyboarModel(const QString& model); + QString keyboardModel() const; + +Q_SIGNALS: + void keyboardModelChanged(); + +private: + QString m_keyboard_model; +}; + +#endif // NEW_KEYBOARD_MAIN_H diff --git a/kcms/new-keyboard/main.cpp b/kcms/new-keyboard/main.cpp new file mode 100644 --- /dev/null +++ b/kcms/new-keyboard/main.cpp @@ -0,0 +1,112 @@ +#include "main.h" + +#include +#include +#include +#include +#include + +class KeyboardModelModel : public QAbstractListModel { + Q_OBJECT + +public: + explicit KeyboardModelModel(QObject* parent = nullptr); + + int rowCount(const QModelIndex& parent = QModelIndex()) const override; + + QVariant data(const QModelIndex& index, int role) const override; + + Qt::ItemFlags flags(const QModelIndex& index) const override; + + struct Roles { + enum { + DescriptionRole = Qt::UserRole + 1, + NameRole, + }; + }; + + QHash roleNames() const override; + +private: + struct KeyboardModel { + QString vendor, type, name; + }; + QList m_model_list; +}; + +KeyboardModelModel::KeyboardModelModel(QObject* parent) + : QAbstractListModel(parent) +{ + m_model_list << KeyboardModel{"Generic", "Generic 101-key PC", "101"}; +} + +int KeyboardModelModel::rowCount(const QModelIndex& parent) const +{ + return m_model_list.size(); +} + +QVariant KeyboardModelModel::data(const QModelIndex& index, int role) const +{ + auto model = m_model_list.at(index.row()); + if (role == Roles::DescriptionRole) + return i18nc("vendor | keyboard model", "%1 | %2", model.vendor, model.type); + if (role == Roles::NameRole) + return model.name; + return QVariant::Invalid; +} + +Qt::ItemFlags KeyboardModelModel::flags(const QModelIndex& index) const +{ + return Qt::ItemIsEnabled | Qt::ItemIsSelectable; +} + +QHash KeyboardModelModel::roleNames() const +{ + return { { Roles::DescriptionRole, "description" }, { Roles::NameRole, "name" } }; +} + +K_PLUGIN_FACTORY_WITH_JSON(NewKeyboardModuleFactory, + "kcm_new_keyboard.json", + registerPlugin();) + +KcmNewKeyboard::KcmNewKeyboard(QObject* parent, const QVariantList& args) + : KQuickAddons::ConfigModule(parent, args) +{ + KAboutData* about = new KAboutData( + "kcm_new_keyboard", i18n("..."), + QStringLiteral("1.0"), QString(), KAboutLicense::GPL); + + about->addAuthor(i18n("Park Gun")); + setAboutData(about); + setButtons(Help | Apply | Default); + + qmlRegisterType("org.kde.kcm.keyboard", 1, 0, "KeyboardModelModel"); +} + +KcmNewKeyboard::~KcmNewKeyboard() +{ +} + +void KcmNewKeyboard::load() +{ +} + +void KcmNewKeyboard::save() +{ +} + +void KcmNewKeyboard::defaults() +{ +} + +void KcmNewKeyboard::setKeyboarModel(const QString& model) +{ + m_keyboard_model = model; +} + +QString KcmNewKeyboard::keyboardModel() const +{ + return m_keyboard_model; +} + +#include diff --git a/kcms/new-keyboard/package/contents/ui/Advanced.qml b/kcms/new-keyboard/package/contents/ui/Advanced.qml new file mode 100644 --- /dev/null +++ b/kcms/new-keyboard/package/contents/ui/Advanced.qml @@ -0,0 +1,16 @@ +import QtQuick 2.1 +import QtQuick.Layouts 1.3 +import QtQuick.Controls 2.3 as Controls +import org.kde.kirigami 2.3 as Kirigami +import org.kde.kcm 1.1 as KCM + +KCM.SimpleKCM { + id: root + + anchors.fill: parent + + Kirigami.FormLayout { + id: formLayout + + } +} diff --git a/kcms/new-keyboard/package/contents/ui/Hardware.qml b/kcms/new-keyboard/package/contents/ui/Hardware.qml new file mode 100644 --- /dev/null +++ b/kcms/new-keyboard/package/contents/ui/Hardware.qml @@ -0,0 +1,96 @@ +import QtQuick 2.1 +import QtQuick.Layouts 1.3 +import QtQuick.Controls 2.3 as Controls +import org.kde.kirigami 2.3 as Kirigami +import org.kde.kcm 1.1 as KCM +import org.kde.kcm.keyboard 1.0 + +KCM.SimpleKCM { + id: root + + anchors.fill: parent + + Kirigami.FormLayout { + id: formLayout + + Controls.ComboBox { + Kirigami.FormData.label: i18n("Keyboard Model:") + model: KeyboardModelModel {} + textRole: "description" + } + + Item { + Kirigami.FormData.isSection: true + } + + TriSelector { + Kirigami.FormData.label: i18n("Numlock on Plasma Startup:") + } + + TriSelector { + Kirigami.FormData.label: i18n("Keyboard Repeat:") + } + + Item { + Kirigami.FormData.isSection: true + } + + RowLayout { + id: delay + Kirigami.FormData.label: i18n("Delay:") + + Controls.Slider { + id: delay_slider + + Layout.fillWidth: true; + anchors.verticalCenter: parent.verticalCenter + width: 300 + from: 100 + value: 10 + to: 5000 + } + + Controls.TextField { + Layout.fillWidth: false; + Layout.preferredWidth: 150; + id: delay_number_field; + text: Math.floor(delay_slider.value) + " ms" + } + } + + RowLayout { + Kirigami.FormData.label: i18n("Rate:") + + Controls.Slider { + id: rate_slider + + Layout.fillWidth: true; + anchors.verticalCenter: parent.verticalCenter + width: 300 + from: 0.2 + value: 10 + to: 50 + } + + Controls.TextField { + Layout.fillWidth: false; + Layout.preferredWidth: 150; + id: rate_number_field; + text: parseFloat(rate_slider.value).toFixed(2) + " repeats/s" + } + } + + Item { + Kirigami.FormData.isSection: true + } + + Controls.TextArea { + Kirigami.FormData.label: i18n("Test area:") + id: textarea + implicitWidth: Math.max(parent.width / 3, delay.width) + implicitHeight: 200 + wrapMode: TextEdit.Wrap + } + + } +} diff --git a/kcms/new-keyboard/package/contents/ui/Layouts.qml b/kcms/new-keyboard/package/contents/ui/Layouts.qml new file mode 100644 --- /dev/null +++ b/kcms/new-keyboard/package/contents/ui/Layouts.qml @@ -0,0 +1,97 @@ +import QtQuick 2.1 +import QtQuick.Layouts 1.3 +import QtQuick.Controls 2.3 as Controls +import org.kde.kirigami 2.3 as Kirigami +import org.kde.kcm 1.1 as KCM + +KCM.SimpleKCM { + id: root + + anchors.fill: parent + + Kirigami.FormLayout { + id: formLayout + + Column { + Kirigami.FormData.label: i18n("Layout Indicator") + + Controls.CheckBox { + id: layout_indicator_show; + text: i18n("Show layout indicator"); + } + Controls.CheckBox { + id: single_layout_show; + text: i18n("Show for single layout"); + } + } + + Column { + Kirigami.FormData.label: i18n("Layout Indicator Icon") + + Controls.RadioButton { + id: show_flag; + text: i18n("Show flag"); + } + Controls.RadioButton { + id: show_label; + text: i18n("Show label"); + } + Controls.RadioButton { + id: show_label_on_flag; + text: i18n("Show label on flag"); + } + } + + Item { + Kirigami.FormData.isSection: true + } + + Controls.ComboBox { + Kirigami.FormData.label: i18n("Switching Policy") + + model: [i18n("Global"), i18n("Desktop"), i18n("Application"), i18n("Window")] + } + + Item { + Kirigami.FormData.isSection: true + Kirigami.FormData.label: i18n("Shortcuts for Switching Layout") + } + + Controls.Button { + Kirigami.FormData.label: i18n("Main shortcuts") + implicitWidth: 200 + } + Controls.Button { + Kirigami.FormData.label: i18n("3rd level shortcut") + implicitWidth: 200 + } + Controls.Button { + Kirigami.FormData.label: i18n("Alternative shortcut") + implicitWidth: 200 + } + + ListView { + id: layout_list + Kirigami.FormData.isSection: true + + contentWidth: headerItem.width + + header: Row { + spacing: 1 + function itemAt(index) { return repeater.itemAt(index) } + Repeater { + id: repeater + model: ["Map", "Layout", "Variant", "Label", "Shortcut"] + Controls.Label { + text: modelData + font.bold: true + padding: 5 + background: Rectangle { color: "white" } + } + } + } + } + + + } +} diff --git a/kcms/new-keyboard/package/contents/ui/TriSelector.qml b/kcms/new-keyboard/package/contents/ui/TriSelector.qml new file mode 100644 --- /dev/null +++ b/kcms/new-keyboard/package/contents/ui/TriSelector.qml @@ -0,0 +1,20 @@ +import QtQuick 2.1 +import QtQuick.Controls 2.0 as Controls +import org.kde.kirigami 2.3 as Kirigami + +Column { + Kirigami.FormData.label: i18n("Numlock on Plasma Startup:") + + Controls.RadioButton { + id: turn_on; + text: i18n("Turn on"); + } + Controls.RadioButton { + id: turn_off; + text: i18n("Turn off"); + } + Controls.RadioButton { + id: leave_unchanged; + text: i18n("Leave unchanged"); + } +} diff --git a/kcms/new-keyboard/package/contents/ui/main.qml b/kcms/new-keyboard/package/contents/ui/main.qml new file mode 100644 --- /dev/null +++ b/kcms/new-keyboard/package/contents/ui/main.qml @@ -0,0 +1,56 @@ +/******************************************************************** +Copyright 2017 Roman Gilg + +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, see . +*********************************************************************/ +import QtQuick 2.1 +import QtQuick.Layouts 1.3 +import QtQuick.Controls 2.3 as Controls +import org.kde.kirigami 2.3 as Kirigami +import org.kde.kcm 1.1 as KCM + +Item { + + Controls.TabBar { + id: tabbar + anchors.top: parent.top + anchors.left: parent.left + anchors.right: parent.right + width: parent.width + Controls.TabButton { + text: i18n("Hardware") + } + Controls.TabButton { + text: i18n("Layouts") + } + Controls.TabButton { + text: i18n("Advanced") + } + } + + StackLayout { + anchors.top: tabbar.bottom + anchors.left: parent.left + anchors.right: parent.right + anchors.bottom: parent.bottom + + currentIndex: tabbar.currentIndex + + Hardware {} + + Layouts {} + + Advanced {} + } +} diff --git a/kcms/new-keyboard/package/metadata.desktop b/kcms/new-keyboard/package/metadata.desktop new file mode 100644 --- /dev/null +++ b/kcms/new-keyboard/package/metadata.desktop @@ -0,0 +1,17 @@ +[Desktop Entry] +Name=Keyboard and IME + +Icon=preferences-desktop-keyboard +Keywords= +Type=Service +X-KDE-ParentApp= +X-KDE-PluginInfo-Author=Park Gun +X-KDE-PluginInfo-Email=mujjingun@gmail.com +X-KDE-PluginInfo-License=GPL +X-KDE-PluginInfo-Name=kcm_new_keyboard +X-KDE-PluginInfo-Version= +X-KDE-PluginInfo-Website= +X-KDE-ServiceTypes=Plasma/Generic +X-Plasma-API=declarativeappletscript + +X-Plasma-MainScript=ui/main.qml