/* === This file is part of Calamares - === * * Copyright 2014, Teo Mrnjavac * Copyright 2019, Adriaan de Groot * * Originally from the Manjaro Installation Framework * by Roland Singer * Copyright (C) 2007 Free Software Foundation, Inc. * * Calamares 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 3 of the License, or * (at your option) any later version. * * Calamares 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 Calamares. If not, see . */ #include "keyboardglobal.h" #include "utils/Logger.h" #ifdef Q_OS_FREEBSD static const char XKB_FILE[] = "/usr/local/share/X11/xkb/rules/base.lst"; #else static const char XKB_FILE[] = "/usr/share/X11/xkb/rules/base.lst"; #endif // The xkb rules file is made of several "sections". Each section // starts with a line "! ". The static methods here // handle individual sections. /** @brief Scans a file for a named section * * Reads from @p fh incrementally until it finds a section named @p name * or hits end-of-file. Returns true if the section is found. The * @p name must include the "! " section marker as well. */ static bool findSection( QFile& fh, const char* name ) { while ( !fh.atEnd() ) { QByteArray line = fh.readLine(); if ( line.startsWith( name ) ) return true; } return false; } //### Source by Georg Grabler ###// static KeyboardGlobal::ModelsMap parseKeyboardModels(const char* filepath) { KeyboardGlobal::ModelsMap models; QFile fh(filepath); fh.open(QIODevice::ReadOnly); if (!fh.isOpen()) { cDebug() << "X11 Keyboard model definitions not found!"; return models; } bool modelsFound = findSection( fh, "! model" ); // read the file until the end or until we break the loop while (modelsFound && !fh.atEnd()) { QByteArray line = fh.readLine(); // check if we start a new section if ( line.startsWith( '!' ) ) break; // here we are in the model section, otherwhise we would continue or break QRegExp rx; rx.setPattern("^\\s+(\\S+)\\s+(\\w.*)\n$"); // insert into the model map if (rx.indexIn(line) != -1) { QString modelDesc = rx.cap(2); QString model = rx.cap(1); if (model == "pc105") modelDesc += " - " + QObject::tr("Default Keyboard Model"); models.insert(modelDesc, model); } } return models; } KeyboardGlobal::LayoutsMap parseKeyboardLayouts(const char* filepath) { KeyboardGlobal::LayoutsMap layouts; //### Get Layouts ###// QFile fh(filepath); fh.open(QIODevice::ReadOnly); if (!fh.isOpen()) { cDebug() << "X11 Keyboard layout definitions not found!"; return layouts; } bool layoutsFound = findSection( fh, "! layout" ); // read the file until the end or we break the loop while ( layoutsFound && !fh.atEnd() ) { QByteArray line = fh.readLine(); if ( line.startsWith( '!' ) ) break; QRegExp rx; rx.setPattern("^\\s+(\\S+)\\s+(\\w.*)\n$"); // insert into the layout map if (rx.indexIn(line) != -1) { KeyboardGlobal::KeyboardInfo info; info.description = rx.cap(2); info.variants.insert(QObject::tr("Default"), ""); layouts.insert(rx.cap(1), info); } } fh.reset(); //### Get Variants ###// bool variantsFound = findSection( fh, "! variant" ); // read the file until the end or until we break while (variantsFound && !fh.atEnd() ) { QByteArray line = fh.readLine(); if ( line.startsWith( '!' ) ) break; QRegExp rx; rx.setPattern("^\\s+(\\S+)\\s+(\\S+): (\\w.*)\n$"); // insert into the variants multimap, if the pattern matches if (rx.indexIn(line) != -1) { if (layouts.find(rx.cap(2)) != layouts.end()) { // in this case we found an entry in the multimap, and add the values to the multimap layouts.find(rx.cap(2)).value().variants.insert(rx.cap(3), rx.cap(1)); } else { // create a new map in the multimap - the value was not found. KeyboardGlobal::KeyboardInfo info; info.description = rx.cap(2); info.variants.insert(QObject::tr("Default"), ""); info.variants.insert(rx.cap(3), rx.cap(1)); layouts.insert(rx.cap(2), info); } } } return layouts; } KeyboardGlobal::LayoutsMap KeyboardGlobal::getKeyboardLayouts() { return parseKeyboardLayouts( XKB_FILE ); } KeyboardGlobal::ModelsMap KeyboardGlobal::getKeyboardModels() { return parseKeyboardModels( XKB_FILE ); }