diff --git a/src/modules/keyboard/CMakeLists.txt b/src/modules/keyboard/CMakeLists.txt new file mode 100644 index 000000000..de450133f --- /dev/null +++ b/src/modules/keyboard/CMakeLists.txt @@ -0,0 +1,17 @@ +include_directories( ${PROJECT_BINARY_DIR}/src/libcalamaresui ) + +calamares_add_plugin( keyboard + TYPE viewmodule + EXPORT_MACRO PLUGINDLLEXPORT_PRO + CONFIG_FILE module.conf + SOURCES + KeyboardViewStep.cpp + KeyboardPage.cpp + keyboardwidget/keyboardglobal.cpp + keyboardwidget/keyboardpreview.cpp + UI + KeyboardPage.ui + LINK_LIBRARIES + calamaresui + SHARED_LIB +) diff --git a/src/modules/keyboard/KeyboardPage.cpp b/src/modules/keyboard/KeyboardPage.cpp new file mode 100644 index 000000000..4b01a15e7 --- /dev/null +++ b/src/modules/keyboard/KeyboardPage.cpp @@ -0,0 +1,232 @@ +/* === This file is part of Calamares - === + * + * Copyright 2014, Teo Mrnjavac + * + * Portions 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 "KeyboardPage.h" + +#include "ui_KeyboardPage.h" +#include "keyboardwidget/keyboardpreview.h" + +#include +#include +#include + + +KeyboardPage::KeyboardPage( QWidget* parent ) + : QWidget() + , ui( new Ui::Page_Keyboard ) + , m_keyboardPreview( new KeyBoardPreview( this ) ) +{ + ui->setupUi( this ); + + // Keyboard Preview + ui->KBPreviewLayout->addWidget( m_keyboardPreview ); + + // Connect signals and slots + connect( ui->listLayout, &QListWidget::currentItemChanged, + this, &KeyboardPage::onListLayoutCurrentItemChanged ); + connect( ui->listVariant, &QListWidget::currentItemChanged, + this, &KeyboardPage::onListVariantCurrentItemChanged ); + + connect( ui->buttonRestore, &QPushButton::clicked, + [this] + { + ui->comboBoxModel->setCurrentIndex( m_defaultIndex ); + }); + + connect( ui->comboBoxModel, + static_cast< void ( QComboBox::* )( const QString& ) >( &QComboBox::currentIndexChanged ), + [this]( const QString& text ) + { + QString model = m_models.value( text, "pc105" ); + + // Set Xorg keyboard model + QProcess::execute( QString( "setxkbmap -model \"%1\"" ) + .arg( model ).toUtf8() ); + }); +} + + +KeyboardPage::~KeyboardPage() +{ + delete ui; +} + + +void +KeyboardPage::init() +{ + //### Detect current keyboard layout and variant + QString currentLayout; + QProcess process; + process.start( "setxkbmap", QStringList() << "-print" ); + + if ( process.waitForFinished() ) + { + QStringList list = QString( process.readAll() ) + .split( "\n", QString::SkipEmptyParts ); + + foreach( QString line, list ) + { + line = line.trimmed(); + if ( !line.startsWith( "xkb_symbols" ) ) + continue; + + line = line.remove( "}" ) + .remove( "{" ) + .remove( ";" ); + line = line.mid( line.indexOf( "\"" ) + 1 ); + + QStringList split = line.split( "+", QString::SkipEmptyParts ); + if ( split.size() >= 2 ) + { + currentLayout = split.at( 1 ); + + if ( currentLayout.contains( "(" ) ) + currentLayout = currentLayout + .mid( 0, currentLayout.indexOf( "(" ) ) + .trimmed(); + } + } + } + + //### Models + m_models = KeyboardGlobal::getKeyboardModels(); + QMapIterator< QString, QString > mi( m_models ); + + ui->comboBoxModel->blockSignals( true ); + + while ( mi.hasNext() ) + { + mi.next(); + + if ( mi.value() == "pc105" ) + m_defaultIndex = ui->comboBoxModel->count(); + + ui->comboBoxModel->addItem( mi.key() ); + } + + ui->comboBoxModel->blockSignals( false ); + + // Set to default value pc105 + ui->comboBoxModel->setCurrentIndex( m_defaultIndex ); + + + //### Layouts and Variants + + // Block signals + ui->listLayout->blockSignals( true ); + + QMap< QString, KeyboardGlobal::KeyboardInfo > layouts = + KeyboardGlobal::getKeyboardLayouts(); + QMapIterator< QString, KeyboardGlobal::KeyboardInfo > li( layouts ); + LayoutItem* currentLayoutItem = nullptr; + + while ( li.hasNext() ) + { + li.next(); + + LayoutItem* item = new LayoutItem(); + KeyboardGlobal::KeyboardInfo info = li.value(); + + item->setText( info.description ); + item->data = li.key(); + item->info = info; + ui->listLayout->addItem( item ); + + // Find current layout index + if ( li.key() == currentLayout ) + currentLayoutItem = item; + } + + ui->listLayout->sortItems(); + + // Unblock signals + ui->listLayout->blockSignals( false ); + + // Set current layout + if ( currentLayoutItem ) + ui->listLayout->setCurrentItem( currentLayoutItem ); + else if ( ui->listLayout->count() > 0 ) + ui->listLayout->setCurrentRow( 0 ); +} + + +void +KeyboardPage::onListLayoutCurrentItemChanged( QListWidgetItem* current, QListWidgetItem* previous ) +{ + LayoutItem *item = dynamic_cast< LayoutItem* >( current ); + if ( !item ) + return; + + // Block signals + ui->listVariant->blockSignals( true ); + + QMap< QString, QString > variants = item->info.variants; + QMapIterator< QString, QString > li( variants ); + LayoutItem* defaultItem = nullptr; + + ui->listVariant->clear(); + + while ( li.hasNext() ) + { + li.next(); + + item = new LayoutItem(); + item->setText( li.key() ); + item->data = li.value(); + ui->listVariant->addItem( item ); + + if ( li.value() == "" ) + defaultItem = item; + } + + // Unblock signals + ui->listVariant->blockSignals( false ); + + // Set to default value + if ( defaultItem ) + ui->listVariant->setCurrentItem( defaultItem ); +} + + +void +KeyboardPage::onListVariantCurrentItemChanged( QListWidgetItem* current, QListWidgetItem* previous ) +{ + LayoutItem* layoutItem = dynamic_cast< LayoutItem* >( ui->listLayout->currentItem() ); + LayoutItem* variantItem = dynamic_cast< LayoutItem* >( current ); + + if ( !layoutItem || !variantItem ) + return; + + QString layout = layoutItem->data; + QString variant = variantItem->data; + + m_keyboardPreview->setLayout( layout ); + m_keyboardPreview->setVariant( variant ); + + //emit checkReady(); + + // Set Xorg keyboard layout + QProcess::execute( QString( "setxkbmap -layout \"%1\" -variant \"%2\"" ) + .arg( layout, variant ).toUtf8() ); +} + diff --git a/src/modules/keyboard/KeyboardPage.h b/src/modules/keyboard/KeyboardPage.h new file mode 100644 index 000000000..0c279966c --- /dev/null +++ b/src/modules/keyboard/KeyboardPage.h @@ -0,0 +1,66 @@ +/* === This file is part of Calamares - === + * + * Copyright 2014, Teo Mrnjavac + * + * Portions 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 . + */ + +#ifndef KEYBOARDPAGE_H +#define KEYBOARDPAGE_H + +#include "keyboardwidget/keyboardglobal.h" + +#include +#include + +namespace Ui +{ +class Page_Keyboard; +} + +class KeyBoardPreview; + +class KeyboardPage : public QWidget +{ + Q_OBJECT +public: + explicit KeyboardPage( QWidget* parent = nullptr ); + virtual ~KeyboardPage(); + + void init(); + +protected slots: + void onListLayoutCurrentItemChanged( QListWidgetItem* current, + QListWidgetItem* previous ); + void onListVariantCurrentItemChanged( QListWidgetItem* current, + QListWidgetItem* previous ); + +private: + class LayoutItem : public QListWidgetItem { + public: + QString data; + KeyboardGlobal::KeyboardInfo info; + }; + + Ui::Page_Keyboard *ui; + KeyBoardPreview* m_keyboardPreview; + int m_defaultIndex; + QMap< QString, QString > m_models; +}; + +#endif // KEYBOARDPAGE_H diff --git a/src/modules/keyboard/KeyboardPage.ui b/src/modules/keyboard/KeyboardPage.ui new file mode 100644 index 000000000..e778722e5 --- /dev/null +++ b/src/modules/keyboard/KeyboardPage.ui @@ -0,0 +1,146 @@ + + + Page_Keyboard + + + + 0 + 0 + 830 + 573 + + + + Form + + + + 9 + + + + + 0 + + + 12 + + + 12 + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + 0 + + + + + Keyboard Model: + + + + + + + + 0 + 0 + + + + + + + + + + + + :/images/restore.png:/images/restore.png + + + + 18 + 18 + + + + + + + + + + 9 + + + + + + + + + + + + + + 50 + false + + + + + + + + + + Type here to test your keyboard + + + + + + + comboBoxModel + listLayout + listVariant + LE_TestKeyboard + buttonRestore + + + + diff --git a/src/modules/keyboard/KeyboardViewStep.cpp b/src/modules/keyboard/KeyboardViewStep.cpp new file mode 100644 index 000000000..677eb90a0 --- /dev/null +++ b/src/modules/keyboard/KeyboardViewStep.cpp @@ -0,0 +1,87 @@ +/* === This file is part of Calamares - === + * + * Copyright 2014, Teo Mrnjavac + * + * 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 "KeyboardViewStep.h" + +#include "KeyboardPage.h" + + +KeyboardViewStep::KeyboardViewStep( QObject* parent ) + : Calamares::ViewStep( parent ) + , m_widget( new KeyboardPage() ) + , m_nextEnabled( false ) +{ + m_widget->init(); + m_nextEnabled = true; + emit nextStatusChanged( m_nextEnabled ); +} + + +KeyboardViewStep::~KeyboardViewStep() +{ + if ( m_widget && m_widget->parent() == nullptr ) + m_widget->deleteLater(); +} + + +QString +KeyboardViewStep::prettyName() const +{ + return tr( "Keyboard" ); +} + + +QWidget* +KeyboardViewStep::widget() +{ + return m_widget; +} + + +void +KeyboardViewStep::next() +{ + //TODO: actually save those settings somewhere + emit done(); +} + + +void +KeyboardViewStep::back() +{} + + +bool +KeyboardViewStep::isNextEnabled() const +{ + return m_nextEnabled; +} + + +bool +KeyboardViewStep::isAtBeginning() const +{ + return true; +} + + +bool +KeyboardViewStep::isAtEnd() const +{ + return true; +} diff --git a/src/modules/keyboard/KeyboardViewStep.h b/src/modules/keyboard/KeyboardViewStep.h new file mode 100644 index 000000000..7d0452360 --- /dev/null +++ b/src/modules/keyboard/KeyboardViewStep.h @@ -0,0 +1,57 @@ +/* === This file is part of Calamares - === + * + * Copyright 2014, Teo Mrnjavac + * + * 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 . + */ + +#ifndef KEYBOARDVIEWSTEP_H +#define KEYBOARDVIEWSTEP_H + +#include + +#include "viewpages/ViewStep.h" +#include "PluginDllMacro.h" + +class KeyboardPage; + +class PLUGINDLLEXPORT KeyboardViewStep : public Calamares::ViewStep +{ + Q_OBJECT + Q_PLUGIN_METADATA( IID "calamares.ViewModule/1.0" ) + + Q_INTERFACES( Calamares::ViewStep ) + +public: + explicit KeyboardViewStep( QObject* parent = nullptr ); + virtual ~KeyboardViewStep(); + + QString prettyName() const override; + + QWidget* widget() override; + + void next() override; + void back() override; + + bool isNextEnabled() const override; + + bool isAtBeginning() const override; + bool isAtEnd() const override; + +private: + KeyboardPage* m_widget; + bool m_nextEnabled; +}; + +#endif // KEYBOARDVIEWSTEP_H diff --git a/src/modules/keyboard/README.md b/src/modules/keyboard/README.md new file mode 100644 index 000000000..cf4ce3994 --- /dev/null +++ b/src/modules/keyboard/README.md @@ -0,0 +1,5 @@ +Keyboard layout configuration viewmodule +--- +Requires ckbcomp script. + * Debian package console-setup or + * Manjaro package keyboardctl https://github.com/manjaro/packages-core/tree/master/keyboardctl diff --git a/src/modules/keyboard/images/restore.png b/src/modules/keyboard/images/restore.png new file mode 100644 index 000000000..094c2c174 Binary files /dev/null and b/src/modules/keyboard/images/restore.png differ diff --git a/src/modules/keyboard/keyboardwidget/keyboardglobal.cpp b/src/modules/keyboard/keyboardwidget/keyboardglobal.cpp new file mode 100644 index 000000000..8136c92c5 --- /dev/null +++ b/src/modules/keyboard/keyboardwidget/keyboardglobal.cpp @@ -0,0 +1,171 @@ +/* === This file is part of Calamares - === + * + * Copyright 2014, Teo Mrnjavac + * + * 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" + +//### +//### Public methods +//### + + +QMap KeyboardGlobal::getKeyboardLayouts() { + return parseKeyboardLayouts(XKB_FILE); +} + + +QMap KeyboardGlobal::getKeyboardModels() { + return parseKeyboardModels(XKB_FILE); +} + + + +//### +//### Private methods +//### + + +//### Source by Georg Grabler ###// +QMap KeyboardGlobal::parseKeyboardModels(QString filepath) +{ + QMap models; + + QFile fh(filepath); + fh.open(QIODevice::ReadOnly); + + if (!fh.isOpen()) { + qDebug() << "X11 Keyboard model definitions not found!"; + return models; + } + + bool modelsFound = false; + // read the file until the end or until we break the loop + while (!fh.atEnd()) { + QByteArray line = fh.readLine(); + + // check if we start with the model section in the file + if (!modelsFound && line.startsWith("! model")) + modelsFound = true; + else if (modelsFound && line.startsWith ("!")) + break; + else if (!modelsFound) + continue; + + // 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; +} + + + +QMap< QString, KeyboardGlobal::KeyboardInfo > KeyboardGlobal::parseKeyboardLayouts(QString filepath) +{ + QMap< QString, KeyboardInfo > layouts; + + //### Get Layouts ###// + + QFile fh(filepath); + fh.open(QIODevice::ReadOnly); + + if (!fh.isOpen()) { + qDebug() << "X11 Keyboard layout definitions not found!"; + return layouts; + } + + bool layoutsFound = false; + // read the file until the end or we break the loop + while (!fh.atEnd()) { + QByteArray line = fh.readLine(); + + // find the layout section otherwhise continue. If the layout section is at it's end, break the loop + if (!layoutsFound && line.startsWith("! layout")) + layoutsFound = true; + else if (layoutsFound && line.startsWith ("!")) + break; + else if (!layoutsFound) + continue; + + QRegExp rx; + rx.setPattern("^\\s+(\\S+)\\s+(\\w.*)\n$"); + + // insert into the layout map + if (rx.indexIn(line) != -1) { + 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 = false; + // read the file until the end or until we break + while (!fh.atEnd()) { + QByteArray line = fh.readLine(); + + // continue until we found the variant section. If found, read until the next section is found + if (!variantsFound && line.startsWith("! variant")) { + variantsFound = true; + continue; + } else if (variantsFound && line.startsWith ("!")) + break; + else if (!variantsFound) + continue; + + 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. + 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; +} diff --git a/src/modules/keyboard/keyboardwidget/keyboardglobal.h b/src/modules/keyboard/keyboardwidget/keyboardglobal.h new file mode 100644 index 000000000..8710fdaa2 --- /dev/null +++ b/src/modules/keyboard/keyboardwidget/keyboardglobal.h @@ -0,0 +1,55 @@ +/* === This file is part of Calamares - === + * + * Copyright 2014, Teo Mrnjavac + * + * 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 . + */ + +#ifndef KEYBOARDGLOBAL_H +#define KEYBOARDGLOBAL_H + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define XKB_FILE "/usr/share/X11/xkb/rules/base.lst" + +class KeyboardGlobal +{ +public: + struct KeyboardInfo { + QString description; + QMap< QString, QString > variants; + }; + + static QMap< QString, KeyboardInfo > getKeyboardLayouts(); + static QMap< QString, QString > getKeyboardModels(); + +private: + static QMap< QString, QString > parseKeyboardModels(QString filepath); + static QMap< QString, KeyboardInfo > parseKeyboardLayouts(QString filepath); +}; + +#endif // KEYBOARDGLOBAL_H diff --git a/src/modules/keyboard/keyboardwidget/keyboardpreview.cpp b/src/modules/keyboard/keyboardwidget/keyboardpreview.cpp new file mode 100644 index 000000000..ff2508979 --- /dev/null +++ b/src/modules/keyboard/keyboardwidget/keyboardpreview.cpp @@ -0,0 +1,327 @@ +/* === This file is part of Calamares - === + * + * Copyright 2014, Teo Mrnjavac + * + * Portions 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 "keyboardpreview.h" + +KeyBoardPreview::KeyBoardPreview(QWidget *parent) : + QWidget(parent) +{ + setMinimumSize(700, 190); + + layout = "us"; + + // We must set up the font size in pixels to fit the keys + lowerFont = QFont("Helvetica", 10, QFont::DemiBold); + lowerFont.setPixelSize(16); + upperFont = QFont("Helvetica", 8); + upperFont.setPixelSize(13); + + // Setup keyboard types + kbList[KB_104].kb_extended_return = false; + kbList[KB_104].keys.append(QList() << 0x29 << 0x2 << 0x3 << 0x4 << 0x5 << 0x6 << 0x7 << 0x8 << 0x9 << 0xa << 0xb << 0xc << 0xd); + kbList[KB_104].keys.append(QList() << 0x10 << 0x11 << 0x12 << 0x13 << 0x14 << 0x15 << 0x16 << 0x17 << 0x18 << 0x19 << 0x1a << 0x1b << 0x2b); + kbList[KB_104].keys.append(QList() << 0x1e << 0x1f << 0x20 << 0x21 << 0x22 << 0x23 << 0x24 << 0x25 << 0x26 << 0x27 << 0x28); + kbList[KB_104].keys.append(QList() << 0x2c << 0x2d << 0x2e << 0x2f << 0x30 << 0x31 << 0x32 << 0x33 << 0x34 << 0x35); + + kbList[KB_105].kb_extended_return = true; + kbList[KB_105].keys.append(QList() << 0x29 << 0x2 << 0x3 << 0x4 << 0x5 << 0x6 << 0x7 << 0x8 << 0x9 << 0xa << 0xb << 0xc << 0xd); + kbList[KB_105].keys.append(QList() << 0x10 << 0x11 << 0x12 << 0x13 << 0x14 << 0x15 << 0x16 << 0x17 << 0x18 << 0x19 << 0x1a << 0x1b); + kbList[KB_105].keys.append(QList() << 0x1e << 0x1f << 0x20 << 0x21 << 0x22 << 0x23 << 0x24 << 0x25 << 0x26 << 0x27 << 0x28 << 0x2b); + kbList[KB_105].keys.append(QList() << 0x54 << 0x2c << 0x2d << 0x2e << 0x2f << 0x30 << 0x31 << 0x32 << 0x33 << 0x34 << 0x35); + + kbList[KB_106].kb_extended_return = true; + kbList[KB_106].keys.append(QList() << 0x29 << 0x2 << 0x3 << 0x4 << 0x5 << 0x6 << 0x7 << 0x8 << 0x9 << 0xa << 0xb << 0xc << 0xd << 0xe); + kbList[KB_106].keys.append(QList() << 0x10 << 0x11 << 0x12 << 0x13 << 0x14 << 0x15 << 0x16 << 0x17 << 0x18 << 0x19 << 0x1a << 0x1b); + kbList[KB_106].keys.append(QList() << 0x1e << 0x1f << 0x20 << 0x21 << 0x22 << 0x23 << 0x24 << 0x25 << 0x26 << 0x27 << 0x28 << 0x29); + kbList[KB_106].keys.append(QList() << 0x2c << 0x2d << 0x2e << 0x2f << 0x30 << 0x31 << 0x32 << 0x33 << 0x34 << 0x35 << 0x36); + + kb = &kbList[KB_104]; +} + + + +void KeyBoardPreview::setLayout(QString layout) { + this->layout = layout; +} + + + +void KeyBoardPreview::setVariant(QString variant) { + this->variant = variant; + + if (!loadCodes()) + return; + + loadInfo(); + repaint(); +} + + + +//### +//### Private +//### + + + +void KeyBoardPreview::loadInfo() { + // kb_104 + if (layout == "us" || layout == "th") + kb = &kbList[KB_104]; + // kb_106 + else if (layout == "jp") + kb = &kbList[KB_106]; + // most keyboards are 105 key so default to that + else + kb = &kbList[KB_105]; +} + + + +bool KeyBoardPreview::loadCodes() { + if (layout.isEmpty()) + return false; + + QStringList param; + param << "-model" << "pc106" << "-layout" << layout << "-compact"; + if (!variant.isEmpty()) + param << "-variant" << variant; + + + QProcess process; + process.setEnvironment(QStringList() << "LANG=C" << "LC_MESSAGES=C"); + process.start("ckbcomp", param); + if (!process.waitForStarted()) + return false; + + if (!process.waitForFinished()) + return false; + + // Clear codes + codes.clear(); + + QStringList list = QString(process.readAll()).split("\n", QString::SkipEmptyParts); + + foreach(QString line, list) { + if (!line.startsWith("keycode") || !line.contains('=')) + continue; + + QStringList split = line.split('=').at(1).trimmed().split(' '); + if (split.size() < 4) + continue; + + Code code; + code.plain = fromUnicodeString(split.at(0)); + code.shift = fromUnicodeString(split.at(1)); + code.ctrl = fromUnicodeString(split.at(2)); + code.alt = fromUnicodeString(split.at(3)); + + if (code.ctrl == code.plain) + code.ctrl = ""; + + if (code.alt == code.plain) + code.alt = ""; + + codes.append(code); + } + + return true; +} + + + +QString KeyBoardPreview::fromUnicodeString(QString raw) { + if (raw.startsWith("U+")) + return QChar(raw.mid(2).toInt(0, 16)); + else if (raw.startsWith("+U")) + return QChar(raw.mid(3).toInt(0, 16)); + + return ""; +} + + + +QString KeyBoardPreview::regular_text(int index) { + if (index < 0 || index >= codes.size()) + return ""; + + return codes.at(index - 1).plain; +} + + + +QString KeyBoardPreview::shift_text(int index) { + if (index < 0 || index >= codes.size()) + return ""; + + return codes.at(index - 1).shift; +} + + + +QString KeyBoardPreview::ctrl_text(int index) { + if (index < 0 || index >= codes.size()) + return ""; + + return codes.at(index - 1).ctrl; +} + + + +QString KeyBoardPreview::alt_text(int index) { + if (index < 0 || index >= codes.size()) + return ""; + + return codes.at(index - 1).alt; +} + + + +void KeyBoardPreview::resizeEvent(QResizeEvent *) { + space = 6; + usable_width = width()-6; + key_w = (usable_width - 14 * space)/15; + + setMaximumHeight(key_w*4 + space*5); +} + + + +void KeyBoardPreview::paintEvent(QPaintEvent * event) { + QPainter p(this); + p.setRenderHint(QPainter::Antialiasing); + + p.setBrush(QColor(0xd6, 0xd6, 0xd6)); + p.drawRect(rect()); + + QPen pen; + pen.setWidth(1); + pen.setColor(QColor(0x58, 0x58, 0x58)); + p.setPen(pen); + + p.setBrush(QColor(0x58, 0x58, 0x58)); + + p.setBackgroundMode(Qt::TransparentMode); + + int rx = 3; + int x=6; + int y=6; + int first_key_w = 0; + int remaining_x[] = {0,0,0,0}; + int remaining_widths[] = {0,0,0,0}; + + for (int i = 0; i < 4; i++) { + if (first_key_w > 0) { + first_key_w = first_key_w*1.375; + + if (kb == &kbList[KB_105] && i == 3) + first_key_w = key_w * 1.275; + + p.drawRoundedRect(QRectF(6, y, first_key_w, key_w), rx, rx); + x = 6 + first_key_w + space; + } + else { + first_key_w = key_w; + } + + + + bool last_end = (i==1 && ! kb->kb_extended_return); + int rw=usable_width-x; + int ii=0; + + foreach (int k, kb->keys.at(i)) { + QRectF rect = QRectF(x, y, key_w, key_w); + + if (ii == kb->keys.at(i).size()-1 && last_end) + rect.setWidth(rw); + + p.drawRoundedRect(rect, rx, rx); + + rect.adjust(5, 1, 0, 0); + + p.setPen(QColor(0x9e, 0xde, 0x00)); + p.setFont(upperFont); + p.drawText(rect, Qt::AlignLeft | Qt::AlignTop, shift_text(k)); + + rect.setBottom(rect.bottom() - 2.5); + + p.setPen(QColor(0xff, 0xff, 0xff)); + p.setFont(lowerFont); + p.drawText(rect, Qt::AlignLeft | Qt::AlignBottom, regular_text(k)); + + rw = rw - space - key_w; + x = x + space + key_w; + ii = ii+1; + + p.setPen(pen); + } + + + + remaining_x[i] = x; + remaining_widths[i] = rw; + + if (i != 1 && i != 2) + p.drawRoundedRect(QRectF(x, y, rw, key_w), rx, rx); + + x=.5; + y = y + space + key_w; + } + + + if (kb->kb_extended_return) { + rx=rx*2; + int x1 = remaining_x[1]; + int y1 = 6 + key_w*1 + space*1; + int w1 = remaining_widths[1]; + int x2 = remaining_x[2]; + int y2 = 6 + key_w*2 + space*2; + + // this is some serious crap... but it has to be so + // maybe one day keyboards won't look like this... + // one can only hope + QPainterPath pp; + pp.moveTo(x1, y1+rx); + pp.arcTo(x1, y1, rx, rx, 180, -90); + pp.lineTo(x1+w1-rx, y1); + pp.arcTo(x1+w1-rx, y1, rx, rx, 90, -90); + pp.lineTo(x1+w1, y2+key_w-rx); + pp.arcTo(x1+w1-rx, y2+key_w-rx, rx, rx, 0, -90); + pp.lineTo(x2+rx, y2+key_w); + pp.arcTo(x2, y2+key_w-rx, rx, rx, -90, -90); + pp.lineTo(x2, y1+key_w); + pp.lineTo(x1+rx, y1+key_w); + pp.arcTo(x1, y1+key_w-rx, rx, rx, -90, -90); + pp.closeSubpath(); + + p.drawPath(pp); + } + else { + x= remaining_x[2]; + y = 6 + key_w*2 + space*2; + p.drawRoundedRect(QRectF(x, y, remaining_widths[2], key_w), rx, rx); + } + + + QWidget::paintEvent(event); +} diff --git a/src/modules/keyboard/keyboardwidget/keyboardpreview.h b/src/modules/keyboard/keyboardwidget/keyboardpreview.h new file mode 100644 index 000000000..0a760ae7b --- /dev/null +++ b/src/modules/keyboard/keyboardwidget/keyboardpreview.h @@ -0,0 +1,80 @@ +/* === This file is part of Calamares - === + * + * Copyright 2014, Teo Mrnjavac + * + * Portions 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 . + */ + +#ifndef KEYBOARDPREVIEW_H +#define KEYBOARDPREVIEW_H + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +class KeyBoardPreview : public QWidget +{ + Q_OBJECT +public: + explicit KeyBoardPreview(QWidget *parent = 0); + + void setLayout(QString layout); + void setVariant(QString variant); + +private: + enum KB_TYPE { KB_104, KB_105, KB_106 }; + + struct KB { + bool kb_extended_return; + QList > keys; + }; + + struct Code { + QString plain, shift, ctrl, alt; + }; + + QString layout, variant; + QFont lowerFont, upperFont; + KB *kb, kbList[3]; + QList codes; + int space, usable_width, key_w; + + void loadInfo(); + bool loadCodes(); + QString regular_text(int index); + QString shift_text(int index); + QString ctrl_text(int index); + QString alt_text(int index); + QString fromUnicodeString(QString raw); + +protected: + void paintEvent(QPaintEvent * event); + void resizeEvent(QResizeEvent * event); + +}; + +#endif // KEYBOARDPREVIEW_H diff --git a/src/modules/keyboard/module.conf b/src/modules/keyboard/module.conf new file mode 100644 index 000000000..e1699d029 --- /dev/null +++ b/src/modules/keyboard/module.conf @@ -0,0 +1,8 @@ +# Module metadata file for keyboard viewmodule +# Syntax is YAML 1.2 +--- +type: "view" +name: "keyboard" +interface: "qtplugin" +requires: [] +load: "libcalamares_viewmodule_keyboard.so" diff --git a/src/modules/keyboard/resources.qrc b/src/modules/keyboard/resources.qrc new file mode 100644 index 000000000..3d5b1c1cd --- /dev/null +++ b/src/modules/keyboard/resources.qrc @@ -0,0 +1,5 @@ + + + images/restore.png + +