Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Loading...
Searching...
No Matches
fontpropertymanager.cpp
Go to the documentation of this file.
1// Copyright (C) 2016 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
3// Qt-Security score:significant reason:default
4
9
10#include <qdesigner_utils_p.h>
11
12#include <QtCore/qcoreapplication.h>
13#include <QtCore/qvariant.h>
14#include <QtCore/qstring.h>
15#include <QtCore/qdebug.h>
16#include <QtCore/qfile.h>
17#include <QtCore/qtextstream.h>
18#include <QtCore/qxmlstream.h>
19
20#include <utility>
21
22QT_BEGIN_NAMESPACE
23
24using namespace Qt::StringLiterals;
25
26namespace qdesigner_internal {
27
28 using DisambiguatedTranslation = std::pair<const char *, const char *>;
29
30 static const char *aliasingC[] = {
31 QT_TRANSLATE_NOOP("FontPropertyManager", "PreferDefault"),
32 QT_TRANSLATE_NOOP("FontPropertyManager", "NoAntialias"),
33 QT_TRANSLATE_NOOP("FontPropertyManager", "PreferAntialias")
34 };
35
37 QT_TRANSLATE_NOOP3("FontPropertyManager", "PreferDefaultHinting", "QFont::StyleStrategy combo"),
38 QT_TRANSLATE_NOOP3("FontPropertyManager", "PreferNoHinting", "QFont::StyleStrategy combo"),
39 QT_TRANSLATE_NOOP3("FontPropertyManager", "PreferVerticalHinting", "QFont::StyleStrategy combo"),
40 QT_TRANSLATE_NOOP3("FontPropertyManager", "PreferFullHinting", "QFont::StyleStrategy combo")
41 };
42
43 FontPropertyManager::FontPropertyManager()
44 {
45 for (const auto *a : aliasingC)
46 m_aliasingEnumNames.append(QCoreApplication::translate("FontPropertyManager", a));
47
48 for (const auto &h : hintingPreferenceC)
49 m_hintingPreferenceEnumNames.append(QCoreApplication::translate("FontPropertyManager", h.first, h.second));
50
51 QString errorMessage;
52 if (!readFamilyMapping(&m_familyMappings, &errorMessage)) {
53 designerWarning(errorMessage);
54 }
55
56 }
57
59 int type,
60 ResetMap &resetMap)
61 {
62 if (m_createdFontProperty) {
63 auto it = m_propertyToFontSubProperties.find(m_createdFontProperty);
64 if (it == m_propertyToFontSubProperties.end())
65 it = m_propertyToFontSubProperties.insert(m_createdFontProperty, PropertyList());
66 const int index = it.value().size();
67 m_fontSubPropertyToFlag.insert(property, index);
68 it.value().push_back(property);
69 resetMap[property] = true;
70 }
71
72 if (type == QMetaType::QFont)
73 m_createdFontProperty = property;
74 }
75
76 // Map the font family names to display names retrieved from the XML configuration
77 static QStringList designerFamilyNames(QStringList families, const FontPropertyManager::NameMap &nm)
78 {
79 if (nm.isEmpty())
80 return families;
81
82 const auto ncend = nm.constEnd();
83 for (auto it = families.begin(), end = families.end(); it != end; ++it) {
84 const auto nit = nm.constFind(*it);
85 if (nit != ncend)
86 *it = nit.value();
87 }
88 return families;
89 }
90
92 QtProperty *property,
93 int type,
94 int enumTypeId)
95 {
96 if (type != QMetaType::QFont)
97 return;
98
99 // This will cause a recursion
100 QtVariantProperty *antialiasing = vm->addProperty(enumTypeId, QCoreApplication::translate("FontPropertyManager", "Antialiasing"));
101 const QFont font = qvariant_cast<QFont>(vm->variantProperty(property)->value());
102
103 antialiasing->setAttribute(u"enumNames"_s, m_aliasingEnumNames);
104 antialiasing->setValue(antialiasingToIndex(font.styleStrategy()));
105 property->addSubProperty(antialiasing);
106
107 m_propertyToAntialiasing[property] = antialiasing;
108 m_antialiasingToProperty[antialiasing] = property;
109
110 QtVariantProperty *hintingPreference = vm->addProperty(enumTypeId, QCoreApplication::translate("FontPropertyManager", "HintingPreference"));
111 hintingPreference->setAttribute(u"enumNames"_s, m_hintingPreferenceEnumNames);
112 hintingPreference->setValue(hintingPreferenceToIndex(font.hintingPreference()));
113 property->addSubProperty(hintingPreference);
114
115 m_propertyToHintingPreference[property] = hintingPreference;
116 m_hintingPreferenceToProperty[hintingPreference] = property;
117
118 // Fiddle family names
119 if (!m_familyMappings.isEmpty()) {
120 const auto it = m_propertyToFontSubProperties.find(m_createdFontProperty);
121 QtVariantProperty *familyProperty = vm->variantProperty(it.value().constFirst());
122 const QString enumNamesAttribute = u"enumNames"_s;
123 QStringList plainFamilyNames = familyProperty->attributeValue(enumNamesAttribute).toStringList();
124 // Did someone load fonts or something?
125 if (m_designerFamilyNames.size() != plainFamilyNames.size())
126 m_designerFamilyNames = designerFamilyNames(plainFamilyNames, m_familyMappings);
127 familyProperty->setAttribute(enumNamesAttribute, m_designerFamilyNames);
128 }
129 // Next
130 m_createdFontProperty = nullptr;
131 }
132
134 {
135 const auto ait = m_propertyToAntialiasing.find(property);
136 if (ait != m_propertyToAntialiasing.end()) {
137 QtProperty *antialiasing = ait.value();
138 m_antialiasingToProperty.remove(antialiasing);
139 m_propertyToAntialiasing.erase(ait);
140 delete antialiasing;
141 }
142
143 const auto hit = m_propertyToHintingPreference.find(property);
144 if (hit != m_propertyToHintingPreference.end()) {
145 QtProperty *hintingPreference = hit.value();
146 m_hintingPreferenceToProperty.remove(hintingPreference);
147 m_propertyToHintingPreference.erase(hit);
148 delete hintingPreference;
149 }
150
151 const auto sit = m_propertyToFontSubProperties.find(property);
152 if (sit == m_propertyToFontSubProperties.end())
153 return false;
154
155 m_propertyToFontSubProperties.erase(sit);
156 m_fontSubPropertyToFlag.remove(property);
157
158 return true;
159 }
160
162 {
163 removeAntialiasingProperty(property);
164 removeHintingPreferenceProperty(property);
165 }
166
167 void FontPropertyManager::removeAntialiasingProperty(QtProperty *property)
168 {
169 const auto ait = m_antialiasingToProperty.find(property);
170 if (ait == m_antialiasingToProperty.end())
171 return;
172 m_propertyToAntialiasing[ait.value()] = 0;
173 m_antialiasingToProperty.erase(ait);
174 }
175
176 void FontPropertyManager::removeHintingPreferenceProperty(QtProperty *property)
177 {
178 const auto hit = m_hintingPreferenceToProperty.find(property);
179 if (hit == m_hintingPreferenceToProperty.end())
180 return;
181 m_propertyToHintingPreference[hit.value()] = nullptr;
182 m_hintingPreferenceToProperty.erase(hit);
183 }
184
186 {
187 auto *parentItem = property->parentProperty();
188 if (!m_propertyToFontSubProperties.contains(parentItem))
189 return false;
190
191 QtVariantProperty *fontProperty = vm->variantProperty(parentItem);
192
193 QVariant v = fontProperty->value();
194 QFont font = qvariant_cast<QFont>(v);
195 unsigned mask = font.resolveMask();
196 const unsigned flag = fontFlag(m_fontSubPropertyToFlag.value(property));
197
198 mask &= ~flag;
199 font.setResolveMask(mask);
200 v.setValue(font);
201 fontProperty->setValue(v);
202 return true;
203 }
204
205 int FontPropertyManager::antialiasingToIndex(QFont::StyleStrategy antialias)
206 {
207 switch (antialias) {
208 case QFont::PreferDefault: return 0;
209 case QFont::NoAntialias: return 1;
210 case QFont::PreferAntialias: return 2;
211 default: break;
212 }
213 return 0;
214 }
215
216 QFont::StyleStrategy FontPropertyManager::indexToAntialiasing(int idx)
217 {
218 switch (idx) {
219 case 0: return QFont::PreferDefault;
220 case 1: return QFont::NoAntialias;
221 case 2: return QFont::PreferAntialias;
222 }
223 return QFont::PreferDefault;
224 }
225
226 int FontPropertyManager::hintingPreferenceToIndex(QFont::HintingPreference h)
227 {
228 switch (h) {
229 case QFont::PreferDefaultHinting:
230 return 0;
231 case QFont::PreferNoHinting:
232 return 1;
233 case QFont::PreferVerticalHinting:
234 return 2;
235 case QFont::PreferFullHinting:
236 return 3;
237 }
238 return 0;
239 }
240
241 QFont::HintingPreference FontPropertyManager::indexToHintingPreference(int idx)
242 {
243 switch (idx) {
244 case 0:
245 return QFont::PreferDefaultHinting;
246 case 1:
247 return QFont::PreferNoHinting;
248 case 2:
249 return QFont::PreferVerticalHinting;
250 case 3:
251 return QFont::PreferFullHinting;
252 }
253 return QFont::PreferDefaultHinting;
254 }
255
256 unsigned FontPropertyManager::fontFlag(int idx)
257 {
258 switch (idx) {
259 case 0:
260 return QFont::FamilyResolved | QFont::FamiliesResolved;
261 case 1:
262 return QFont::SizeResolved;
263 case 2:
264 case 7:
265 return QFont::WeightResolved;
266 case 3:
267 return QFont::StyleResolved;
268 case 4:
269 return QFont::UnderlineResolved;
270 case 5:
271 return QFont::StrikeOutResolved;
272 case 6:
273 return QFont::KerningResolved;
274 case 8:
275 return QFont::StyleStrategyResolved;
276 case 9:
277 return QFont::HintingPreferenceResolved;
278 }
279 return 0;
280 }
281
282 int FontPropertyManager::valueChanged(QtVariantPropertyManager *vm, QtProperty *property, const QVariant &value)
283 {
284 if (auto *antialiasingProperty = m_antialiasingToProperty.value(property, nullptr))
285 return antialiasingValueChanged(vm, antialiasingProperty, value);
286
287 if (auto *hintingPreferenceProperty = m_hintingPreferenceToProperty.value(property, nullptr))
288 return hintingPreferenceValueChanged(vm, hintingPreferenceProperty, value);
289
290 if (m_propertyToFontSubProperties.contains(property))
291 updateModifiedState(property, value);
292
293 return DesignerPropertyManager::NoMatch;
294 }
295
296 int FontPropertyManager::antialiasingValueChanged(QtVariantPropertyManager *vm,
297 QtProperty *antialiasingProperty,
298 const QVariant &value)
299 {
300 QtVariantProperty *fontProperty = vm->variantProperty(antialiasingProperty);
301 const QFont::StyleStrategy newValue = indexToAntialiasing(value.toInt());
302
303 QFont font = qvariant_cast<QFont>(fontProperty->value());
304 const QFont::StyleStrategy oldValue = font.styleStrategy();
305 if (newValue == oldValue)
306 return DesignerPropertyManager::Unchanged;
307
308 font.setStyleStrategy(newValue);
309 fontProperty->setValue(QVariant::fromValue(font));
310 return DesignerPropertyManager::Changed;
311 }
312
313 int FontPropertyManager::hintingPreferenceValueChanged(QtVariantPropertyManager *vm,
314 QtProperty *hintingPreferenceProperty,
315 const QVariant &value)
316 {
317 QtVariantProperty *fontProperty = vm->variantProperty(hintingPreferenceProperty);
318 const QFont::HintingPreference newValue = indexToHintingPreference(value.toInt());
319
320 QFont font = qvariant_cast<QFont>(fontProperty->value());
321 const QFont::HintingPreference oldValue = font.hintingPreference();
322 if (newValue == oldValue)
323 return DesignerPropertyManager::Unchanged;
324
325 font.setHintingPreference(newValue);
326 fontProperty->setValue(QVariant::fromValue(font));
327 return DesignerPropertyManager::Changed;
328 }
329
330 void FontPropertyManager::updateModifiedState(QtProperty *property, const QVariant &value)
331 {
332 const auto it = m_propertyToFontSubProperties.find(property);
333 if (it == m_propertyToFontSubProperties.end())
334 return;
335
336 const PropertyList &subProperties = it.value();
337
338 QFont font = qvariant_cast<QFont>(value);
339 const unsigned mask = font.resolveMask();
340
341 const int count = subProperties.size();
342 for (int index = 0; index < count; index++) {
343 const unsigned flag = fontFlag(index);
344 subProperties.at(index)->setModified(mask & flag);
345 }
346 }
347
348 void FontPropertyManager::setValue(QtVariantPropertyManager *vm, QtProperty *property, const QVariant &value)
349 {
350 updateModifiedState(property, value);
351
352 if (QtProperty *antialiasingProperty = m_propertyToAntialiasing.value(property, 0)) {
353 QtVariantProperty *antialiasing = vm->variantProperty(antialiasingProperty);
354 if (antialiasing) {
355 QFont font = qvariant_cast<QFont>(value);
356 antialiasing->setValue(antialiasingToIndex(font.styleStrategy()));
357 }
358 }
359
360 if (QtProperty *hintingPreferenceProperty = m_propertyToHintingPreference.value(property, nullptr)) {
361 if (auto *hintingPreference = vm->variantProperty(hintingPreferenceProperty)) {
362 QFont font = qvariant_cast<QFont>(value);
363 hintingPreference->setValue(hintingPreferenceToIndex(font.hintingPreference()));
364 }
365 }
366
367 }
368
369 /* Parse a mappings file of the form:
370 * <fontmappings>
371 * <mapping><family>DejaVu Sans</family><display>DejaVu Sans [CE]</display></mapping>
372 * ... which is used to display on which platforms fonts are available.*/
373
374static constexpr auto rootTagC = "fontmappings"_L1;
375static constexpr auto mappingTagC = "mapping"_L1;
376static constexpr auto familyTagC = "family"_L1;
377static constexpr auto displayTagC = "display"_L1;
378
379 static QString msgXmlError(const QXmlStreamReader &r, const QString& fileName)
380 {
381 return u"An error has been encountered at line %1 of %2: %3:"_s.arg(r.lineNumber()).arg(fileName, r.errorString());
382 }
383
384 /* Switch stages when encountering a start element (state table) */
387
388 static ParseStage nextStage(ParseStage currentStage, QStringView startElement)
389 {
390 switch (currentStage) {
391 case ParseBeginning:
392 return startElement == rootTagC ? ParseWithinRoot : ParseError;
393 case ParseWithinRoot:
394 case ParseWithinDisplay: // Next mapping, was in <display>
395 return startElement == mappingTagC ? ParseWithinMapping : ParseError;
397 return startElement == familyTagC ? ParseWithinFamily : ParseError;
399 return startElement == displayTagC ? ParseWithinDisplay : ParseError;
400 case ParseError:
401 break;
402 }
403 return ParseError;
404 }
405
407 {
408 rc->clear();
409 const QString fileName = u":/qt-project.org/propertyeditor/fontmapping.xml"_s;
411 if (!file.open(QIODevice::ReadOnly)) {
412 *errorMessage = "Unable to open %1: %2"_L1.arg(fileName, file.errorString());
413 return false;
414 }
415
418
421 do {
423 switch (token) {
426 return false;
429 switch (stage) {
430 case ParseError:
431 reader.raiseError("Unexpected element <%1>."_L1.arg(reader.name()));
433 return false;
436 break;
439 break;
440 default:
441 break;
442 }
443 break;
444 default:
445 break;
446 }
447 } while (token != QXmlStreamReader::EndDocument);
448 return true;
449 }
450
451}
452
453QT_END_NAMESPACE
The QtProperty class encapsulates an instance of a property.
QtProperty * parentProperty() const
void addSubProperty(QtProperty *property)
Appends the given property to this property's subproperties.
The QtVariantPropertyManager class provides and manages QVariant based properties.
QtVariantProperty * variantProperty(const QtProperty *property) const
Returns the given property converted into a QtVariantProperty.
The QtVariantProperty class is a convenience class handling QVariant based properties.
bool resetFontSubProperty(QtVariantPropertyManager *vm, QtProperty *subProperty)
void setValue(QtVariantPropertyManager *vm, QtProperty *property, const QVariant &value)
void postInitializeProperty(QtVariantPropertyManager *vm, QtProperty *property, int type, int enumTypeId)
int valueChanged(QtVariantPropertyManager *vm, QtProperty *property, const QVariant &value)
void preInitializeProperty(QtProperty *property, int type, ResetMap &resetMap)
Auxiliary methods to store/retrieve settings.
static QString msgXmlError(const QXmlStreamReader &r, const QString &fileName)
static QStringList designerFamilyNames(QStringList families, const FontPropertyManager::NameMap &nm)
static constexpr auto familyTagC
static const char * aliasingC[]
std::pair< const char *, const char * > DisambiguatedTranslation
static constexpr auto rootTagC
static ParseStage nextStage(ParseStage currentStage, QStringView startElement)
static constexpr auto displayTagC
static const DisambiguatedTranslation hintingPreferenceC[]
static constexpr auto mappingTagC