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
8
9#include <qdesigner_utils_p.h>
10
11#include <QtCore/qcoreapplication.h>
12#include <QtCore/qvariant.h>
13#include <QtCore/qstring.h>
14#include <QtCore/qdebug.h>
15#include <QtCore/qfile.h>
16#include <QtCore/qtextstream.h>
17#include <QtCore/qxmlstream.h>
18
19#include <utility>
20
21QT_BEGIN_NAMESPACE
22
23using namespace Qt::StringLiterals;
24
25namespace qdesigner_internal {
26
27 using DisambiguatedTranslation = std::pair<const char *, const char *>;
28
29 static const char *aliasingC[] = {
30 QT_TRANSLATE_NOOP("FontPropertyManager", "PreferDefault"),
31 QT_TRANSLATE_NOOP("FontPropertyManager", "NoAntialias"),
32 QT_TRANSLATE_NOOP("FontPropertyManager", "PreferAntialias")
33 };
34
35 static const DisambiguatedTranslation hintingPreferenceC[] = {
36 QT_TRANSLATE_NOOP3("FontPropertyManager", "PreferDefaultHinting", "QFont::StyleStrategy combo"),
37 QT_TRANSLATE_NOOP3("FontPropertyManager", "PreferNoHinting", "QFont::StyleStrategy combo"),
38 QT_TRANSLATE_NOOP3("FontPropertyManager", "PreferVerticalHinting", "QFont::StyleStrategy combo"),
39 QT_TRANSLATE_NOOP3("FontPropertyManager", "PreferFullHinting", "QFont::StyleStrategy combo")
40 };
41
42 FontPropertyManager::FontPropertyManager()
43 {
44 for (const auto *a : aliasingC)
45 m_aliasingEnumNames.append(QCoreApplication::translate("FontPropertyManager", a));
46
47 for (const auto &h : hintingPreferenceC)
48 m_hintingPreferenceEnumNames.append(QCoreApplication::translate("FontPropertyManager", h.first, h.second));
49
50 QString errorMessage;
51 if (!readFamilyMapping(&m_familyMappings, &errorMessage)) {
52 designerWarning(errorMessage);
53 }
54
55 }
56
58 int type,
59 ResetMap &resetMap)
60 {
61 if (m_createdFontProperty) {
62 auto it = m_propertyToFontSubProperties.find(m_createdFontProperty);
63 if (it == m_propertyToFontSubProperties.end())
64 it = m_propertyToFontSubProperties.insert(m_createdFontProperty, PropertyList());
65 const int index = it.value().size();
66 m_fontSubPropertyToFlag.insert(property, index);
67 it.value().push_back(property);
68 m_fontSubPropertyToProperty[property] = m_createdFontProperty;
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 m_fontSubPropertyToProperty.remove(property);
158
159 return true;
160 }
161
163 {
164 removeAntialiasingProperty(property);
165 removeHintingPreferenceProperty(property);
166 }
167
168 void FontPropertyManager::removeAntialiasingProperty(QtProperty *property)
169 {
170 const auto ait = m_antialiasingToProperty.find(property);
171 if (ait == m_antialiasingToProperty.end())
172 return;
173 m_propertyToAntialiasing[ait.value()] = 0;
174 m_antialiasingToProperty.erase(ait);
175 }
176
177 void FontPropertyManager::removeHintingPreferenceProperty(QtProperty *property)
178 {
179 const auto hit = m_hintingPreferenceToProperty.find(property);
180 if (hit == m_hintingPreferenceToProperty.end())
181 return;
182 m_propertyToHintingPreference[hit.value()] = nullptr;
183 m_hintingPreferenceToProperty.erase(hit);
184 }
185
187 {
188 const auto it = m_fontSubPropertyToProperty.find(property);
189 if (it == m_fontSubPropertyToProperty.end())
190 return false;
191
192 QtVariantProperty *fontProperty = vm->variantProperty(it.value());
193
194 QVariant v = fontProperty->value();
195 QFont font = qvariant_cast<QFont>(v);
196 unsigned mask = font.resolveMask();
197 const unsigned flag = fontFlag(m_fontSubPropertyToFlag.value(property));
198
199 mask &= ~flag;
200 font.setResolveMask(mask);
201 v.setValue(font);
202 fontProperty->setValue(v);
203 return true;
204 }
205
206 int FontPropertyManager::antialiasingToIndex(QFont::StyleStrategy antialias)
207 {
208 switch (antialias) {
209 case QFont::PreferDefault: return 0;
210 case QFont::NoAntialias: return 1;
211 case QFont::PreferAntialias: return 2;
212 default: break;
213 }
214 return 0;
215 }
216
217 QFont::StyleStrategy FontPropertyManager::indexToAntialiasing(int idx)
218 {
219 switch (idx) {
220 case 0: return QFont::PreferDefault;
221 case 1: return QFont::NoAntialias;
222 case 2: return QFont::PreferAntialias;
223 }
224 return QFont::PreferDefault;
225 }
226
227 int FontPropertyManager::hintingPreferenceToIndex(QFont::HintingPreference h)
228 {
229 switch (h) {
230 case QFont::PreferDefaultHinting:
231 return 0;
232 case QFont::PreferNoHinting:
233 return 1;
234 case QFont::PreferVerticalHinting:
235 return 2;
236 case QFont::PreferFullHinting:
237 return 3;
238 }
239 return 0;
240 }
241
242 QFont::HintingPreference FontPropertyManager::indexToHintingPreference(int idx)
243 {
244 switch (idx) {
245 case 0:
246 return QFont::PreferDefaultHinting;
247 case 1:
248 return QFont::PreferNoHinting;
249 case 2:
250 return QFont::PreferVerticalHinting;
251 case 3:
252 return QFont::PreferFullHinting;
253 }
254 return QFont::PreferDefaultHinting;
255 }
256
257 unsigned FontPropertyManager::fontFlag(int idx)
258 {
259 switch (idx) {
260 case 0:
261 return QFont::FamilyResolved | QFont::FamiliesResolved;
262 case 1:
263 return QFont::SizeResolved;
264 case 2:
265 case 7:
266 return QFont::WeightResolved;
267 case 3:
268 return QFont::StyleResolved;
269 case 4:
270 return QFont::UnderlineResolved;
271 case 5:
272 return QFont::StrikeOutResolved;
273 case 6:
274 return QFont::KerningResolved;
275 case 8:
276 return QFont::StyleStrategyResolved;
277 case 9:
278 return QFont::HintingPreferenceResolved;
279 }
280 return 0;
281 }
282
283 int FontPropertyManager::valueChanged(QtVariantPropertyManager *vm, QtProperty *property, const QVariant &value)
284 {
285 if (auto *antialiasingProperty = m_antialiasingToProperty.value(property, nullptr))
286 return antialiasingValueChanged(vm, antialiasingProperty, value);
287
288 if (auto *hintingPreferenceProperty = m_hintingPreferenceToProperty.value(property, nullptr))
289 return hintingPreferenceValueChanged(vm, hintingPreferenceProperty, value);
290
291 if (m_propertyToFontSubProperties.contains(property))
292 updateModifiedState(property, value);
293
294 return DesignerPropertyManager::NoMatch;
295 }
296
297 int FontPropertyManager::antialiasingValueChanged(QtVariantPropertyManager *vm,
298 QtProperty *antialiasingProperty,
299 const QVariant &value)
300 {
301 QtVariantProperty *fontProperty = vm->variantProperty(antialiasingProperty);
302 const QFont::StyleStrategy newValue = indexToAntialiasing(value.toInt());
303
304 QFont font = qvariant_cast<QFont>(fontProperty->value());
305 const QFont::StyleStrategy oldValue = font.styleStrategy();
306 if (newValue == oldValue)
307 return DesignerPropertyManager::Unchanged;
308
309 font.setStyleStrategy(newValue);
310 fontProperty->setValue(QVariant::fromValue(font));
311 return DesignerPropertyManager::Changed;
312 }
313
314 int FontPropertyManager::hintingPreferenceValueChanged(QtVariantPropertyManager *vm,
315 QtProperty *hintingPreferenceProperty,
316 const QVariant &value)
317 {
318 QtVariantProperty *fontProperty = vm->variantProperty(hintingPreferenceProperty);
319 const QFont::HintingPreference newValue = indexToHintingPreference(value.toInt());
320
321 QFont font = qvariant_cast<QFont>(fontProperty->value());
322 const QFont::HintingPreference oldValue = font.hintingPreference();
323 if (newValue == oldValue)
324 return DesignerPropertyManager::Unchanged;
325
326 font.setHintingPreference(newValue);
327 fontProperty->setValue(QVariant::fromValue(font));
328 return DesignerPropertyManager::Changed;
329 }
330
331 void FontPropertyManager::updateModifiedState(QtProperty *property, const QVariant &value)
332 {
333 const auto it = m_propertyToFontSubProperties.find(property);
334 if (it == m_propertyToFontSubProperties.end())
335 return;
336
337 const PropertyList &subProperties = it.value();
338
339 QFont font = qvariant_cast<QFont>(value);
340 const unsigned mask = font.resolveMask();
341
342 const int count = subProperties.size();
343 for (int index = 0; index < count; index++) {
344 const unsigned flag = fontFlag(index);
345 subProperties.at(index)->setModified(mask & flag);
346 }
347 }
348
349 void FontPropertyManager::setValue(QtVariantPropertyManager *vm, QtProperty *property, const QVariant &value)
350 {
351 updateModifiedState(property, value);
352
353 if (QtProperty *antialiasingProperty = m_propertyToAntialiasing.value(property, 0)) {
354 QtVariantProperty *antialiasing = vm->variantProperty(antialiasingProperty);
355 if (antialiasing) {
356 QFont font = qvariant_cast<QFont>(value);
357 antialiasing->setValue(antialiasingToIndex(font.styleStrategy()));
358 }
359 }
360
361 if (QtProperty *hintingPreferenceProperty = m_propertyToHintingPreference.value(property, nullptr)) {
362 if (auto *hintingPreference = vm->variantProperty(hintingPreferenceProperty)) {
363 QFont font = qvariant_cast<QFont>(value);
364 hintingPreference->setValue(hintingPreferenceToIndex(font.hintingPreference()));
365 }
366 }
367
368 }
369
370 /* Parse a mappings file of the form:
371 * <fontmappings>
372 * <mapping><family>DejaVu Sans</family><display>DejaVu Sans [CE]</display></mapping>
373 * ... which is used to display on which platforms fonts are available.*/
374
375static constexpr auto rootTagC = "fontmappings"_L1;
376static constexpr auto mappingTagC = "mapping"_L1;
377static constexpr auto familyTagC = "family"_L1;
378static constexpr auto displayTagC = "display"_L1;
379
380 static QString msgXmlError(const QXmlStreamReader &r, const QString& fileName)
381 {
382 return u"An error has been encountered at line %1 of %2: %3:"_s.arg(r.lineNumber()).arg(fileName, r.errorString());
383 }
384
385 /* Switch stages when encountering a start element (state table) */
388
389 static ParseStage nextStage(ParseStage currentStage, QStringView startElement)
390 {
391 switch (currentStage) {
392 case ParseBeginning:
393 return startElement == rootTagC ? ParseWithinRoot : ParseError;
394 case ParseWithinRoot:
395 case ParseWithinDisplay: // Next mapping, was in <display>
396 return startElement == mappingTagC ? ParseWithinMapping : ParseError;
398 return startElement == familyTagC ? ParseWithinFamily : ParseError;
400 return startElement == displayTagC ? ParseWithinDisplay : ParseError;
401 case ParseError:
402 break;
403 }
404 return ParseError;
405 }
406
408 {
409 rc->clear();
410 const QString fileName = u":/qt-project.org/propertyeditor/fontmapping.xml"_s;
412 if (!file.open(QIODevice::ReadOnly)) {
413 *errorMessage = "Unable to open %1: %2"_L1.arg(fileName, file.errorString());
414 return false;
415 }
416
419
422 do {
424 switch (token) {
427 return false;
430 switch (stage) {
431 case ParseError:
432 reader.raiseError("Unexpected element <%1>."_L1.arg(reader.name()));
434 return false;
437 break;
440 break;
441 default:
442 break;
443 }
444 break;
445 default:
446 break;
447 }
448 } while (token != QXmlStreamReader::EndDocument);
449 return true;
450 }
451
452}
453
454QT_END_NAMESPACE
The QtProperty class encapsulates an instance of a property.
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[]
static constexpr auto rootTagC
static ParseStage nextStage(ParseStage currentStage, QStringView startElement)
static constexpr auto displayTagC
static const DisambiguatedTranslation hintingPreferenceC[]
static constexpr auto mappingTagC