<commit_before>// -*- mode: C++; c-basic-offset: 4; indent-tabs-mode: nil; c-file-offsets: ((innamespace . 0)); -*-
/*
 * This file is part of Maliit Plugins
 *
 * Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). All rights reserved.
 *
 * Contact: <NAME> <<EMAIL>>
 *
 * Redistribution and use in source and binary forms, with or without modification,
 * are permitted provided that the following conditions are met:
 *
 * Redistributions of source code must retain the above copyright notice, this list
 * of conditions and the following disclaimer.
 * Redistributions in binary form must reproduce the above copyright notice, this list
 * of conditions and the following disclaimer in the documentation and/or other materials
 * provided with the distribution.
 * Neither the name of Nokia Corporation nor the names of its contributors may be
 * used to endorse or promote products derived from this software without specific
 * prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
 * THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 */

#include <QDir>
#include <QFile>
#include <QRegExp>

#include "parser/layoutparser.h"

#include "keyboardloader.h"

namespace {

using namespace MaliitKeyboard;

const char *const languages_dir(MALIIT_PLUGINS_DATA_DIR "/languages");

TagKeyboardPtr get_tag_keyboard(const QString& id)
{
    QFile file (QString::fromLatin1(languages_dir) + "/" + id + ".xml");

    if (file.exists()) {
        file.open(QIODevice::ReadOnly);

        LayoutParser parser(&file);
        const bool result(parser.parse());

        file.close();
        if (result) {
            return parser.keyboard();
        }
    }

    return TagKeyboardPtr();
}

QStringList get_imports(const QString &id)
{
    QFile file (QString::fromLatin1(languages_dir) + "/" + id + ".xml");

    if (file.exists()) {
        file.open(QIODevice::ReadOnly);

        LayoutParser parser(&file);
        const bool result(parser.parse());

        file.close();
        if (result) {
            return parser.imports();
        }
    }

    return QStringList();

}

Keyboard get_keyboard(const TagKeyboardPtr& keyboard,
                      bool shifted = false,
                      int page = 0,
                      const QString &dead_label = "")
{
    Keyboard skeyboard;

    // FIXME: set style based on key count/style override.
    skeyboard.style_name = QString("keys33");
    const QChar dead_key((dead_label.size() == 1) ? dead_label[0] : QChar::Null);

    if (keyboard) {
        TagKeyboard::TagLayouts layouts(keyboard->layouts());

        if (not layouts.isEmpty()) {
            TagLayout::TagSections sections(layouts.first()->sections());
            // sections cannot be empty - parser does not allow that.
            TagSection::TagRows rows(sections[page % sections.size()]->rows());
            int row_num(0);

            Q_FOREACH (const TagRowPtr& row, rows) {
                TagRow::TagRowElements elements(row->elements());
                Q_FOREACH (const TagRowElementPtr& element, elements) {
                    if (element->element_type() == TagRowElement::Key) {
                        TagKeyPtr key(element.staticCast<TagKey>());
                        TagKey::TagBindings bindings(key->bindings());
                        Key skey;
                        KeyDescription skey_description;

                        skey_description.row = row_num;
                        skey_description.width = static_cast<KeyDescription::Width>(key->width());
                        skey_description.style = static_cast<KeyDescription::Style>(key->style());
                        skey_description.use_rtl_icon = key->rtl();

                        TagBindingPtr the_binding;

                        Q_FOREACH (const TagBindingPtr& binding, bindings) {
                            if (binding->shift() == shifted and not binding->alt()) {
                                the_binding = binding;
                                break;
                            }
                        }
                        if (not the_binding) {
                            the_binding = bindings.first();
                        }

                        KeyLabel label;
                        const int index(dead_key.isNull() ? -1 : the_binding->accents().indexOf(dead_key));

                        if (index < 0) {
                            label.setText(the_binding->label());
                        } else {
                            label.setText(the_binding->accented_labels()[index]);
                        }
                        if (the_binding->dead()) {
                            // TODO: document it.
                            skey.setAction(Key::ActionDead);
                        } else {
                            skey.setAction(static_cast<Key::Action>(the_binding->action()));
                        }
                        skey.setLabel(label);

                        skeyboard.keys.append(skey);
                        skeyboard.key_descriptions.append(skey_description);
                    }
                }
                ++row_num;
            }
        }
    }
    return skeyboard;
}

QPair<TagKeyPtr, TagBindingPtr> get_tag_key_and_binding(const TagKeyboardPtr &keyboard,
                                                        const QString &label)
{
    QPair<TagKeyPtr, TagBindingPtr> pair;
<commit_msg>Fill spacer and icon information in key description<commit_after>// -*- mode: C++; c-basic-offset: 4; indent-tabs-mode: nil; c-file-offsets: ((innamespace . 0)); -*-
/*
 * This file is part of Maliit Plugins
 *
 * Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). All rights reserved.
 *
 * Contact: <NAME> <<EMAIL>>
 *
 * Redistribution and use in source and binary forms, with or without modification,
 * are permitted provided that the following conditions are met:
 *
 * Redistributions of source code must retain the above copyright notice, this list
 * of conditions and the following disclaimer.
 * Redistributions in binary form must reproduce the above copyright notice, this list
 * of conditions and the following disclaimer in the documentation and/or other materials
 * provided with the distribution.
 * Neither the name of Nokia Corporation nor the names of its contributors may be
 * used to endorse or promote products derived from this software without specific
 * prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
 * THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 */

#include <QDir>
#include <QFile>
#include <QRegExp>

#include "parser/layoutparser.h"

#include "keyboardloader.h"

namespace {

using namespace MaliitKeyboard;

const char *const languages_dir(MALIIT_PLUGINS_DATA_DIR "/languages");

TagKeyboardPtr get_tag_keyboard(const QString& id)
{
    QFile file (QString::fromLatin1(languages_dir) + "/" + id + ".xml");

    if (file.exists()) {
        file.open(QIODevice::ReadOnly);

        LayoutParser parser(&file);
        const bool result(parser.parse());

        file.close();
        if (result) {
            return parser.keyboard();
        }
    }

    return TagKeyboardPtr();
}

QStringList get_imports(const QString &id)
{
    QFile file (QString::fromLatin1(languages_dir) + "/" + id + ".xml");

    if (file.exists()) {
        file.open(QIODevice::ReadOnly);

        LayoutParser parser(&file);
        const bool result(parser.parse());

        file.close();
        if (result) {
            return parser.imports();
        }
    }

    return QStringList();

}

Keyboard get_keyboard(const TagKeyboardPtr& keyboard,
                      bool shifted = false,
                      int page = 0,
                      const QString &dead_label = "")
{
    Keyboard skeyboard;

    // FIXME: set style based on key count/style override.
    skeyboard.style_name = QString("keys33");
    const QChar dead_key((dead_label.size() == 1) ? dead_label[0] : QChar::Null);

    if (keyboard) {
        TagKeyboard::TagLayouts layouts(keyboard->layouts());

        if (not layouts.isEmpty()) {
            TagLayout::TagSections sections(layouts.first()->sections());
            // sections cannot be empty - parser does not allow that.
            TagSection::TagRows rows(sections[page % sections.size()]->rows());
            int row_num(0);

            Q_FOREACH (const TagRowPtr& row, rows) {
                TagRow::TagRowElements elements(row->elements());
                bool spacer_met(false);

                Q_FOREACH (const TagRowElementPtr& element, elements) {
                    if (element->element_type() == TagRowElement::Key) {
                        TagKeyPtr key(element.staticCast<TagKey>());
                        TagKey::TagBindings bindings(key->bindings());
                        TagBindingPtr the_binding;

                        Q_FOREACH (const TagBindingPtr& binding, bindings) {
                            if (binding->shift() == shifted and not binding->alt()) {
                                the_binding = binding;
                                break;
                            }
                        }
                        if (not the_binding) {
                            the_binding = bindings.first();
                        }

                        KeyLabel label;
                        const int index(dead_key.isNull() ? -1 : the_binding->accents().indexOf(dead_key));

                        if (index < 0) {
                            label.setText(the_binding->label());
                        } else {
                            label.setText(the_binding->accented_labels()[index]);
                        }

                        Key skey;

                        if (the_binding->dead()) {
                            // TODO: document it.
                            skey.setAction(Key::ActionDead);
                        } else {
                            skey.setAction(static_cast<Key::Action>(the_binding->action()));
                        }
                        skey.setLabel(label);
                        skeyboard.keys.append(skey);

                        KeyDescription skey_description;

                        skey_description.row = row_num;
                        skey_description.use_rtl_icon = key->rtl();
                        skey_description.left_spacer = spacer_met;
                        skey_description.right_spacer = false;
                        skey_description.style = static_cast<KeyDescription::Style>(key->style());
                        skey_description.width = static_cast<KeyDescription::Width>(key->width());
                        switch (skey.action()) {
                        case Key::ActionBackspace:
                            skey_description.icon = KeyDescription::BackspaceIcon;
                            break;
                        case Key::ActionReturn:
                            skey_description.icon = KeyDescription::ReturnIcon;
                            break;
                        case Key::ActionShift:
                            skey_description.icon = KeyDescription::ShiftIcon;
                            break;
                        default:
                            skey_description.icon = KeyDescription::NoIcon;
                            break;
                        }
                        skey_description.font_group = KeyDescription::NormalFontGroup;
                        skeyboard.key_descriptions.append(skey_description);
                        spacer_met = false;
                    } else { // spacer
                        if (not skeyboard.key_descriptions.isEmpty()) {
                            KeyDescription& previous_skey_description(skeyboard.key_descriptions.last());

                            if (previous_skey_description.row == row_num) {
                                previous_skey_description.right_spacer = true;
                            }
                        }
                        spacer_met = true;
                    }
                }
                ++row_num;
            }
        }
    }
    return skeyboard;
}

QPair<TagKeyPtr, TagBindingPtr> get_tag_key_and_binding(const TagKeyboardPtr &keyboard,
                                                        const QString &label)
{
    QPair<TagKeyPtr, TagBindingPtr> pair;

{'fraction_non_alphanumeric': 0.09126551949466347, 'fraction_numerical': 0.0023233863355841137, 'mean_word_length': 1.7882591093117408, 'pattern_counts': {'":': 0, '<': 29, '<?xml version=': 0, '>': 59, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 4}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 4, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5991305', 'n_tokens_mistral': 3560, 'n_tokens_neox': 3298, 'n_words': 962}