You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

288 lines
7.7 KiB

/*
* Copyright (C) 2014 John Layt <john@layt.net>
* Copyright (C) 2018 Eike Hein <hein@kde.org>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library 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
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public License
* along with this library; see the file COPYING.LIB. If not, write to
* the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301, USA.
*/
#include "translationsmodel.h"
#include <KLocalizedString>
#include <QCollator>
#include <QDebug>
#include <QLocale>
#include <QMetaEnum>
QStringList TranslationsModel::m_languages = QStringList();
QSet<QString> TranslationsModel::m_installedLanguages = QSet<QString>();
TranslationsModel::TranslationsModel(QObject *parent)
: QAbstractListModel(parent)
{
if (m_installedLanguages.isEmpty()) {
m_installedLanguages = KLocalizedString::availableDomainTranslations("systemsettings");
m_languages = m_installedLanguages.toList();
}
}
TranslationsModel::~TranslationsModel()
{
}
QHash<int, QByteArray> TranslationsModel::roleNames() const
{
QHash<int, QByteArray> roles = QAbstractItemModel::roleNames();
QMetaEnum e = metaObject()->enumerator(metaObject()->indexOfEnumerator("AdditionalRoles"));
for (int i = 0; i < e.keyCount(); ++i) {
roles.insert(e.value(i), e.key(i));
}
return roles;
}
QVariant TranslationsModel::data(const QModelIndex &index, int role) const
{
if (!index.isValid() || index.row() < 0 || index.row() >= m_languages.count()) {
return QVariant();
}
if (role == Qt::DisplayRole) {
return languageCodeToName(m_languages.at(index.row()));
} else if (role == LanguageCode) {
return m_languages.at(index.row());
} else if (role == IsMissing) {
return false;
}
return QVariant();
}
int TranslationsModel::rowCount(const QModelIndex &parent) const
{
if (parent.isValid()) {
return 0;
}
return m_languages.count();
}
QString TranslationsModel::languageCodeToName(const QString& languageCode) const
{
const QLocale locale(languageCode);
const QString &languageName = locale.nativeLanguageName();
if (languageName.isEmpty()) {
return languageCode;
}
if (languageCode.contains(QStringLiteral("@"))) {
return i18nc("%1 is language name, %2 is language code name", "%1 (%2)", languageName, languageCode);
}
if (locale.name() != languageCode && m_installedLanguages.contains(locale.name())) {
// KDE languageCode got translated by QLocale to a locale code we also have on
// the list. Currently this only happens with pt that gets translated to pt_BR.
if (languageCode == QLatin1String("pt")) {
return QLocale(QStringLiteral("pt_PT")).nativeLanguageName();
}
qWarning() << "Language code morphed into another existing language code, please report!" << languageCode << locale.name();
return i18nc("%1 is language name, %2 is language code name", "%1 (%2)", languageName, languageCode);
}
return languageName;
}
SelectedTranslationsModel::SelectedTranslationsModel(QObject *parent)
: TranslationsModel(parent)
{
}
SelectedTranslationsModel::~SelectedTranslationsModel()
{
}
QVariant SelectedTranslationsModel::data(const QModelIndex &index, int role) const
{
if (!index.isValid() || index.row() < 0 || index.row() >= m_selectedLanguages.count()) {
return QVariant();
}
if (role == Qt::DisplayRole) {
return languageCodeToName(m_selectedLanguages.at(index.row()));
} else if (role == LanguageCode) {
return m_selectedLanguages.at(index.row());
} else if (role == IsMissing) {
return m_missingLanguages.contains(m_selectedLanguages.at(index.row()));
}
return QVariant();
}
int SelectedTranslationsModel::rowCount(const QModelIndex &parent) const
{
if (parent.isValid()) {
return 0;
}
return m_selectedLanguages.count();
}
QStringList SelectedTranslationsModel::selectedLanguages() const
{
return m_selectedLanguages;
}
void SelectedTranslationsModel::setSelectedLanguages(const QStringList &languages)
{
if (m_selectedLanguages != languages) {
QStringList missingLanguages;
for (const QString& lang : languages) {
if (!m_installedLanguages.contains(lang)) {
missingLanguages << lang;
}
}
missingLanguages.sort();
if (missingLanguages != m_missingLanguages) {
m_missingLanguages = missingLanguages;
emit missingLanguagesChanged();
}
beginResetModel();
m_selectedLanguages = languages;
endResetModel();
emit selectedLanguagesChanged(m_selectedLanguages);
}
}
QStringList SelectedTranslationsModel::missingLanguages() const
{
return m_missingLanguages;
}
void SelectedTranslationsModel::move(int from, int to)
{
if (from >= m_selectedLanguages.count() || to >= m_selectedLanguages.count()) {
return;
}
if (from == to) {
return;
}
const int modelTo = to + (to > from ? 1 : 0);
const bool ok = beginMoveRows(QModelIndex(), from, from, QModelIndex(), modelTo);
if (ok) {
m_selectedLanguages.move(from, to);
endMoveRows();
emit selectedLanguagesChanged(m_selectedLanguages);
}
}
void SelectedTranslationsModel::remove(const QString &languageCode)
{
if (languageCode.isEmpty()) {
return;
}
int index = m_selectedLanguages.indexOf(languageCode);
if (index < 0 || m_selectedLanguages.count() < 2) {
return;
}
beginRemoveRows(QModelIndex(), index, index);
m_selectedLanguages.removeAt(index);
endRemoveRows();
emit selectedLanguagesChanged(m_selectedLanguages);
}
AvailableTranslationsModel::AvailableTranslationsModel(QObject *parent)
: TranslationsModel(parent)
{
}
AvailableTranslationsModel::~AvailableTranslationsModel()
{
}
QVariant AvailableTranslationsModel::data(const QModelIndex &index, int role) const
{
if (!index.isValid() || index.row() < 0 || index.row() >= m_availableLanguages.count()) {
return QVariant();
}
if (role == Qt::DisplayRole) {
return languageCodeToName(m_availableLanguages.at(index.row()));
} else if (role == LanguageCode) {
return m_availableLanguages.at(index.row());
} else if (role == IsMissing) {
return false;
}
return QVariant();
}
int AvailableTranslationsModel::rowCount(const QModelIndex &parent) const
{
if (parent.isValid()) {
return 0;
}
return m_availableLanguages.count();
}
QString AvailableTranslationsModel::langCodeAt(int row)
{
if (row < 0 || row >= m_availableLanguages.count()) {
return QString();
}
return m_availableLanguages.at(row);
}
void AvailableTranslationsModel::setSelectedLanguages(const QStringList &languages)
{
beginResetModel();
m_availableLanguages = (m_installedLanguages - QSet<QString>::fromList(languages)).toList();
QCollator c;
c.setCaseSensitivity(Qt::CaseInsensitive);
std::sort(m_availableLanguages.begin(), m_availableLanguages.end(),
[this, &c](const QString &a, const QString &b) {
return c.compare(languageCodeToName(a), languageCodeToName(b)) < 0;
});
endResetModel();
}