KConfig

kconfiggroupgui.cpp
1 /*
2  This file is part of the KDE libraries
3  SPDX-FileCopyrightText: 2007 Thiago Macieira <thiago@kde.org>
4 
5  SPDX-License-Identifier: LGPL-2.0-or-later
6 */
7 
8 #include "kconfiggui_export.h"
9 #include <kconfiggroup.h>
10 
11 #include <QColor>
12 #include <QDebug>
13 #include <QFont>
14 
15 #include <kconfiggroup_p.h>
16 
17 /**
18  * Try to read a GUI type from config group @p cg at key @p key.
19  * @p input is the default value and also indicates the type to be read.
20  * @p output is to be set with the value that has been read.
21  *
22  * @returns true if something was handled (even if output was set to clear or default)
23  * or false if nothing was handled (e.g., Core type)
24  */
25 static bool readEntryGui(const QByteArray &data, const char *key, const QVariant &input, QVariant &output)
26 {
27  const auto errString = [&]() {
28  return QStringLiteral("\"%1\" - conversion from \"%3\" to %2 failed")
29  .arg(QLatin1String(key), QLatin1String(input.typeName()), QLatin1String(data.constData()));
30  };
31 
32  // set in case of failure
33  output = input;
34 
35  switch (static_cast<QMetaType::Type>(input.userType())) {
36  case QMetaType::QColor: {
37  if (data.isEmpty() || data == "invalid") {
38  output = QColor(); // return what was stored
39  return true;
40  } else if (data.at(0) == '#') {
41  QColor col = QColor::fromString(QUtf8StringView(data.constData(), data.length()));
42  if (!col.isValid()) {
43  qCritical() << qPrintable(errString());
44  }
45  output = col;
46  return true;
47  } else if (!data.contains(',')) {
48  QColor col = QColor::fromString(QUtf8StringView(data.constData(), data.length()));
49  if (!col.isValid()) {
50  qCritical() << qPrintable(errString());
51  }
52  output = col;
53  return true;
54  } else {
55  const QList<QByteArray> list = data.split(',');
56  const int count = list.count();
57 
58  if (count != 3 && count != 4) {
59  qCritical() //
60  << qPrintable(errString()) //
61  << qPrintable(QStringLiteral(" (wrong format: expected '%1' items, read '%2')").arg(QStringLiteral("3' or '4")).arg(count));
62  return true; // return default
63  }
64 
65  int temp[4];
66  // bounds check components
67  for (int i = 0; i < count; i++) {
68  bool ok;
69  const int j = temp[i] = list.at(i).toInt(&ok);
70  if (!ok) { // failed to convert to int
71  qCritical() << qPrintable(errString()) << " (integer conversion failed)";
72  return true; // return default
73  }
74  if (j < 0 || j > 255) {
75  static const char *const components[] = {"red", "green", "blue", "alpha"};
76  qCritical() << qPrintable(errString())
77  << qPrintable(QStringLiteral(" (bounds error: %1 component %2)")
78  .arg(QLatin1String(components[i]), //
79  j < 0 ? QStringLiteral("< 0") : QStringLiteral("> 255")));
80  return true; // return default
81  }
82  }
83  QColor aColor(temp[0], temp[1], temp[2]);
84  if (count == 4) {
85  aColor.setAlpha(temp[3]);
86  }
87 
88  if (aColor.isValid()) {
89  output = aColor;
90  } else {
91  qCritical() << qPrintable(errString());
92  }
93  return true;
94  }
95  }
96 
97  case QMetaType::QFont: {
98  QVariant tmp = QString::fromUtf8(data.constData(), data.length());
99  if (tmp.canConvert<QFont>()) {
100  output = tmp;
101  } else {
102  qCritical() << qPrintable(errString());
103  }
104  return true;
105  }
106  case QMetaType::QPixmap:
107  case QMetaType::QImage:
108  case QMetaType::QBrush:
109  case QMetaType::QPalette:
110  case QMetaType::QIcon:
111  case QMetaType::QRegion:
112  case QMetaType::QBitmap:
113  case QMetaType::QCursor:
115  case QMetaType::QPen:
116  // we may want to handle these in the future
117 
118  default:
119  break;
120  }
121 
122  return false; // not handled
123 }
124 
125 /**
126  * Try to write a GUI type @p prop to config group @p cg at key @p key.
127  *
128  * @returns true if something was handled (even if an empty value was written)
129  * or false if nothing was handled (e.g., Core type)
130  */
131 static bool writeEntryGui(KConfigGroup *cg, const char *key, const QVariant &prop, KConfigGroup::WriteConfigFlags pFlags)
132 {
133  switch (static_cast<QMetaType::Type>(prop.userType())) {
134  case QMetaType::QColor: {
135  const QColor rColor = prop.value<QColor>();
136 
137  if (!rColor.isValid()) {
138  cg->writeEntry(key, "invalid", pFlags);
139  return true;
140  }
141 
143  list.insert(0, rColor.red());
144  list.insert(1, rColor.green());
145  list.insert(2, rColor.blue());
146  if (rColor.alpha() != 255) {
147  list.insert(3, rColor.alpha());
148  }
149 
150  cg->writeEntry(key, list, pFlags);
151  return true;
152  }
153  case QMetaType::QFont: {
154  QFont f = prop.value<QFont>();
155  // If the styleName property is set for a QFont, using setBold(true) would
156  // lead to Qt using an "emboldended"/synthetic font style instead of using
157  // the bold style provided by the font itself; the latter looks much better
158  // than the former. For more details see:
159  // https://bugreports.qt.io/browse/QTBUG-63792
160  // https://bugs.kde.org/show_bug.cgi?id=378523
161  /* clang-format off */
162  if (f.weight() == QFont::Normal
163  && (f.styleName() == QLatin1String("Regular")
164  || f.styleName() == QLatin1String("Normal")
165  || f.styleName() == QLatin1String("Book")
166  || f.styleName() == QLatin1String("Roman"))) { /* clang-format on */
167  f.setStyleName(QString());
168  }
169  cg->writeEntry(key, f.toString().toUtf8(), pFlags);
170  return true;
171  }
172  case QMetaType::QPixmap:
173  case QMetaType::QImage:
174  case QMetaType::QBrush:
175  case QMetaType::QPalette:
176  case QMetaType::QIcon:
177  case QMetaType::QRegion:
178  case QMetaType::QBitmap:
179  case QMetaType::QCursor:
181  case QMetaType::QPen:
182  // we may want to handle one of these in the future
183  break;
184 
185  default:
186  break;
187  }
188 
189  return false;
190 }
191 
192 // Not static, because for static builds we use it in the kconfigguistaticinitializer.cpp file
193 // Exported as we need this to force linking in consumers that read GUI types from KConfig, but
194 // which are otherwise not using this library (and thus linking with --as-needed or MSVC would
195 // break things)
196 KCONFIGGUI_EXPORT int initKConfigGroupGui()
197 {
198  _kde_internal_KConfigGroupGui.readEntryGui = readEntryGui;
199  _kde_internal_KConfigGroupGui.writeEntryGui = writeEntryGui;
200  return 42; // because 42 is nicer than 1 or 0
201 }
202 
203 #ifdef Q_CONSTRUCTOR_FUNCTION
204 Q_CONSTRUCTOR_FUNCTION(initKConfigGroupGui)
205 #else
206 static int dummyKConfigGroupGui = initKConfigGroupGui();
207 #endif
void writeEntry(const QString &key, const QVariant &value, WriteConfigFlags pFlags=Normal)
Writes a value to the configuration object.
int weight() const const
QString fromUtf8(const char *str, int size)
int count(const T &value) const const
T value() const const
int red() const const
void setStyleName(const QString &styleName)
KIOCORE_EXPORT QStringList list(const QString &fileClass)
int userType() const const
QVariant data() const
QString styleName() const const
QByteArray toUtf8() const const
const T & at(int i) const const
int alpha() const const
int green() const const
QString toString() const const
void insert(int i, const T &value)
bool canConvert(int targetTypeId) const const
int blue() const const
bool isValid() const const
const char * typeName() const const
This file is part of the KDE documentation.
Documentation copyright © 1996-2024 The KDE developers.
Generated on Thu Feb 15 2024 04:07:59 by doxygen 1.8.17 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.