File indexing completed on 2024-05-12 15:34:13
0001 /* 0002 This file is part of the KDE libraries 0003 SPDX-FileCopyrightText: 2007 Thiago Macieira <thiago@kde.org> 0004 0005 SPDX-License-Identifier: LGPL-2.0-or-later 0006 */ 0007 0008 #include <kconfiggroup.h> 0009 0010 #include <QColor> 0011 #include <QDebug> 0012 #include <QFont> 0013 0014 #include <kconfiggroup_p.h> 0015 0016 /** 0017 * Try to read a GUI type from config group @p cg at key @p key. 0018 * @p input is the default value and also indicates the type to be read. 0019 * @p output is to be set with the value that has been read. 0020 * 0021 * @returns true if something was handled (even if output was set to clear or default) 0022 * or false if nothing was handled (e.g., Core type) 0023 */ 0024 static bool readEntryGui(const QByteArray &data, const char *key, const QVariant &input, QVariant &output) 0025 { 0026 const auto errString = [&]() { 0027 return QStringLiteral("\"%1\" - conversion from \"%3\" to %2 failed") 0028 .arg(QLatin1String(key), QLatin1String(QVariant::typeToName(input.type())), QLatin1String(data.constData())); 0029 }; 0030 0031 // set in case of failure 0032 output = input; 0033 0034 switch (static_cast<QMetaType::Type>(input.type())) { 0035 case QMetaType::QColor: { 0036 if (data.isEmpty() || data == "invalid") { 0037 output = QColor(); // return what was stored 0038 return true; 0039 } else if (data.at(0) == '#') { 0040 QColor col; 0041 col.setNamedColor(QString::fromUtf8(data.constData(), data.length())); 0042 output = col; 0043 return true; 0044 } else if (!data.contains(',')) { 0045 QColor col; 0046 col.setNamedColor(QString::fromUtf8(data.constData(), data.length())); 0047 if (!col.isValid()) { 0048 qCritical() << qPrintable(errString()); 0049 } 0050 output = col; 0051 return true; 0052 } else { 0053 const QList<QByteArray> list = data.split(','); 0054 const int count = list.count(); 0055 0056 if (count != 3 && count != 4) { 0057 qCritical() // 0058 << qPrintable(errString()) // 0059 << qPrintable(QStringLiteral(" (wrong format: expected '%1' items, read '%2')").arg(QStringLiteral("3' or '4")).arg(count)); 0060 return true; // return default 0061 } 0062 0063 int temp[4]; 0064 // bounds check components 0065 for (int i = 0; i < count; i++) { 0066 bool ok; 0067 const int j = temp[i] = list.at(i).toInt(&ok); 0068 if (!ok) { // failed to convert to int 0069 qCritical() << qPrintable(errString()) << " (integer conversion failed)"; 0070 return true; // return default 0071 } 0072 if (j < 0 || j > 255) { 0073 static const char *const components[] = {"red", "green", "blue", "alpha"}; 0074 qCritical() << qPrintable(errString()) 0075 << qPrintable(QStringLiteral(" (bounds error: %1 component %2)") 0076 .arg(QLatin1String(components[i]), // 0077 j < 0 ? QStringLiteral("< 0") : QStringLiteral("> 255"))); 0078 return true; // return default 0079 } 0080 } 0081 QColor aColor(temp[0], temp[1], temp[2]); 0082 if (count == 4) { 0083 aColor.setAlpha(temp[3]); 0084 } 0085 0086 if (aColor.isValid()) { 0087 output = aColor; 0088 } else { 0089 qCritical() << qPrintable(errString()); 0090 } 0091 return true; 0092 } 0093 } 0094 0095 case QMetaType::QFont: { 0096 QVariant tmp = QString::fromUtf8(data.constData(), data.length()); 0097 if (tmp.convert(QMetaType::QFont)) { 0098 output = tmp; 0099 } else { 0100 qCritical() << qPrintable(errString()); 0101 } 0102 return true; 0103 } 0104 case QMetaType::QPixmap: 0105 case QMetaType::QImage: 0106 case QMetaType::QBrush: 0107 case QMetaType::QPalette: 0108 case QMetaType::QIcon: 0109 case QMetaType::QRegion: 0110 case QMetaType::QBitmap: 0111 case QMetaType::QCursor: 0112 case QMetaType::QSizePolicy: 0113 case QMetaType::QPen: 0114 // we may want to handle these in the future 0115 0116 default: 0117 break; 0118 } 0119 0120 return false; // not handled 0121 } 0122 0123 /** 0124 * Try to write a GUI type @p prop to config group @p cg at key @p key. 0125 * 0126 * @returns true if something was handled (even if an empty value was written) 0127 * or false if nothing was handled (e.g., Core type) 0128 */ 0129 static bool writeEntryGui(KConfigGroup *cg, const char *key, const QVariant &prop, KConfigGroup::WriteConfigFlags pFlags) 0130 { 0131 switch (static_cast<QMetaType::Type>(prop.type())) { 0132 case QMetaType::QColor: { 0133 const QColor rColor = prop.value<QColor>(); 0134 0135 if (!rColor.isValid()) { 0136 cg->writeEntry(key, "invalid", pFlags); 0137 return true; 0138 } 0139 0140 QList<int> list; 0141 list.insert(0, rColor.red()); 0142 list.insert(1, rColor.green()); 0143 list.insert(2, rColor.blue()); 0144 if (rColor.alpha() != 255) { 0145 list.insert(3, rColor.alpha()); 0146 } 0147 0148 cg->writeEntry(key, list, pFlags); 0149 return true; 0150 } 0151 case QMetaType::QFont: { 0152 QFont f = prop.value<QFont>(); 0153 // If the styleName property is set for a QFont, using setBold(true) would 0154 // lead to Qt using an "emboldended"/synthetic font style instead of using 0155 // the bold style provided by the font itself; the latter looks much better 0156 // than the former. For more details see: 0157 // https://bugreports.qt.io/browse/QTBUG-63792 0158 // https://bugs.kde.org/show_bug.cgi?id=378523 0159 /* clang-format off */ 0160 if (f.weight() == QFont::Normal 0161 && (f.styleName() == QLatin1String("Regular") 0162 || f.styleName() == QLatin1String("Normal") 0163 || f.styleName() == QLatin1String("Book") 0164 || f.styleName() == QLatin1String("Roman"))) { /* clang-format on */ 0165 f.setStyleName(QString()); 0166 } 0167 cg->writeEntry(key, f.toString().toUtf8(), pFlags); 0168 return true; 0169 } 0170 case QMetaType::QPixmap: 0171 case QMetaType::QImage: 0172 case QMetaType::QBrush: 0173 case QMetaType::QPalette: 0174 case QMetaType::QIcon: 0175 case QMetaType::QRegion: 0176 case QMetaType::QBitmap: 0177 case QMetaType::QCursor: 0178 case QMetaType::QSizePolicy: 0179 case QMetaType::QPen: 0180 // we may want to handle one of these in the future 0181 break; 0182 0183 default: 0184 break; 0185 } 0186 0187 return false; 0188 } 0189 0190 // Not static, because for static builds we use it in the kconfigguistaticinitializer.cpp file 0191 int initKConfigGroupGui() 0192 { 0193 _kde_internal_KConfigGroupGui.readEntryGui = readEntryGui; 0194 _kde_internal_KConfigGroupGui.writeEntryGui = writeEntryGui; 0195 return 42; // because 42 is nicer than 1 or 0 0196 } 0197 0198 #ifdef Q_CONSTRUCTOR_FUNCTION 0199 Q_CONSTRUCTOR_FUNCTION(initKConfigGroupGui) 0200 #else 0201 static int dummyKConfigGroupGui = initKConfigGroupGui(); 0202 #endif