File indexing completed on 2024-05-19 05:38:05

0001 /*
0002     SPDX-FileCopyrightText: 1997 Mark Donohoe
0003     SPDX-FileCopyrightText: 1999 Lars Knoll
0004     SPDX-FileCopyrightText: 2000 Rik Hemsley
0005     SPDX-FileCopyrightText: 2015 Antonis Tsiapaliokas <antonis.tsiapaliokas@kde.org>
0006     SPDX-FileCopyrightText: 2017 Marco Martin <mart@kde.org>
0007     SPDX-FileCopyrightText: 2019 Benjamin Port <benjamin.port@enioka.com>
0008 
0009     Ported to kcontrol2:
0010     SPDX-FileCopyrightText: Geert Jansen
0011 
0012     SPDX-License-Identifier: LGPL-2.0-or-later
0013 */
0014 
0015 #include "fonts.h"
0016 
0017 #include <QApplication>
0018 #include <QDBusConnection>
0019 #include <QDBusMessage>
0020 #include <QFontDatabase>
0021 #include <QProcess>
0022 #include <QQmlEngine>
0023 #include <QQuickItem>
0024 #include <QQuickView>
0025 #include <QWindow>
0026 
0027 #include <KAcceleratorManager>
0028 #include <KConfig>
0029 #include <KConfigGroup>
0030 #include <KFontChooserDialog>
0031 #include <KLocalizedString>
0032 #include <KPluginFactory>
0033 #include <KWindowSystem>
0034 
0035 #include "../kcms-common_p.h"
0036 #include "krdb.h"
0037 #include "kxftconfig.h"
0038 #include "previewimageprovider.h"
0039 
0040 #include "fontsdata.h"
0041 
0042 /**** DLL Interface ****/
0043 K_PLUGIN_FACTORY_WITH_JSON(KFontsFactory, "kcm_fonts.json", registerPlugin<KFonts>(); registerPlugin<FontsData>();)
0044 
0045 /**** KFonts ****/
0046 
0047 KFonts::KFonts(QObject *parent, const KPluginMetaData &metaData)
0048     : KQuickManagedConfigModule(parent, metaData)
0049     , m_data(new FontsData(this))
0050     , m_subPixelOptionsModel(new QStandardItemModel(this))
0051     , m_hintingOptionsModel(new QStandardItemModel(this))
0052 {
0053     qmlRegisterAnonymousType<QStandardItemModel>("QStandardItemModel", 1);
0054     qmlRegisterAnonymousType<FontsSettings>("FontsSettings", 1);
0055     qmlRegisterAnonymousType<FontsAASettings>("FontsAASettings", 1);
0056 
0057     setButtons(Apply | Default | Help);
0058 
0059     for (KXftConfig::SubPixel::Type t :
0060          {KXftConfig::SubPixel::None, KXftConfig::SubPixel::Rgb, KXftConfig::SubPixel::Bgr, KXftConfig::SubPixel::Vrgb, KXftConfig::SubPixel::Vbgr}) {
0061         auto item = new QStandardItem(KXftConfig::description(t));
0062         m_subPixelOptionsModel->appendRow(item);
0063     }
0064 
0065     for (KXftConfig::Hint::Style s : {KXftConfig::Hint::None, KXftConfig::Hint::Slight, KXftConfig::Hint::Medium, KXftConfig::Hint::Full}) {
0066         auto item = new QStandardItem(KXftConfig::description(s));
0067         m_hintingOptionsModel->appendRow(item);
0068     }
0069     connect(fontsAASettings(), &FontsAASettings::hintingChanged, this, &KFonts::hintingCurrentIndexChanged);
0070     connect(fontsAASettings(), &FontsAASettings::subPixelChanged, this, &KFonts::subPixelCurrentIndexChanged);
0071 }
0072 
0073 KFonts::~KFonts()
0074 {
0075 }
0076 
0077 FontsSettings *KFonts::fontsSettings() const
0078 {
0079     return m_data->fontsSettings();
0080 }
0081 
0082 FontsAASettings *KFonts::fontsAASettings() const
0083 {
0084     return m_data->fontsAASettings();
0085 }
0086 
0087 QAbstractItemModel *KFonts::subPixelOptionsModel() const
0088 {
0089     return m_subPixelOptionsModel;
0090 }
0091 
0092 QAbstractItemModel *KFonts::hintingOptionsModel() const
0093 {
0094     return m_hintingOptionsModel;
0095 }
0096 
0097 void KFonts::load()
0098 {
0099     // first load all the settings
0100     KQuickManagedConfigModule::load();
0101 
0102     // Load preview
0103     // NOTE: This needs to be done AFTER AA settings is loaded
0104     // otherwise AA settings will be reset in process of loading
0105     // previews
0106     engine()->addImageProvider("preview", new PreviewImageProvider(fontsSettings()->font()));
0107 
0108     // KCM expect save state to be false at this point (can be true because if a font setting loaded
0109     // from the config isn't available on the system, font substitution may take place)
0110     setNeedsSave(false);
0111 }
0112 
0113 void KFonts::save()
0114 {
0115 #if HAVE_X11
0116     bool forceFontDPIChanged = false;
0117 
0118     if (KWindowSystem::isPlatformX11()) {
0119         auto dpiItem = fontsAASettings()->findItem("forceFontDPI");
0120         auto antiAliasingItem = fontsAASettings()->findItem("antiAliasing");
0121         Q_ASSERT(dpiItem && antiAliasingItem);
0122         if (dpiItem->isSaveNeeded() || antiAliasingItem->isSaveNeeded()) {
0123             emit aliasingChangeApplied();
0124         }
0125 
0126         forceFontDPIChanged = dpiItem->isSaveNeeded();
0127     }
0128 #endif
0129 
0130     KQuickManagedConfigModule::save();
0131 
0132 #if HAVE_X11
0133     // if the setting is reset in the module, remove the dpi value,
0134     // otherwise don't explicitly remove it and leave any possible system-wide value
0135     if (fontsAASettings()->forceFontDPI() == 0 && forceFontDPIChanged && KWindowSystem::isPlatformX11()) {
0136         QProcess proc;
0137         proc.setProcessChannelMode(QProcess::ForwardedChannels);
0138         proc.start("xrdb",
0139                    QStringList() << "-quiet"
0140                                  << "-remove"
0141                                  << "-nocpp");
0142         if (proc.waitForStarted()) {
0143             proc.write(QByteArray("Xft.dpi\n"));
0144             proc.closeWriteChannel();
0145             proc.waitForFinished();
0146         }
0147     }
0148     QApplication::processEvents();
0149 #endif
0150 
0151     // Notify the world about the font changes
0152     if (qEnvironmentVariableIsSet("KDE_FULL_SESSION")) {
0153         QDBusMessage message = QDBusMessage::createSignal("/KDEPlatformTheme", "org.kde.KDEPlatformTheme", "refreshFonts");
0154         QDBusConnection::sessionBus().send(message);
0155     }
0156 
0157     runRdb(KRdbExportXftSettings | KRdbExportGtkTheme);
0158 }
0159 
0160 void KFonts::adjustFont(const QFont &font, const QString &category)
0161 {
0162     QFont selFont = font;
0163     int ret = KFontChooserDialog::getFont(selFont, KFontChooser::NoDisplayFlags);
0164 
0165     if (ret == QDialog::Accepted) {
0166         if (category == QLatin1String("font")) {
0167             fontsSettings()->setFont(selFont);
0168         } else if (category == QLatin1String("menuFont")) {
0169             fontsSettings()->setMenuFont(selFont);
0170         } else if (category == QLatin1String("toolBarFont")) {
0171             fontsSettings()->setToolBarFont(selFont);
0172         } else if (category == QLatin1String("activeFont")) {
0173             fontsSettings()->setActiveFont(selFont);
0174         } else if (category == QLatin1String("smallestReadableFont")) {
0175             fontsSettings()->setSmallestReadableFont(selFont);
0176         } else if (category == QLatin1String("fixed")) {
0177             fontsSettings()->setFixed(selFont);
0178         }
0179     }
0180     Q_EMIT fontsHaveChanged();
0181 }
0182 
0183 void KFonts::adjustAllFonts()
0184 {
0185     QFont font = fontsSettings()->font();
0186     KFontChooser::FontDiffFlags fontDiffFlags;
0187     int ret = KFontChooserDialog::getFontDiff(font, fontDiffFlags, KFontChooser::NoDisplayFlags);
0188 
0189     if (ret == QDialog::Accepted && fontDiffFlags) {
0190         fontsSettings()->setFont(applyFontDiff(fontsSettings()->font(), font, fontDiffFlags));
0191         fontsSettings()->setMenuFont(applyFontDiff(fontsSettings()->menuFont(), font, fontDiffFlags));
0192         fontsSettings()->setToolBarFont(applyFontDiff(fontsSettings()->toolBarFont(), font, fontDiffFlags));
0193         fontsSettings()->setActiveFont(applyFontDiff(fontsSettings()->activeFont(), font, fontDiffFlags));
0194 
0195         QFont smallestFont = font;
0196         // Make the small font 2 points smaller than the general font, but only
0197         // if the general font is 9pt or higher or else the small font would be
0198         // borderline unreadable. Assume that if the user is making the font
0199         // tiny, they want a tiny font everywhere.
0200         const int generalFontPointSize = font.pointSize();
0201         if (generalFontPointSize >= 9) {
0202             smallestFont.setPointSize(generalFontPointSize - 2);
0203         }
0204         fontsSettings()->setSmallestReadableFont(applyFontDiff(fontsSettings()->smallestReadableFont(), smallestFont, fontDiffFlags));
0205 
0206         const QFont adjustedFont = applyFontDiff(fontsSettings()->fixed(), font, fontDiffFlags);
0207         if (QFontInfo(adjustedFont).fixedPitch()) {
0208             fontsSettings()->setFixed(adjustedFont);
0209         }
0210     }
0211 }
0212 
0213 QFont KFonts::applyFontDiff(const QFont &fnt, const QFont &newFont, int fontDiffFlags)
0214 {
0215     QFont font(fnt);
0216 
0217     if (fontDiffFlags & KFontChooser::FontDiffSize) {
0218         font.setPointSizeF(newFont.pointSizeF());
0219     }
0220     if ((fontDiffFlags & KFontChooser::FontDiffFamily)) {
0221         font.setFamily(newFont.family());
0222     }
0223     if (fontDiffFlags & KFontChooser::FontDiffStyle) {
0224         font.setWeight(newFont.weight());
0225         font.setStyle(newFont.style());
0226         font.setUnderline(newFont.underline());
0227         font.setStyleName(newFont.styleName());
0228     }
0229 
0230     return font;
0231 }
0232 
0233 int KFonts::subPixelCurrentIndex() const
0234 {
0235     return fontsAASettings()->subPixel() - KXftConfig::SubPixel::None;
0236 }
0237 
0238 void KFonts::setSubPixelCurrentIndex(int idx)
0239 {
0240     fontsAASettings()->setSubPixel(static_cast<KXftConfig::SubPixel::Type>(KXftConfig::SubPixel::None + idx));
0241 }
0242 
0243 int KFonts::hintingCurrentIndex() const
0244 {
0245     return fontsAASettings()->hinting() - KXftConfig::Hint::None;
0246 }
0247 
0248 void KFonts::setHintingCurrentIndex(int idx)
0249 {
0250     fontsAASettings()->setHinting(static_cast<KXftConfig::Hint::Style>(KXftConfig::Hint::None + idx));
0251 }
0252 
0253 #include "fonts.moc"