diff --git a/kcms/fonts/fonts.cpp b/kcms/fonts/fonts.cpp index 3e47b5ef1..f336518a7 100644 --- a/kcms/fonts/fonts.cpp +++ b/kcms/fonts/fonts.cpp @@ -1,711 +1,711 @@ /* Copyright 1997 Mark Donohoe Copyright 1999 Lars Knoll Copyright 2000 Rik Hemsley Copyright 2015 Antonis Tsiapaliokas Copyright 2017 Marco Martin Ported to kcontrol2 by Geert Jansen. 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 "fonts.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "../krdb/krdb.h" #include "previewimageprovider.h" /**** DLL Interface ****/ K_PLUGIN_FACTORY_WITH_JSON(KFontsFactory, "kcm_fonts.json", registerPlugin();) //from KFontRequester // Determine if the font with given properties is available on the system, // otherwise find and return the best fitting combination. static QFont nearestExistingFont(const QFont &font) { QFontDatabase dbase; // Initialize font data according to given font object. QString family = font.family(); QString style = dbase.styleString(font); qreal size = font.pointSizeF(); // Check if the family exists. const QStringList families = dbase.families(); if (!families.contains(family)) { // Chose another family. family = QFontInfo(font).family(); // the nearest match if (!families.contains(family)) { family = families.count() ? families.at(0) : QStringLiteral("fixed"); } } // Check if the family has the requested style. // Easiest by piping it through font selection in the database. QString retStyle = dbase.styleString(dbase.font(family, style, 10)); style = retStyle; // Check if the family has the requested size. // Only for bitmap fonts. if (!dbase.isSmoothlyScalable(family, style)) { QList sizes = dbase.smoothSizes(family, style); if (!sizes.contains(size)) { // Find nearest available size. int mindiff = 1000; int refsize = size; Q_FOREACH (int lsize, sizes) { int diff = qAbs(refsize - lsize); if (mindiff > diff) { mindiff = diff; size = lsize; } } } } // Select the font with confirmed properties. QFont result = dbase.font(family, style, int(size)); if (dbase.isSmoothlyScalable(family, style) && result.pointSize() == floor(size)) { result.setPointSizeF(size); } return result; } /**** FontAASettings ****/ #if defined(HAVE_FONTCONFIG) && defined (HAVE_X11) FontAASettings::FontAASettings(QObject *parent) : QObject(parent) , m_subPixelOptionsModel(new QStandardItemModel(this)) , m_hintingOptionsModel(new QStandardItemModel(this)) { for (int t = KXftConfig::SubPixel::NotSet; t <= KXftConfig::SubPixel::Vbgr; ++t) { QStandardItem *item = new QStandardItem(KXftConfig::description((KXftConfig::SubPixel::Type)t)); m_subPixelOptionsModel->appendRow(item); } for (int s = KXftConfig::Hint::NotSet; s <= KXftConfig::Hint::Full; ++s) { QStandardItem * item = new QStandardItem(KXftConfig::description((KXftConfig::Hint::Style)s)); m_hintingOptionsModel->appendRow(item); } } void FontAASettings::load() { double from, to; KXftConfig xft; if (xft.getExcludeRange(from, to)) { m_excludeFrom = from; m_excludeTo = to; setExclude(true); } else { m_excludeFrom = 8; m_excludeTo = 15; setExclude(false); } m_excludeFromOriginal = m_excludeFrom; m_excludeToOriginal = m_excludeTo; excludeToChanged(); excludeFromChanged(); KXftConfig::SubPixel::Type spType; xft.getSubPixelType(spType); setSubPixelCurrentIndex(spType); m_subPixelCurrentIndexOriginal = spType; KXftConfig::Hint::Style hStyle; if (!xft.getHintStyle(hStyle) || KXftConfig::Hint::NotSet == hStyle) { KConfig kglobals("kdeglobals", KConfig::NoGlobals); hStyle = KXftConfig::Hint::NotSet; xft.setHintStyle(hStyle); KConfigGroup(&kglobals, "General").writeEntry("XftHintStyle", KXftConfig::toStr(hStyle)); kglobals.sync(); runRdb(KRdbExportXftSettings | KRdbExportGtkTheme); } setHintingCurrentIndex(hStyle); m_hintingCurrentIndexOriginal = hStyle; KConfig _cfgfonts("kcmfonts"); KConfigGroup cfgfonts(&_cfgfonts, "General"); int dpicfg; if (KWindowSystem::isPlatformWayland()) { dpicfg = cfgfonts.readEntry("forceFontDPIWayland", 0); } else { dpicfg = cfgfonts.readEntry("forceFontDPI", 0); } if (dpicfg <= 0) { m_dpiOriginal = 0; } else { m_dpiOriginal = dpicfg; }; setDpi(dpicfg); KSharedConfig::Ptr config = KSharedConfig::openConfig("kdeglobals"); KConfigGroup cg(config, "General"); if (cfgfonts.readEntry("dontChangeAASettings", true)) { setAntiAliasing(1); //AASystem } else if (cg.readEntry("XftAntialias", true)) { setAntiAliasing(0); //AAEnabled } else { setAntiAliasing(2); //AADisabled } m_antiAliasingOriginal = m_antiAliasing; } bool FontAASettings::save(KXftConfig::AntiAliasing::State aaState) { KXftConfig xft; KConfig kglobals("kdeglobals", KConfig::NoGlobals); KConfigGroup grp(&kglobals, "General"); xft.setAntiAliasing(aaState); if (m_exclude) { xft.setExcludeRange(m_excludeFrom, m_excludeTo); } else { xft.setExcludeRange(0, 0); } KXftConfig::SubPixel::Type spType = (KXftConfig::SubPixel::Type)m_subPixelCurrentIndex; xft.setSubPixelType(spType); grp.writeEntry("XftSubPixel", KXftConfig::toStr(spType)); if (aaState == KXftConfig::AntiAliasing::NotSet) { grp.revertToDefault("XftAntialias"); } else { grp.writeEntry("XftAntialias", aaState == KXftConfig::AntiAliasing::Enabled); } bool mod = false; KXftConfig::Hint::Style hStyle = (KXftConfig::Hint::Style)m_hintingCurrentIndex; xft.setHintStyle(hStyle); QString hs(KXftConfig::toStr(hStyle)); if (hs != grp.readEntry("XftHintStyle")) { if (KXftConfig::Hint::NotSet == hStyle) { grp.revertToDefault("XftHintStyle"); } else { grp.writeEntry("XftHintStyle", hs); } } mod = true; kglobals.sync(); if (!mod) { mod = xft.changed(); } xft.apply(); KConfig _cfgfonts("kcmfonts"); KConfigGroup cfgfonts(&_cfgfonts, "General"); if (KWindowSystem::isPlatformWayland()) { cfgfonts.writeEntry("forceFontDPIWayland", m_dpi); } else { cfgfonts.writeEntry("forceFontDPI", m_dpi); } cfgfonts.sync(); #if HAVE_X11 // if the setting is reset in the module, remove the dpi value, // otherwise don't explicitly remove it and leave any possible system-wide value if (m_dpi == 0 && m_dpiOriginal != 0 && !KWindowSystem::isPlatformWayland()) { QProcess proc; proc.setProcessChannelMode(QProcess::ForwardedChannels); proc.start("xrdb", QStringList() << "-quiet" << "-remove" << "-nocpp"); if (proc.waitForStarted()) { proc.write(QByteArray("Xft.dpi\n")); proc.closeWriteChannel(); proc.waitForFinished(); } } #endif QApplication::processEvents(); // Process font change ourselves // Don't overwrite global settings unless explicitly asked for - e.g. the system // fontconfig setup may be much more complex than this module can provide. // TODO: With AASystem the changes already made by this module should be reverted somehow. #if defined(HAVE_FONTCONFIG) && defined (HAVE_X11) if (mod || (m_antiAliasing != m_antiAliasingOriginal) || m_dpi != m_dpiOriginal) { KMessageBox::information(nullptr, i18n( "

Some changes such as anti-aliasing or DPI will only affect newly started applications.

" ), i18n("Font Settings Changed"), "FontSettingsChanged"); m_antiAliasingOriginal = m_antiAliasing; m_dpiOriginal = m_dpi; } #else #if HAVE_X11 if (m_dpi != m_dpiOriginal) { KMessageBox::information(0, i18n( "

Some changes such as DPI will only affect newly started applications.

" ), i18n("Font Settings Changed"), "FontSettingsChanged"); m_dpiOriginal = m_dpi; } #endif #endif m_excludeToOriginal = m_excludeTo; m_excludeFromOriginal = m_excludeFrom; m_subPixelCurrentIndexOriginal = m_subPixelCurrentIndex; m_hintingCurrentIndexOriginal = m_hintingCurrentIndex; return mod; } void FontAASettings::defaults() { setExcludeTo(15); setExcludeFrom(8); setAntiAliasing(1); m_antiAliasingOriginal = m_antiAliasing; setDpi(0); setSubPixelCurrentIndex(KXftConfig::SubPixel::NotSet); setHintingCurrentIndex(KXftConfig::Hint::NotSet); } #endif void FontAASettings::setExclude(bool exclude) { if (exclude == m_exclude) { return; } m_exclude = exclude; emit excludeChanged(); } bool FontAASettings::exclude() const { return m_exclude; } void FontAASettings::setExcludeTo(const int &excludeTo) { if (m_excludeTo == excludeTo) { return; } m_excludeTo = excludeTo; emit excludeToChanged(); } int FontAASettings::excludeTo() const { return m_excludeTo; } void FontAASettings::setExcludeFrom(const int &excludeTo) { if (m_excludeFrom == excludeTo) { return; } m_excludeFrom = excludeTo; emit excludeToChanged(); } int FontAASettings::excludeFrom() const { return m_excludeFrom; } void FontAASettings::setAntiAliasing(const int &antiAliasing) { if (m_antiAliasing == antiAliasing) { return; } m_antiAliasing = antiAliasing; emit aliasingChanged(); } int FontAASettings::antiAliasing() const { return m_antiAliasing; } void FontAASettings::setDpi(const int &dpi) { if (m_dpi == dpi) { return; } m_dpi = dpi; emit dpiChanged(); } int FontAASettings::dpi() const { return m_dpi; } void FontAASettings::setSubPixelCurrentIndex(int idx) { if (m_subPixelCurrentIndex == idx) { return; } m_subPixelCurrentIndex = idx; emit subPixelCurrentIndexChanged(); } int FontAASettings::subPixelCurrentIndex() { return m_subPixelCurrentIndex; } void FontAASettings::setHintingCurrentIndex(int idx) { if (m_hintingCurrentIndex == idx) { return; } m_hintingCurrentIndex = idx; emit hintingCurrentIndexChanged(); } int FontAASettings::hintingCurrentIndex() { return m_hintingCurrentIndex; } bool FontAASettings::needsSave() const { return m_excludeTo != m_excludeToOriginal || m_excludeFrom != m_excludeFromOriginal || m_antiAliasing != m_antiAliasingOriginal || m_dpi != m_dpiOriginal || m_subPixelCurrentIndex != m_subPixelCurrentIndexOriginal || m_hintingCurrentIndex != m_hintingCurrentIndexOriginal; } /**** KFonts ****/ KFonts::KFonts(QObject *parent, const QVariantList &args) : KQuickAddons::ConfigModule(parent, args) , m_fontAASettings(new FontAASettings(this)) { qApp->setAttribute(Qt::AA_DontCreateNativeWidgetSiblings); KAboutData* about = new KAboutData("kcm_fonts", i18n("Configure Fonts"), "0.1", QString(), KAboutLicense::LGPL); about->addAuthor(i18n("Antonis Tsiapaliokas"), QString(), "antonis.tsiapaliokas@kde.org"); setAboutData(about); qmlRegisterType(); - setButtons(Apply | Default); + setButtons(Apply | Default | Help); auto updateState = [this]() { setNeedsSave(m_fontAASettings->needsSave()); }; connect(m_fontAASettings, &FontAASettings::subPixelCurrentIndexChanged, this, updateState); connect(m_fontAASettings, &FontAASettings::hintingCurrentIndexChanged, this, updateState); connect(m_fontAASettings, &FontAASettings::excludeToChanged, this, updateState); connect(m_fontAASettings, &FontAASettings::antiAliasingChanged, this, updateState); connect(m_fontAASettings, &FontAASettings::aliasingChanged, this, updateState); connect(m_fontAASettings, &FontAASettings::dpiChanged, this, updateState); } KFonts::~KFonts() { } void KFonts::defaults() { #ifdef Q_OS_MAC setGeneralFont(QFont("Lucida Grande", 13)); setMenuFont(QFont("Lucida Grande", 13)); setFixedWidthFont(QFont("Monaco", 10)); setToolbarFont(QFont("Lucida Grande", 11)); setSmallFont(QFont("Lucida Grande", 9)); setWindowTitleFont(QFont("Lucida Grande", 14)); #else setGeneralFont(QFont("Noto Sans", 10)); setMenuFont(QFont("Noto Sans", 10)); setFixedWidthFont(QFont("Hack", 9)); setToolbarFont(QFont("Noto Sans", 10)); setSmallFont(QFont("Noto Sans", 8)); setWindowTitleFont(QFont("Noto Sans", 10)); #endif m_fontAASettings->defaults(); } void KFonts::load() { KSharedConfig::Ptr config = KSharedConfig::openConfig("kdeglobals"); KConfigGroup cg(config, "General"); m_generalFont = m_generalFontOriginal = nearestExistingFont(cg.readEntry("font", m_defaultFont)); m_fixedWidthFont = m_fixedWidthFontOriginal = nearestExistingFont(cg.readEntry("fixed", QFont("Hack", 9))); m_smallFont = m_smallFontOriginal = nearestExistingFont(cg.readEntry("smallestReadableFont", m_defaultFont)); m_toolbarFont = m_toolbarFontOriginal = nearestExistingFont(cg.readEntry("toolBarFont", m_defaultFont)); m_menuFont = m_menuFontOriginal = nearestExistingFont(cg.readEntry("menuFont", m_defaultFont)); cg = KConfigGroup(config, "WM"); m_windowTitleFont = m_windowTitleFontOriginal = nearestExistingFont(cg.readEntry("activeFont", m_defaultFont)); engine()->addImageProvider("preview", new PreviewImageProvider(generalFont())); emit generalFontChanged(); emit fixedWidthFontChanged(); emit smallFontChanged(); emit toolbarFontChanged(); emit menuFontChanged(); emit windowTitleFontChanged(); m_fontAASettings->load(); setNeedsSave(false); } void KFonts::save() { KSharedConfig::Ptr config = KSharedConfig::openConfig("kdeglobals"); KConfigGroup cg(config, "General"); cg.writeEntry("font", m_generalFont.toString()); cg.writeEntry("fixed", m_fixedWidthFont.toString()); cg.writeEntry("smallestReadableFont", m_smallFont.toString()); cg.writeEntry("toolBarFont", m_toolbarFont.toString()); cg.writeEntry("menuFont", m_menuFont.toString()); cg.sync(); cg = KConfigGroup(config, "WM"); cg.writeEntry("activeFont", m_windowTitleFont.toString()); cg.sync(); m_defaultFontOriginal = m_defaultFont; m_generalFontOriginal = m_generalFont; m_fixedWidthFontOriginal = m_fixedWidthFont; m_smallFontOriginal = m_smallFont; m_toolbarFontOriginal = m_toolbarFont; m_menuFontOriginal = m_menuFont; m_windowTitleFontOriginal = m_windowTitleFont; KConfig _cfgfonts("kcmfonts"); KConfigGroup cfgfonts(&_cfgfonts, "General"); FontAASettings::AASetting aaSetting = (FontAASettings::AASetting)m_fontAASettings->antiAliasing(); cfgfonts.writeEntry("dontChangeAASettings", aaSetting == FontAASettings::AASystem); if (aaSetting == FontAASettings::AAEnabled) { m_fontAASettings->save(KXftConfig::AntiAliasing::Enabled); } else if (aaSetting == FontAASettings::AADisabled) { m_fontAASettings->save(KXftConfig::AntiAliasing::Disabled); } else { m_fontAASettings->save(KXftConfig::AntiAliasing::NotSet); } KGlobalSettings::self()->emitChange(KGlobalSettings::FontChanged); runRdb(KRdbExportXftSettings | KRdbExportGtkTheme); emit fontsHaveChanged(); setNeedsSave(false); } void KFonts::updateNeedsSave() { setNeedsSave(m_defaultFontOriginal != m_defaultFont || m_generalFontOriginal != m_generalFont || m_fixedWidthFontOriginal != m_fixedWidthFont || m_smallFontOriginal != m_smallFont || m_toolbarFontOriginal != m_toolbarFont || m_menuFontOriginal != m_menuFont || m_windowTitleFontOriginal != m_windowTitleFont || m_fontAASettings->needsSave()); } void KFonts::setGeneralFont(const QFont &font) { if (m_generalFont == font) { return; } m_generalFont = font; emit generalFontChanged(); updateNeedsSave(); } QFont KFonts::generalFont() const { return m_generalFont; } void KFonts::setFixedWidthFont(const QFont &font) { if (m_fixedWidthFont == font) { return; } m_fixedWidthFont = font; emit fixedWidthFontChanged(); updateNeedsSave(); } QFont KFonts::fixedWidthFont() const { return m_fixedWidthFont; } void KFonts::setSmallFont(const QFont &font) { if (m_smallFont == font) { return; } m_smallFont = font; emit smallFontChanged(); updateNeedsSave(); } QFont KFonts::smallFont() const { return m_smallFont; } void KFonts::setToolbarFont(const QFont &font) { if (m_toolbarFont == font) { return; } m_toolbarFont = font; emit toolbarFontChanged(); updateNeedsSave(); } QFont KFonts::toolbarFont() const { return m_toolbarFont; } void KFonts::setMenuFont(const QFont &font) { if (m_menuFont == font) { return; } m_menuFont = font; emit menuFontChanged(); updateNeedsSave(); } QFont KFonts::menuFont() const { return m_menuFont; } void KFonts::setWindowTitleFont(const QFont &font) { if (m_windowTitleFont == font) { return; } m_windowTitleFont = font; emit windowTitleFontChanged(); updateNeedsSave(); } QFont KFonts::windowTitleFont() const { return m_windowTitleFont; } void KFonts::adjustAllFonts() { QFont font = m_generalFont; KFontChooser::FontDiffFlags fontDiffFlags; int ret = KFontDialog::getFontDiff(font, fontDiffFlags, KFontChooser::NoDisplayFlags); if (ret == KDialog::Accepted && fontDiffFlags) { setGeneralFont(applyFontDiff(m_generalFont, font, fontDiffFlags)); setMenuFont(applyFontDiff(m_menuFont, font, fontDiffFlags)); { const QFont adjustedFont = applyFontDiff(m_fixedWidthFont, font, fontDiffFlags); if (QFontInfo(adjustedFont).fixedPitch()) { setFixedWidthFont(adjustedFont); } } setToolbarFont(applyFontDiff(m_toolbarFont, font, fontDiffFlags)); setSmallFont(applyFontDiff(m_smallFont, font, fontDiffFlags)); setWindowTitleFont(applyFontDiff(m_windowTitleFont, font, fontDiffFlags)); } } QFont KFonts::applyFontDiff(const QFont &fnt, const QFont &newFont, int fontDiffFlags) { QFont font(fnt); if (fontDiffFlags & KFontChooser::FontDiffSize) { font.setPointSizeF(newFont.pointSizeF()); } if ((fontDiffFlags & KFontChooser::FontDiffFamily)) { font.setFamily(newFont.family()); } if (fontDiffFlags & KFontChooser::FontDiffStyle) { font.setWeight(newFont.weight()); font.setStyle(newFont.style()); font.setUnderline(newFont.underline()); font.setStyleName(newFont.styleName()); } return font; } #include "fonts.moc" diff --git a/kcms/launch/package/contents/ui/main.qml b/kcms/launch/package/contents/ui/main.qml index 5429c59f5..f4b7280c8 100644 --- a/kcms/launch/package/contents/ui/main.qml +++ b/kcms/launch/package/contents/ui/main.qml @@ -1,121 +1,122 @@ /* Copyright (c) 2017 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 version 2 as published by the Free Software Foundation. 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.0 as QtControls import org.kde.kirigami 2.3 as Kirigami import org.kde.kcm 1.1 SimpleKCM { id: root ConfigModule.quickHelp: i18n("Launch Feedback") + ConfigModule.buttons: ConfigModule.Help | ConfigModule.Defaults | ConfigModule.Apply function applyBusyCursorCurrentIndex() { if (kcm.busyCursorCurrentIndex == 0) { busyCursorDisabled.checked = true; } else if (kcm.busyCursorCurrentIndex == 1) { busyCursorStatic.checked = true; } else if (kcm.busyCursorCurrentIndex == 2) { busyCursorBlinking.checked = true; } else if (kcm.busyCursorCurrentIndex == 3) { busyCursorBouncing.checked = true; } } Kirigami.FormLayout { id: formLayout Connections { target: kcm onBusyCursorCurrentIndexChanged: applyBusyCursorCurrentIndex() onTaskManagerNotificationChanged: taskManagerNotification.checked = kcm.taskManagerNotification onNotificationTimeoutChanged: notificationTimeout.value = kcm.notificationTimeout } ColumnLayout { Kirigami.FormData.label: i18n("Cursor:") QtControls.RadioButton { id: busyCursorDisabled text: i18n("No Feedback") onCheckedChanged: Qt.callLater(function() { kcm.busyCursorCurrentIndex = 0; }) } QtControls.RadioButton { id: busyCursorStatic text: i18n("Static") onCheckedChanged: Qt.callLater(function() { kcm.busyCursorCurrentIndex = 1; }) } QtControls.RadioButton { id: busyCursorBlinking text: i18n("Blinking") onCheckedChanged: Qt.callLater(function() { kcm.busyCursorCurrentIndex = 2; }) } QtControls.RadioButton { id: busyCursorBouncing text: i18n("Bouncing") onCheckedChanged: Qt.callLater(function() { kcm.busyCursorCurrentIndex = 3; }) } } QtControls.CheckBox { id: taskManagerNotification Kirigami.FormData.label: i18n("Task Manager:") text: i18n("Enable animation") checked: kcm.taskManagerNotification onCheckedChanged: kcm.taskManagerNotification = checked } QtControls.SpinBox { id: notificationTimeout Kirigami.FormData.label: i18n("Stop animation after:") stepSize: 1 enabled: taskManagerNotification.checked value: kcm.notificationTimeout onValueChanged: kcm.notificationTimeout = value textFromValue: function(value, locale) { return i18np("%1 sec", "%1 secs", value)} } } Component.onCompleted: applyBusyCursorCurrentIndex() } diff --git a/kcms/translations/package/contents/ui/main.qml b/kcms/translations/package/contents/ui/main.qml index 7897b8650..8c6edc55d 100644 --- a/kcms/translations/package/contents/ui/main.qml +++ b/kcms/translations/package/contents/ui/main.qml @@ -1,260 +1,261 @@ /* * 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.5 as Kirigami import org.kde.plasma.core 2.1 as PlasmaCore import org.kde.kcm 1.2 ScrollViewKCM { id: root ConfigModule.quickHelp: i18n("Language") + ConfigModule.buttons: ConfigModule.Help | ConfigModule.Defaults | ConfigModule.Apply Component { id: addLanguageItemComponent Kirigami.BasicListItem { id: languageItem property string languageCode: model.LanguageCode reserveSpaceForIcon: false label: model.display checkable: true onCheckedChanged: { if (checked) { addLanguagesSheet.selectedLanguages.push(index); // There's no property change notification for pushing to an array // in a var prop, so we can't bind selectedLanguages.length to // addLanguagesButton.enabled. addLanguagesButton.enabled = true; } else { addLanguagesSheet.selectedLanguages = addLanguagesSheet.selectedLanguages.filter(function(item) { return item !== index }); // There's no property change notification for pushing to an array // in a var prop, so we can't bind selectedLanguages.length to // addLanguagesButton.enabled. if (!addLanguagesSheet.selectedLanguages.length) { addLanguagesButton.enabled = false; } } } data: [Connections { target: addLanguagesSheet onSheetOpenChanged: languageItem.checked = false }] } } Kirigami.OverlaySheet { id: addLanguagesSheet parent: root.parent topPadding: 0 leftPadding: 0 rightPadding: 0 bottomPadding: 0 header: Kirigami.Heading { text: i18nc("@title:window", "Add Languages") } property var selectedLanguages: [] onSheetOpenChanged: selectedLanguages = [] ListView { id: availableLanguagesList implicitWidth: 18 * Kirigami.Units.gridUnit model: kcm.availableTranslationsModel delegate: Kirigami.DelegateRecycler { width: parent.width sourceComponent: addLanguageItemComponent } } footer: RowLayout { QtControls.Button { id: addLanguagesButton Layout.alignment: Qt.AlignHCenter text: i18nc("@action:button", "Add") enabled: false onClicked: { var langs = kcm.selectedTranslationsModel.selectedLanguages.slice(); addLanguagesSheet.selectedLanguages.sort().forEach(function(index) { langs.push(kcm.availableTranslationsModel.langCodeAt(index)); }); kcm.selectedTranslationsModel.selectedLanguages = langs; addLanguagesSheet.sheetOpen = false; } } } } header: ColumnLayout { id: messagesLayout spacing: Kirigami.Units.largeSpacing Kirigami.InlineMessage { Layout.fillWidth: true type: Kirigami.MessageType.Information text: i18nc("@info", "There are no languages available on this system.") visible: !availableLanguagesList.count } Kirigami.InlineMessage { Layout.fillWidth: true type: kcm.everSaved ? Kirigami.MessageType.Positive : Kirigami.MessageType.Information text: (kcm.everSaved ? i18nc("@info", "Your changes will take effect the next time you log in.") : i18nc("@info", "There are currently no preferred languages configured.")) visible: !languagesList.count || kcm.everSaved } Kirigami.InlineMessage { Layout.fillWidth: true type: Kirigami.MessageType.Error text: i18ncp("@info %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.selectedTranslationsModel.missingLanguages.length, kcm.selectedTranslationsModel.missingLanguages.join("', '")) visible: kcm.selectedTranslationsModel.missingLanguages.length } QtControls.Label { Layout.fillWidth: true visible: languagesList.count text: i18n("The language at the top of this list is the one you want to see and use most often.") } } Component { id: languagesListItemComponent Kirigami.SwipeListItem { id: listItem contentItem: RowLayout { Kirigami.ListItemDragHandle { listItem: listItem listView: languagesList onMoveRequested: kcm.selectedTranslationsModel.move(oldIndex, newIndex) } 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: (index == 0) ? i18nc("@item:inlistbox 1 = Language name", "%1 (Default)", model.display) : 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: "go-top" tooltip: i18nc("@info:tooltip", "Promote to default") onTriggered: kcm.selectedTranslationsModel.move(index, 0) }, Kirigami.Action { enabled: !model.IsMissing iconName: "list-remove" tooltip: i18nc("@info:tooltip", "Remove") onTriggered: kcm.selectedTranslationsModel.remove(model.LanguageCode) }] } } view: ListView { id: languagesList model: kcm.selectedTranslationsModel delegate: Kirigami.DelegateRecycler { width: languagesList.width sourceComponent: languagesListItemComponent } } footer: RowLayout { id: footerLayout QtControls.Button { Layout.alignment: Qt.AlignRight enabled: availableLanguagesList.count text: i18nc("@action:button", "Add languages...") onClicked: addLanguagesSheet.sheetOpen = !addLanguagesSheet.sheetOpen checkable: true checked: addLanguagesSheet.sheetOpen } } } diff --git a/kcms/workspaceoptions/package/contents/ui/main.qml b/kcms/workspaceoptions/package/contents/ui/main.qml index 21125c1c1..1f69c0156 100644 --- a/kcms/workspaceoptions/package/contents/ui/main.qml +++ b/kcms/workspaceoptions/package/contents/ui/main.qml @@ -1,81 +1,83 @@ /* * Copyright 2018 Furkan Tokac * * 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. */ import QtQuick 2.7 import QtQuick.Controls 2.4 as Controls import QtQuick.Layouts 1.3 as Layouts import org.kde.kirigami 2.4 as Kirigami -import org.kde.kcm 1.1 as KCM +import org.kde.kcm 1.2 as KCM import org.kde.plasma.core 2.0 as PlasmaCore KCM.SimpleKCM { id: root + KCM.ConfigModule.buttons: KCM.ConfigModule.Help | KCM.ConfigModule.Defaults | KCM.ConfigModule.Apply + Kirigami.FormLayout { id: formLayout // Visaul behavior settings Controls.CheckBox { id: showToolTips Kirigami.FormData.label: i18n("Visual behavior:") text: i18n("Display informational tooltips on mouse hover") checked: kcm.toolTip onCheckedChanged: kcm.toolTip = checked } Controls.CheckBox { id: showVisualFeedback text: i18n("Display visual feedback for status changes") checked: kcm.visualFeedback onCheckedChanged: kcm.visualFeedback = checked } Connections { target: kcm onToolTipChanged: showToolTips.checked = kcm.toolTip onVisualFeedbackChanged: showVisualFeedback.checked = kcm.visualFeedback } Item { Kirigami.FormData.isSection: false } // Click behavior settings Controls.RadioButton { id: singleClick Kirigami.FormData.label: i18n("Click behavior:") text: i18n("Single-click to open files and folders") checked: kcm.singleClick onCheckedChanged: kcm.singleClick = checked } Controls.RadioButton { id: doubleClick text: i18n("Double-click to open files and folders (single click to select)") } Connections { target: kcm onSingleClickChanged: { singleClick.checked = kcm.singleClick doubleClick.checked = !singleClick.checked } } } }