diff --git a/kcms/CMakeLists.txt b/kcms/CMakeLists.txt --- a/kcms/CMakeLists.txt +++ b/kcms/CMakeLists.txt @@ -10,10 +10,6 @@ set(libkxftconfig_SRCS ${CMAKE_CURRENT_SOURCE_DIR}/fonts/kxftconfig.cpp ) -if(X11_Xkb_FOUND AND XCB_XKB_FOUND) - add_subdirectory( keyboard ) -endif() - if (EVDEV_FOUND AND XORGLIBINPUT_FOUND AND X11_Xinput_FOUND) add_subdirectory( input ) endif() diff --git a/kcms/translations/CMakeLists.txt b/kcms/translations/CMakeLists.txt --- a/kcms/translations/CMakeLists.txt +++ b/kcms/translations/CMakeLists.txt @@ -1,19 +1,26 @@ +include(ECMQMLModules) +ecm_find_qmlmodule(org.kde.plasma.core 2.0) + +# KI18N Translation Domain for this library. add_definitions(-DTRANSLATION_DOMAIN=\"kcmtranslations\") -set(kcm_translations_PART_SRCS kcmtranslations.cpp) +########### next target ############### -ki18n_wrap_ui(kcm_translations_PART_SRCS kcmtranslationswidget.ui) +set(kcm_translations_PART_SRCS translations.cpp translationsmodel.cpp) -add_library(kcm_translations ${kcm_translations_PART_SRCS}) +add_library(kcm_translations MODULE ${kcm_translations_PART_SRCS}) target_link_libraries(kcm_translations - Qt5::Widgets - KF5::WidgetsAddons - KF5::KCMUtils KF5::I18n + KF5::KCMUtils + KF5::QuickAddons ) +kcoreaddons_desktop_to_json(kcm_translations "kcm_translations.desktop") + ########### install files ############### -install(TARGETS kcm_translations DESTINATION ${KDE_INSTALL_PLUGINDIR}) -install(FILES translations.desktop DESTINATION ${KDE_INSTALL_KSERVICES5DIR}) +install(TARGETS kcm_translations DESTINATION ${KDE_INSTALL_PLUGINDIR}/kcms) +install(FILES kcm_translations.desktop DESTINATION ${KDE_INSTALL_KSERVICES5DIR}) +kpackage_install_package(package kcm_translations kcms) + diff --git a/kcms/translations/Messages.sh b/kcms/translations/Messages.sh --- a/kcms/translations/Messages.sh +++ b/kcms/translations/Messages.sh @@ -1,4 +1,2 @@ #! /usr/bin/env bash -$EXTRACTRC *.ui >> rc.cpp -$XGETTEXT -ktranslate:1,1t -ktranslate:1c,2,2t *.cpp -o $podir/kcmtranslations.pot -rm -f rc.cpp +$XGETTEXT `find . -name \*.cpp -o -name \*.qml` -o $podir/kcmtranslations.pot diff --git a/kcms/translations/translations.desktop b/kcms/translations/kcm_translations.desktop rename from kcms/translations/translations.desktop rename to kcms/translations/kcm_translations.desktop diff --git a/kcms/translations/kcmtranslations.h b/kcms/translations/kcmtranslations.h deleted file mode 100644 --- a/kcms/translations/kcmtranslations.h +++ /dev/null @@ -1,84 +0,0 @@ -/* This file is part of the KDE's Plasma workspace - * Copyright 2014 John Layt - * - * 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. - */ - -#ifndef KCMTRANSLATIONS_H -#define KCMTRANSLATIONS_H - - -#include -#include -#include - -class QListWidgetItem; -class KMessageWidget; - -namespace Ui -{ -class KCMTranslationsWidget; -} - -/** - * @short A KCM to configure KDE Gui Translations - * - * This module is for changing the User's Gui Translations settings. - */ - -class KCMTranslations : public KCModule -{ - Q_OBJECT - -public: - KCMTranslations(QWidget *parent, const QVariantList &); - ~KCMTranslations() override; - - void load() override; - void save() override; - void defaults() override; - QString quickHelp() const override; - -private Q_SLOTS: - - void changedTranslationsAvailable(QListWidgetItem *item); - void changedTranslationsSelected(QListWidgetItem *item); - - void installTranslations(); - -private: - - void loadTranslations(); - void changedTranslations(); - - void initWidgets(); - void initTranslations(); - void initTranslationsInstall(); - - // The list of translations currently set in the KCM - QStringList m_kcmTranslations; - // The currently saved list of user translations, used to check if value changed - QString m_configTranslations; - // The currently installed translations, used to check if users translations are valid - QStringList m_installedTranslations; - - KConfigGroup m_config; - - Ui::KCMTranslationsWidget *m_ui; - KMessageWidget *m_messageWidget; -}; - -#endif //KCMTRANSLATIONS_H diff --git a/kcms/translations/kcmtranslations.cpp b/kcms/translations/kcmtranslations.cpp deleted file mode 100644 --- a/kcms/translations/kcmtranslations.cpp +++ /dev/null @@ -1,328 +0,0 @@ -/* - * Copyright 2010, 2014 John Layt - * - * 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. - * - */ - -#include "kcmtranslations.h" - -#include "../formats/writeexports.h" - -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -#include "ui_kcmtranslationswidget.h" - -K_PLUGIN_FACTORY(KCMTranslationsFactory, registerPlugin();) - -KCMTranslations::KCMTranslations(QWidget *parent, const QVariantList &args) - : KCModule(parent, args), - m_ui(new Ui::KCMTranslationsWidget), - m_messageWidget(0) -{ - KAboutData *about = new KAboutData(QStringLiteral("KCMTranslations"), - i18n("Translations"), - QString(), - i18n("Configure Plasma translations"), - KAboutLicense::GPL); - about->addAuthor(i18n("John Layt"), i18n("Maintainer"), QStringLiteral("jlayt@kde.net")); - setAboutData(about); - - m_ui->setupUi(this); - - // Get the current config - m_config = KConfigGroup(KSharedConfig::openConfig(configFile), "Translations"); - - // Set up UI to respond to user changing the translation selection - connect(m_ui->m_selectTranslations, &KActionSelector::added, this, &KCMTranslations::changedTranslationsSelected); - connect(m_ui->m_selectTranslations, &KActionSelector::removed, this, &KCMTranslations::changedTranslationsAvailable); - connect(m_ui->m_selectTranslations, &KActionSelector::movedUp, this, &KCMTranslations::changedTranslationsSelected); - connect(m_ui->m_selectTranslations, &KActionSelector::movedDown, this, &KCMTranslations::changedTranslationsSelected); - - // If user clicks the Install button, trigger distro specific install routine - connect(m_ui->m_buttonTranslationsInstall, &QPushButton::clicked, this, &KCMTranslations::installTranslations); - - // Hide the Install button, this will be activated by those distros that support this feature. - m_ui->m_buttonTranslationsInstall->setHidden(true); -} - -KCMTranslations::~KCMTranslations() -{ - delete m_ui; -} - -// Reimp -// Load == User has clicked on Reset to restore saved settings -// Also gets called automatically called after constructor -void KCMTranslations::load() -{ - // Get the currently installed translations for Plasma - // TODO May want to later add all installed .po files on system? - m_installedTranslations.clear(); - - m_installedTranslations = KLocalizedString::availableDomainTranslations("systemsettings").toList(); - - // Load the current user translations - loadTranslations(); - - // Check if any of the current user translations are no longer installed - // If any missing remove them and save the settings, then tell the user - QStringList missingLanguages; - QStringList availableLanguages; - if (!m_config.isEntryImmutable(lcLanguage)) { - foreach (const QString &languageCode, m_kcmTranslations) { - if (m_installedTranslations.contains(languageCode)) { - availableLanguages.append(languageCode); - } else { - missingLanguages.append(languageCode); - } - } - m_config.writeEntry(lcLanguage, availableLanguages.join(QStringLiteral(":"))); - m_config.sync(); - m_config.config()->reparseConfiguration(); - loadTranslations(); - } - - // Then update all the widgets to use the new settings - initWidgets(); - - if (missingLanguages.count()) { - const QString txt = i18ncp("%1 is the language code", - "The translation files for the language with the code '%2' " - "could not be found. The " - "language has been removed from your configuration. " - "If you want to add it back, please install the " - "localization files for it and add the language again.", - - "The translation files for the languages with the codes " - "'%2' could not be found. These " - "languages have been removed from your configuration. " - "If you want to add them back, please install the " - "localization files for it and the languages again.", - missingLanguages.count(), - missingLanguages.join("', '")); - - m_messageWidget = new KMessageWidget(this); - m_messageWidget->setMessageType(KMessageWidget::Information); - m_messageWidget->setWordWrap(true); - m_messageWidget->setText(txt); - - m_ui->verticalLayout->insertWidget(0, m_messageWidget); - } -} - -// Reimp -// Save the new LANGUAGE setting -void KCMTranslations::save() -{ - m_config.writeEntry(lcLanguage, m_kcmTranslations.join(QStringLiteral(":")), KConfig::Persistent | KConfig::Global); - m_config.sync(); - KMessageBox::information(this, - i18n("Your changes will take effect the next time you log in."), - i18n("Applying Language Settings"), - QStringLiteral("LanguageChangesApplyOnlyToNewlyStartedPrograms")); - load(); - writeExports(); -} - -// Reimp -// Defaults == User has clicked on Defaults to load default settings -// We interpret this to mean the default LANG setting -void KCMTranslations::defaults() -{ - // Get the users LANG setting, or if empty the system LANG - KConfigGroup formatsConfig = KConfigGroup(KSharedConfig::openConfig(configFile), "Formats"); - - QString lang = formatsConfig.readEntry("LANG", QString()); - if (lang.isEmpty() || !m_installedTranslations.contains(lang)) { - lang = QLocale::system().name(); - } - if (!m_installedTranslations.contains(lang)) { - lang = QStringLiteral("en_US"); - } - - // Use the available lang as the default - m_kcmTranslations.clear(); - m_kcmTranslations.append(lang); - - // The update all the widgets to use the new language - initWidgets(); -} - -void KCMTranslations::loadTranslations() -{ - // Load the user translations - m_configTranslations = m_config.readEntry(lcLanguage, QString()); - m_kcmTranslations.clear(); - m_kcmTranslations = m_configTranslations.split(':', QString::SkipEmptyParts); -} - -QString KCMTranslations::quickHelp() const -{ - return i18n("

Translations

\n" - "

Here you can set your preferred language for translating the " - "user interface of your applications. You can choose a single " - "language, or a list of languages to be applied in sequence. Only " - "language translations that are installed on your system will " - "be listed as available. If your language is not listed then " - "you will need to install it first.

"); -} - -void KCMTranslations::initWidgets() -{ - initTranslations(); - initTranslationsInstall(); - // Init the KCM "Apply" button - emit changed(m_kcmTranslations.join(QStringLiteral(":")) != m_configTranslations); -} - -void KCMTranslations::initTranslations() -{ - m_ui->m_selectTranslations->blockSignals(true); - - m_ui->m_selectTranslations->setAvailableLabel(i18n("Available Languages:")); - QString availableHelp = i18n("This is the list of installed KDE Plasma language " - "translations not currently being used.
To use a language " - "translation move it to the 'Preferred Languages' list in " - "the order of preference.
If no suitable languages are " - "listed, then you may need to install more language packages " - "using your usual installation method."); - m_ui->m_selectTranslations->availableListWidget()->setToolTip(availableHelp); - m_ui->m_selectTranslations->availableListWidget()->setWhatsThis(availableHelp); - - m_ui->m_selectTranslations->setSelectedLabel(i18n("Preferred Languages:")); - QString selectedHelp = i18n("This is the list of installed KDE Plasma language " - "translations currently being used, listed in order of " - "preference.
If a translation is not available for the " - "first language in the list, the next language will be used.
" - "If no other translations are available then US English will " - "be used."); - m_ui->m_selectTranslations->selectedListWidget()->setToolTip(selectedHelp); - m_ui->m_selectTranslations->selectedListWidget()->setWhatsThis(selectedHelp); - - // Clear the selector before reloading - m_ui->m_selectTranslations->availableListWidget()->clear(); - m_ui->m_selectTranslations->selectedListWidget()->clear(); - - // Load each user selected language into the selected list - foreach (const QString &languageCode, m_kcmTranslations) { - QListWidgetItem *listItem = new QListWidgetItem(m_ui->m_selectTranslations->selectedListWidget()); - // TODO This gives the name in the language itself, not in current language, need new QLocale api for that - QString label = QLocale(languageCode).nativeLanguageName(); - if (label.isEmpty()) { - label = languageCode; - } - listItem->setText(label); - listItem->setData(Qt::UserRole, languageCode); - } - - // Load all the available languages the user hasn't selected into the available list - foreach (const QString &languageCode, m_installedTranslations) { - if (!m_kcmTranslations.contains(languageCode)) { - QListWidgetItem *listItem = new QListWidgetItem(m_ui->m_selectTranslations->availableListWidget()); - // TODO This gives the name in the language itself, not in current language, need new QLocale api for that - const QLocale l(languageCode); - QString label = l.nativeLanguageName(); - if (label.isEmpty()) { - label = languageCode; - } else if (languageCode.contains(QStringLiteral("@"))) { - label = i18nc("%1 is language name, %2 is language code name", "%1 (%2)", label, languageCode); - } else if (l.name() != languageCode) { - if (m_installedTranslations.contains(l.name())) { - // KDE languageCode got translated by QLocale to a locale code we also have on the list - // Currently only this happens with pt that gets trasnated to pt_BR - if (languageCode == QLatin1String("pt")) { - label = QLocale(QStringLiteral("pt_PT")).nativeLanguageName(); - } else { - qWarning() << "Language code morphed into another existing language code, please report" << languageCode << l.name(); - label = i18nc("%1 is language name, %2 is language code name", "%1 (%2)", label, languageCode); - } - } - } - listItem->setText(label); - listItem->setData(Qt::UserRole, languageCode); - } - } - m_ui->m_selectTranslations->availableListWidget()->sortItems(); - - // Default to selecting the first Selected language, - // otherwise the first Available language, - // otherwise no languages so disable all buttons - if (m_ui->m_selectTranslations->selectedListWidget()->count() > 0) { - m_ui->m_selectTranslations->selectedListWidget()->setCurrentRow(0); - } else if (m_ui->m_selectTranslations->availableListWidget()->count() > 0) { - m_ui->m_selectTranslations->availableListWidget()->setCurrentRow(0); - } - - // If the setting is locked down by Kiosk, then don't let the user make any changes - if (m_config.isEntryImmutable(lcLanguage)) { - m_ui->m_selectTranslations->setEnabled(false); - } - - m_ui->m_selectTranslations->blockSignals(false); -} - -void KCMTranslations::changedTranslationsAvailable(QListWidgetItem *item) -{ - Q_UNUSED(item); - m_ui->m_selectTranslations->availableListWidget()->sortItems(); - int row = m_ui->m_selectTranslations->availableListWidget()->currentRow(); - changedTranslations(); - m_ui->m_selectTranslations->availableListWidget()->setCurrentRow(row); -} - -void KCMTranslations::changedTranslationsSelected(QListWidgetItem *item) -{ - Q_UNUSED(item); - int row = m_ui->m_selectTranslations->selectedListWidget()->currentRow(); - changedTranslations(); - m_ui->m_selectTranslations->selectedListWidget()->setCurrentRow(row); -} - -void KCMTranslations::changedTranslations() -{ - // Read the list of all Selected translations from the selector widget - m_kcmTranslations.clear(); - for (int i = 0; i < m_ui->m_selectTranslations->selectedListWidget()->count(); ++i) { - m_kcmTranslations.append(m_ui->m_selectTranslations->selectedListWidget()->item(i)->data(Qt::UserRole).toString()); - } - initWidgets(); -} - -void KCMTranslations::initTranslationsInstall() -{ - m_ui->m_buttonTranslationsInstall->blockSignals(true); - m_ui->m_buttonTranslationsInstall->setText(i18n("Install more languages")); - QString helpText = i18n("

Click here to install more languages

"); - m_ui->m_buttonTranslationsInstall->setToolTip(helpText); - m_ui->m_buttonTranslationsInstall->setWhatsThis(helpText); - m_ui->m_buttonTranslationsInstall->blockSignals(false); -} - -void KCMTranslations::installTranslations() -{ - // User has clicked Install Languages button, trigger distro specific install routine -} - -#include "kcmtranslations.moc" diff --git a/kcms/translations/kcmtranslationswidget.ui b/kcms/translations/kcmtranslationswidget.ui deleted file mode 100644 --- a/kcms/translations/kcmtranslationswidget.ui +++ /dev/null @@ -1,87 +0,0 @@ - - - KCMTranslationsWidget - - - - 0 - 0 - 687 - 333 - - - - - 0 - 0 - - - - - - - - - - 0 - 0 - - - - Available &Translations: - - - Preferred Trans&lations: - - - - - - - false - - - Install more translations - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - Qt::Vertical - - - - 20 - 40 - - - - - - - - - - - KActionSelector - QWidget -
kactionselector.h
-
-
- - -
diff --git a/kcms/translations/package/contents/ui/main.qml b/kcms/translations/package/contents/ui/main.qml new file mode 100644 --- /dev/null +++ b/kcms/translations/package/contents/ui/main.qml @@ -0,0 +1,253 @@ +/* + * Copyright (C) 2015 Marco Martin + * Copyright (C) 2018 Eike Hein + * + * 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. +*/ + +import QtQuick 2.1 +import QtQuick.Layouts 1.1 +import QtQuick.Controls 2.3 as QtControls +import org.kde.kirigami 2.4 as Kirigami +import org.kde.plasma.core 2.1 as PlasmaCore +import org.kde.kcm 1.1 + +SimpleKCM { + id: root + + ConfigModule.quickHelp: i18n("Language") + + topPadding: 0 + leftPadding: 0 + rightPadding: 0 + bottomPadding: 0 + + Kirigami.OverlaySheet { + id: addLanguagesSheet + + parent: root.parent + + topPadding: 0 + leftPadding: 0 + rightPadding: 0 + bottomPadding: 0 + + header: Kirigami.Heading { text: i18n("Add Languages") } + + property var selectedLanguages: [] + + ListView { + implicitWidth: Kirigami.Units.gridUnit * 18 + implicitHeight: Kirigami.Units.gridUnit * 15 + + model: PlasmaCore.SortFilterModel { + id: availableLanguagesModel + + sourceModel: addLanguagesSheet.sheetOpen ? kcm.translationsModel : null + + filterRole: "IsSelected" + filterCallback: function(source_row, value) { return !value; } + + sortRole: "display" + } + + delegate: Kirigami.BasicListItem { + Layout.fillWidth: true + + property string languageCode: model.LanguageCode + + reserveSpaceForIcon: false + + label: model.display + + checkable: true + onCheckedChanged: { + if (checked) { + addLanguagesSheet.selectedLanguages.push(index); + } else { + addLanguagesSheet.selectedLanguages = addLanguagesSheet.selectedLanguages.filter(function(item) { return item !== index }) + } + } + } + } + + footer: QtControls.Button { + width: parent.width + + text: i18n("Add") + + onClicked: { + var langs = []; + addLanguagesSheet.selectedLanguages.sort().forEach(function(index) { + langs.push(availableLanguagesModel.get(index).LanguageCode); + }); + + if (addLanguagesSheet.selectedLanguages.length) { + if (kcm.translationsModel.selectedLanguages.length) { + kcm.translationsModel.selectedLanguages = kcm.translationsModel.selectedLanguages.concat(langs); + } else { + kcm.translationsModel.selectedLanguages = langs; + } + } + + addLanguagesSheet.sheetOpen = false; + } + } + } + + header: QtControls.Control { + width: parent.width + height: messagesLayout.implicitHeight + (messagesLayout.implicitHeight ? bottomPadding : 0) + + bottomPadding: Kirigami.Units.smallSpacing + + ColumnLayout { + id: messagesLayout + + width: parent.width + + spacing: Kirigami.Units.largeSpacing + + Kirigami.InlineMessage { + Layout.fillWidth: true + Layout.leftMargin: Kirigami.Units.smallSpacing + Layout.rightMargin: Kirigami.Units.smallSpacing + + type: kcm.everSaved ? Kirigami.MessageType.Positive : Kirigami.MessageType.Information + + text: (kcm.everSaved ? i18n("Your changes will take effect the next time you log in.") + : i18n("There are currently no preferred languages configured.")) + + visible: !languagesList.count || kcm.everSaved + } + + Kirigami.InlineMessage { + Layout.fillWidth: true + Layout.leftMargin: Kirigami.Units.smallSpacing + Layout.rightMargin: Kirigami.Units.smallSpacing + + type: Kirigami.MessageType.Error + + text: i18ncp("%2 is the language code", + "The translation files for the language with the code '%2' could not be found. The language will be removed from your configuration. If you want to add it back, please install the localization files for it and add the language again.", + "The translation files for the languages with the codes '%2' could not be found. These languages will be removed from your configuration. If you want to add them back, please install the localization files for it and the languages again.", + kcm.translationsModel.missingLanguages.length, + kcm.translationsModel.missingLanguages.join("', '")) + + visible: kcm.translationsModel.missingLanguages.length + } + } + } + + ListView { + id: languagesList + + Layout.fillWidth: true + + model: PlasmaCore.SortFilterModel { + sourceModel: kcm.translationsModel + + filterRole: "IsSelected" + filterCallback: function(source_row, value) { return value; } + + sortRole: "SelectedPriority" + } + + delegate: Kirigami.SwipeListItem { + id: listItem + + Layout.fillWidth: true + Layout.margins: 0 + + contentItem: RowLayout { + width: implicitWidth + height: Math.max(implicitHeight, Kirigami.Units.iconSizes.smallMedium) + + anchors.verticalCenter: parent.verticalCenter + + Kirigami.Icon { + visible: model.IsMissing + + Layout.alignment: Qt.AlignVCenter + + width: Kirigami.Units.iconSizes.smallMedium + height: width + + source: "error" + color: Kirigami.Theme.negativeTextColor + } + + QtControls.Label { + Layout.fillWidth: true + + Layout.alignment: Qt.AlignVCenter + + text: model.display + + color: (model.IsMissing ? Kirigami.Theme.negativeTextColor + : (listItem.checked || (listItem.pressed && !listItem.checked && !listItem.sectionDelegate) + ? listItem.activeTextColor : listItem.textColor)) + } + } + + actions: [ + Kirigami.Action { + enabled: !model.IsMissing && index > 0 + iconName: "arrow-up" + onTriggered: kcm.translationsModel.selectedLanguages.splice(index - 1, 0, kcm.translationsModel.selectedLanguages.splice(index, 1)[0]) + + }, + Kirigami.Action { + enabled: !model.IsMissing && index < (languagesList.count - 1) + iconName: "arrow-down" + onTriggered: kcm.translationsModel.selectedLanguages.splice(index + 1, 0, kcm.translationsModel.selectedLanguages.splice(index, 1)[0]) + + }, + Kirigami.Action { + enabled: !model.IsMissing + iconName: "list-remove" + onTriggered: kcm.translationsModel.selectedLanguages = kcm.translationsModel.selectedLanguages.filter(function(item) { return item !== model.LanguageCode }) + }] + } + } + + footer: QtControls.Control { + width: parent.width + height: footerLayout.implicitHeight + topPadding + + topPadding: Kirigami.Units.smallSpacing + leftPadding: Kirigami.Units.smallSpacing + rightPadding: Kirigami.Units.smallSpacing + + RowLayout { + id: footerLayout + + width: parent.width + + QtControls.Button { + Layout.alignment: Qt.AlignHCenter + + text: i18n("Add languages...") + + onClicked: addLanguagesSheet.sheetOpen = !addLanguagesSheet.sheetOpen + + checkable: true + checked: addLanguagesSheet.sheetOpen + } + } + } +} + diff --git a/kcms/translations/translations.desktop b/kcms/translations/package/metadata.desktop rename from kcms/translations/translations.desktop rename to kcms/translations/package/metadata.desktop --- a/kcms/translations/translations.desktop +++ b/kcms/translations/package/metadata.desktop @@ -1,16 +1,4 @@ [Desktop Entry] -Exec=kcmshell5 translations -Icon=preferences-desktop-locale -Type=Service -X-KDE-ServiceTypes=KCModule -X-DocPath=kcontrol/translations/index.html - -X-KDE-Library=kcm_translations -X-KDE-ParentApp=kcontrol - -X-KDE-System-Settings-Parent-Category=regionalsettings -X-KDE-Weight=40 - Name=Language Name[ca]=Idioma Name[ca@valencia]=Idioma @@ -52,4 +40,11 @@ Name[zh_CN]=语言 Name[zh_TW]=語言 -Categories=Qt;KDE;X-KDE-settings-translations; +Icon=preferences-desktop-locale +Type=Service +X-KDE-PluginInfo-License=GPL +X-KDE-PluginInfo-Name=kcm_translations +X-KDE-ServiceTypes=Plasma/Generic +X-Plasma-API=declarativeappletscript + +X-Plasma-MainScript=ui/main.qml diff --git a/kcms/translations/translations.h b/kcms/translations/translations.h new file mode 100644 --- /dev/null +++ b/kcms/translations/translations.h @@ -0,0 +1,68 @@ +/* + * Copyright (C) 2014 John Layt + * Copyright (C) 2018 Eike Hein + * + * 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. + */ + +#ifndef TRANSLATIONS_H +#define TRANSLATIONS_H + +#include + +#include + +class TranslationsModel; + +class QAbstractListModel; + +class Translations : public KQuickAddons::ConfigModule +{ + Q_OBJECT + + Q_PROPERTY(QAbstractItemModel* translationsModel READ translationsModel CONSTANT) + Q_PROPERTY(bool everSaved READ everSaved NOTIFY everSavedChanged) + + public: + explicit Translations(QObject* parent = 0, const QVariantList &list = QVariantList()); + ~Translations() override; + + QAbstractItemModel* translationsModel() const; + + bool everSaved() const; + + public Q_SLOTS: + void load(); + void save(); + void defaults(); + + Q_SIGNALS: + void everSavedChanged() const; + + private Q_SLOTS: + void selectedLanguagesChanged(); + void missingLanguagesChanged(); + + private: + TranslationsModel *m_translationsModel; + + KConfigGroup m_config; + QStringList m_configuredLanguages; + + bool m_everSaved; +}; + +#endif diff --git a/kcms/translations/translations.cpp b/kcms/translations/translations.cpp new file mode 100644 --- /dev/null +++ b/kcms/translations/translations.cpp @@ -0,0 +1,127 @@ +/* + * Copyright (C) 2014 John Layt + * Copyright (C) 2018 Eike Hein + * + * 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 "translations.h" +#include "translationsmodel.h" + +#include "../formats/writeexports.h" + +#include +#include +#include +#include + +K_PLUGIN_FACTORY_WITH_JSON(TranslationsFactory, "kcm_translations.json", registerPlugin();) + +Translations::Translations(QObject *parent, const QVariantList &args) + : KQuickAddons::ConfigModule(parent, args) + , m_translationsModel(new TranslationsModel(this)) + , m_everSaved(false) +{ + KAboutData *about = new KAboutData("kcm_translations", + i18n("Configure Plasma translations"), + "2.0", QString(), KAboutLicense::LGPL); + setAboutData(about); + + setButtons(Apply | Default); + + m_config = KConfigGroup(KSharedConfig::openConfig(configFile), "Translations"); + + connect(m_translationsModel, &TranslationsModel::selectedLanguagesChanged, + this, &Translations::selectedLanguagesChanged); + connect(m_translationsModel, &TranslationsModel::missingLanguagesChanged, + this, &Translations::missingLanguagesChanged); +} + +Translations::~Translations() +{ +} + +QAbstractItemModel* Translations::translationsModel() const +{ + return m_translationsModel; +} + +bool Translations::everSaved() const +{ + return m_everSaved; +} + +void Translations::load() +{ + m_configuredLanguages = m_config.readEntry(lcLanguage, + QString()).split(':', QString::SkipEmptyParts); + + m_translationsModel->setSelectedLanguages(m_configuredLanguages); +} + +void Translations::save() +{ + m_everSaved = true; + emit everSavedChanged(); + + m_configuredLanguages = m_translationsModel->selectedLanguages(); + qDebug() << m_configuredLanguages; + + for (const QString& lang : m_translationsModel->missingLanguages()) { + m_configuredLanguages.removeOne(lang); + } + + m_config.writeEntry(lcLanguage, m_configuredLanguages.join(QStringLiteral(":")), + KConfig::Persistent | KConfig::Global); + m_config.sync(); + + m_translationsModel->setSelectedLanguages(m_configuredLanguages); +} + +void Translations::defaults() +{ + KConfigGroup formatsConfig = KConfigGroup(KSharedConfig::openConfig(configFile), "Formats"); + + QString lang = formatsConfig.readEntry("LANG", QString()); + + if (lang.isEmpty() + || !KLocalizedString::availableDomainTranslations("systemsettings").contains(lang)) { + lang = QLocale::system().name(); + } + + if (!KLocalizedString::availableDomainTranslations("systemsettings").contains(lang)) { + lang = QStringLiteral("en_US"); + } + + QStringList languages; + languages << lang; + + m_translationsModel->setSelectedLanguages(languages); +} + +void Translations::selectedLanguagesChanged() +{ + setNeedsSave(m_configuredLanguages != m_translationsModel->selectedLanguages()); +} + +void Translations::missingLanguagesChanged() +{ + if (m_translationsModel->missingLanguages().count()) { + setNeedsSave(true); + } +} + +#include "translations.moc" diff --git a/kcms/translations/translationsmodel.h b/kcms/translations/translationsmodel.h new file mode 100644 --- /dev/null +++ b/kcms/translations/translationsmodel.h @@ -0,0 +1,76 @@ +/* + * Copyright (C) 2014 John Layt + * Copyright (C) 2018 Eike Hein + * + * 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. + */ + +#ifndef TRANSLATIONSMODEL_H +#define TRANSLATIONSMODEL_H + +#include + +#include + +#include + +class TranslationsModel : public QAbstractListModel +{ + Q_OBJECT + + Q_PROPERTY(QStringList selectedLanguages READ selectedLanguages WRITE setSelectedLanguages NOTIFY selectedLanguagesChanged) + Q_PROPERTY(QStringList missingLanguages READ missingLanguages NOTIFY missingLanguagesChanged) + + public: + enum AdditionalRoles { + LanguageCode = Qt::UserRole + 1, + IsSelected, + SelectedPriority, + IsMissing + }; + Q_ENUM(AdditionalRoles) + + explicit TranslationsModel(QObject *parent = nullptr); + ~TranslationsModel() override; + + QHash roleNames() const override; + + QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override; + int rowCount(const QModelIndex &parent = QModelIndex()) const override; + + QStringList selectedLanguages() const; + void setSelectedLanguages(const QStringList &languages); + + QStringList missingLanguages() const; + + Q_SIGNALS: + void selectedLanguagesChanged() const; + void missingLanguagesChanged() const; + + private: + QString languageCodeToName(const QString& languageCode) const; + + KConfigGroup m_config; + + QStringList m_languages; + + QSet m_installedLanguages; + + QStringList m_selectedLanguages; + QStringList m_missingLanguages; +}; + +#endif diff --git a/kcms/translations/translationsmodel.cpp b/kcms/translations/translationsmodel.cpp new file mode 100644 --- /dev/null +++ b/kcms/translations/translationsmodel.cpp @@ -0,0 +1,149 @@ +/* + * Copyright (C) 2014 John Layt + * Copyright (C) 2018 Eike Hein + * + * 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 + +#include +#include +#include + +TranslationsModel::TranslationsModel(QObject *parent) + : QAbstractListModel(parent) +{ + m_installedLanguages = KLocalizedString::availableDomainTranslations("systemsettings"); + m_languages = m_installedLanguages.toList(); +} + +TranslationsModel::~TranslationsModel() +{ +} + +QHash TranslationsModel::roleNames() const +{ + QHash 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 == IsSelected) { + return m_selectedLanguages.contains(m_languages.at(index.row())); + } else if (role == SelectedPriority) { + return m_selectedLanguages.indexOf(m_languages.at(index.row())); + } else if (role == IsMissing) { + return m_missingLanguages.contains(m_languages.at(index.row())); + } + + return QVariant(); +} + +int TranslationsModel::rowCount(const QModelIndex &parent) const +{ + if (parent.isValid()) { + return 0; + } + + return m_languages.count(); +} + +QStringList TranslationsModel::selectedLanguages() const +{ + return m_selectedLanguages; +} + + +void TranslationsModel::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; + m_languages = (m_installedLanguages | QSet::fromList(m_selectedLanguages)).toList(); + + endResetModel(); + + emit selectedLanguagesChanged(); + } +} + +QStringList TranslationsModel::missingLanguages() const +{ + return m_missingLanguages; +} + + +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(); + } else { + 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; +}