KeyboardTranslatorManager.cpp 6.08 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
/*
    This source file is part of Konsole, a terminal emulator.

    Copyright 2007-2008 by Robert Knight <robertknight@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.
*/

// Own
#include "KeyboardTranslatorManager.h"

25 26
#include "konsoledebug.h"

27 28 29
// Qt
#include <QtCore/QFile>
#include <QtCore/QFileInfo>
30
#include <QtCore/QDir>
Laurent Montel's avatar
Laurent Montel committed
31
#include <QStandardPaths>
32 33 34 35 36

using namespace Konsole;

KeyboardTranslatorManager::KeyboardTranslatorManager()
    : _haveLoadedAll(false)
37
    , _fallbackTranslator(0)
38
    , _translators(QHash<QString, KeyboardTranslator*>())
39
{
40
    _fallbackTranslator = new FallbackKeyboardTranslator();
41
}
Jekyll Wu's avatar
Jekyll Wu committed
42

43 44 45
KeyboardTranslatorManager::~KeyboardTranslatorManager()
{
    qDeleteAll(_translators);
46
    delete _fallbackTranslator;
47
}
Jekyll Wu's avatar
Jekyll Wu committed
48

49
Q_GLOBAL_STATIC(KeyboardTranslatorManager, theKeyboardTranslatorManager)
Jekyll Wu's avatar
Jekyll Wu committed
50 51 52 53 54 55 56 57 58 59
KeyboardTranslatorManager* KeyboardTranslatorManager::instance()
{
    return theKeyboardTranslatorManager;
}

void KeyboardTranslatorManager::addTranslator(KeyboardTranslator* translator)
{
    _translators.insert(translator->name(), translator);

    if (!saveTranslator(translator))
60
        qCDebug(KonsoleDebug) << "Unable to save translator" << translator->name()
Jekyll Wu's avatar
Jekyll Wu committed
61 62 63 64 65 66 67 68 69 70 71 72 73
                   << "to disk.";
}

bool KeyboardTranslatorManager::deleteTranslator(const QString& name)
{
    Q_ASSERT(_translators.contains(name));

    // locate and delete
    QString path = findTranslatorPath(name);
    if (QFile::remove(path)) {
        _translators.remove(name);
        return true;
    } else {
74
        qCDebug(KonsoleDebug) << "Failed to remove translator - " << path;
Jekyll Wu's avatar
Jekyll Wu committed
75 76 77 78
        return false;
    }
}

79 80
QString KeyboardTranslatorManager::findTranslatorPath(const QString& name)
{
81
    return QStandardPaths::locate(QStandardPaths::GenericDataLocation, QStringLiteral("konsole/") + name + QStringLiteral(".keytab"));
82
}
Jekyll Wu's avatar
Jekyll Wu committed
83

84 85
void KeyboardTranslatorManager::findTranslators()
{
86 87

    QStringList list;
88
    const QStringList dirs = QStandardPaths::locateAll(QStandardPaths::GenericDataLocation, QStringLiteral("konsole"), QStandardPaths::LocateDirectory);
Kurt Hindenburg's avatar
Kurt Hindenburg committed
89 90
    list.reserve(dirs.size());

91 92 93
    Q_FOREACH (const QString& dir, dirs) {
        const QStringList fileNames = QDir(dir).entryList(QStringList() << QStringLiteral("*.keytab"));
        Q_FOREACH (const QString& file, fileNames) {
94
            list.append(dir + QLatin1Char('/') + file);
95 96
        }
    }
97 98 99 100

    // add the name of each translator to the list and associated
    // the name with a null pointer to indicate that the translator
    // has not yet been loaded from disk
Kurt Hindenburg's avatar
Kurt Hindenburg committed
101
    foreach(const QString& translatorPath, list) {
102 103 104 105 106 107 108 109 110 111 112 113
        QString name = QFileInfo(translatorPath).baseName();

        if (!_translators.contains(name))
            _translators.insert(name, 0);
    }

    _haveLoadedAll = true;
}

const KeyboardTranslator* KeyboardTranslatorManager::findTranslator(const QString& name)
{
    if (name.isEmpty())
114
        return defaultTranslator();
115 116 117 118 119 120 121 122 123

    if (_translators.contains(name) && _translators[name] != 0)
        return _translators[name];

    KeyboardTranslator* translator = loadTranslator(name);

    if (translator != 0)
        _translators[name] = translator;
    else if (!name.isEmpty())
124
        qCDebug(KonsoleDebug) << "Unable to load translator" << name;
125 126 127 128 129 130

    return translator;
}

bool KeyboardTranslatorManager::saveTranslator(const KeyboardTranslator* translator)
{
131
    const QString dir = QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation) + QStringLiteral("/konsole/");
132 133
    QDir().mkpath(dir);
    const QString path = dir + translator->name() + QStringLiteral(".keytab");
134

Laurent Montel's avatar
Laurent Montel committed
135
    ////qDebug() << "Saving translator to" << path;
136 137 138

    QFile destination(path);
    if (!destination.open(QIODevice::WriteOnly | QIODevice::Text)) {
139
        qCDebug(KonsoleDebug) << "Unable to save keyboard translation:"
140 141 142 143 144 145 146 147
                   << destination.errorString();
        return false;
    }

    {
        KeyboardTranslatorWriter writer(&destination);
        writer.writeHeader(translator->description());

Kurt Hindenburg's avatar
Kurt Hindenburg committed
148
        foreach(const KeyboardTranslator::Entry& entry, translator->entries()) {
149
            writer.writeEntry(entry);
Kurt Hindenburg's avatar
Kurt Hindenburg committed
150
        }
151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170
    }

    destination.close();

    return true;
}

KeyboardTranslator* KeyboardTranslatorManager::loadTranslator(const QString& name)
{
    const QString& path = findTranslatorPath(name);

    QFile source(path);
    if (name.isEmpty() || !source.open(QIODevice::ReadOnly | QIODevice::Text))
        return 0;

    return loadTranslator(&source, name);
}

KeyboardTranslator* KeyboardTranslatorManager::loadTranslator(QIODevice* source, const QString& name)
{
Kurt Hindenburg's avatar
Kurt Hindenburg committed
171
    auto translator = new KeyboardTranslator(name);
172 173 174 175 176 177 178 179 180 181 182 183 184 185 186
    KeyboardTranslatorReader reader(source);
    translator->setDescription(reader.description());
    while (reader.hasNextEntry())
        translator->addEntry(reader.nextEntry());

    source->close();

    if (!reader.parseError()) {
        return translator;
    } else {
        delete translator;
        return 0;
    }
}

187
const KeyboardTranslator* KeyboardTranslatorManager::defaultTranslator()
Jekyll Wu's avatar
Jekyll Wu committed
188 189
{
    // Try to find the default.keytab file if it exists, otherwise
190
    // fall back to the internal hard-coded fallback translator
191
    const KeyboardTranslator* translator = findTranslator(QStringLiteral("default"));
192
    if (translator == nullptr) {
193
        translator = _fallbackTranslator;
Jekyll Wu's avatar
Jekyll Wu committed
194 195 196 197
    }
    return translator;
}

Jekyll Wu's avatar
Jekyll Wu committed
198
QStringList KeyboardTranslatorManager::allTranslators()
199 200 201 202 203 204 205
{
    if (!_haveLoadedAll) {
        findTranslators();
    }

    return _translators.keys();
}