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
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 resetMap[property] = true;
69 }
70
71 if (type == QMetaType::QFont)
72 m_createdFontProperty = property;
73 }
74
75 // Map the font family names to display names retrieved from the XML configuration
76 static QStringList designerFamilyNames(QStringList families, const FontPropertyManager::NameMap &nm)
77 {
78 if (nm.isEmpty())
79 return families;
80
81 const auto ncend = nm.constEnd();
82 for (auto it = families.begin(), end = families.end(); it != end; ++it) {
83 const auto nit = nm.constFind(*it);
84 if (nit != ncend)
85 *it = nit.value();
86 }
87 return families;
88 }
89
91 QtProperty *property,
92 int type,
93 int enumTypeId)
94 {
95 if (type != QMetaType::QFont)
96 return;
97
98 // This will cause a recursion
99 QtVariantProperty *antialiasing = vm->addProperty(enumTypeId, QCoreApplication::translate("FontPropertyManager", "Antialiasing"));
100 const QFont font = qvariant_cast<QFont>(vm->variantProperty(property)->value());
101
102 antialiasing->setAttribute(u"enumNames"_s, m_aliasingEnumNames);
103 antialiasing->setValue(antialiasingToIndex(font.styleStrategy()));
104 property->addSubProperty(antialiasing);
105
106 m_propertyToAntialiasing[property] = antialiasing;
107 m_antialiasingToProperty[antialiasing] = property;
108
109 QtVariantProperty *hintingPreference = vm->addProperty(enumTypeId, QCoreApplication::translate("FontPropertyManager", "HintingPreference"));
110 hintingPreference->setAttribute(u"enumNames"_s, m_hintingPreferenceEnumNames);
111 hintingPreference->setValue(hintingPreferenceToIndex(font.hintingPreference()));
112 property->addSubProperty(hintingPreference);
113
114 m_propertyToHintingPreference[property] = hintingPreference;
115 m_hintingPreferenceToProperty[hintingPreference] = property;
116
117 // Fiddle family names
118 if (!m_familyMappings.isEmpty()) {
119 const auto it = m_propertyToFontSubProperties.find(m_createdFontProperty);
120 QtVariantProperty *familyProperty = vm->variantProperty(it.value().constFirst());
121 const QString enumNamesAttribute = u"enumNames"_s;
122 QStringList plainFamilyNames = familyProperty->attributeValue(enumNamesAttribute).toStringList();
123 // Did someone load fonts or something?
124 if (m_designerFamilyNames.size() != plainFamilyNames.size())
125 m_designerFamilyNames = designerFamilyNames(plainFamilyNames, m_familyMappings);
126 familyProperty->setAttribute(enumNamesAttribute, m_designerFamilyNames);
127 }
128 // Next
129 m_createdFontProperty = nullptr;
130 }
131
133 {
134 const auto ait = m_propertyToAntialiasing.find(property);
135 if (ait != m_propertyToAntialiasing.end()) {
136 QtProperty *antialiasing = ait.value();
137 m_antialiasingToProperty.remove(antialiasing);
138 m_propertyToAntialiasing.erase(ait);
139 delete antialiasing;
140 }
141
142 const auto hit = m_propertyToHintingPreference.find(property);
143 if (hit != m_propertyToHintingPreference.end()) {
144 QtProperty *hintingPreference = hit.value();
145 m_hintingPreferenceToProperty.remove(hintingPreference);
146 m_propertyToHintingPreference.erase(hit);
147 delete hintingPreference;
148 }
149
150 const auto sit = m_propertyToFontSubProperties.find(property);
151 if (sit == m_propertyToFontSubProperties.end())
152 return false;
153
154 m_propertyToFontSubProperties.erase(sit);
155 m_fontSubPropertyToFlag.remove(property);
156
157 return true;
158 }
159
161 {
162 removeAntialiasingProperty(property);
163 removeHintingPreferenceProperty(property);
164 }
165
166 void FontPropertyManager::removeAntialiasingProperty(QtProperty *property)
167 {
168 const auto ait = m_antialiasingToProperty.find(property);
169 if (ait == m_antialiasingToProperty.end())
170 return;
171 m_propertyToAntialiasing[ait.value()] = 0;
172 m_antialiasingToProperty.erase(ait);
173 }
174
175 void FontPropertyManager::removeHintingPreferenceProperty(QtProperty *property)
176 {
177 const auto hit = m_hintingPreferenceToProperty.find(property);
178 if (hit == m_hintingPreferenceToProperty.end())
179 return;
180 m_propertyToHintingPreference[hit.value()] = nullptr;
181 m_hintingPreferenceToProperty.erase(hit);
182 }
183
185 {
186 auto *parentItem = property->parentProperty();
187 if (!m_propertyToFontSubProperties.contains(parentItem))
188 return false;
189
190 QtVariantProperty *fontProperty = vm->variantProperty(parentItem);
191
192 QVariant v = fontProperty->value();
193 QFont font = qvariant_cast<QFont>(v);
194 unsigned mask = font.resolveMask();
195 const unsigned flag = fontFlag(m_fontSubPropertyToFlag.value(property));
196
197 mask &= ~flag;
198 font.setResolveMask(mask);
199 v.setValue(font);
200 fontProperty->setValue(v);
201 return true;
202 }
203
204 int FontPropertyManager::antialiasingToIndex(QFont::StyleStrategy antialias)
205 {
206 switch (antialias) {
207 case QFont::PreferDefault: return 0;
208 case QFont::NoAntialias: return 1;
209 case QFont::PreferAntialias: return 2;
210 default: break;
211 }
212 return 0;
213 }
214
215 QFont::StyleStrategy FontPropertyManager::indexToAntialiasing(int idx)
216 {
217 switch (idx) {
218 case 0: return QFont::PreferDefault;
219 case 1: return QFont::NoAntialias;
220 case 2: return QFont::PreferAntialias;
221 }
222 return QFont::PreferDefault;
223 }
224
225 int FontPropertyManager::hintingPreferenceToIndex(QFont::HintingPreference h)
226 {
227 switch (h) {
228 case QFont::PreferDefaultHinting:
229 return 0;
230 case QFont::PreferNoHinting:
231 return 1;
232 case QFont::PreferVerticalHinting:
233 return 2;
234 case QFont::PreferFullHinting:
235 return 3;
236 }
237 return 0;
238 }
239
240 QFont::HintingPreference FontPropertyManager::indexToHintingPreference(int idx)
241 {
242 switch (idx) {
243 case 0:
244 return QFont::PreferDefaultHinting;
245 case 1:
246 return QFont::PreferNoHinting;
247 case 2:
248 return QFont::PreferVerticalHinting;
249 case 3:
250 return QFont::PreferFullHinting;
251 }
252 return QFont::PreferDefaultHinting;
253 }
254
255 unsigned FontPropertyManager::fontFlag(int idx)
256 {
257 switch (idx) {
258 case 0:
259 return QFont::FamilyResolved | QFont::FamiliesResolved;
260 case 1:
261 return QFont::SizeResolved;
262 case 2:
263 case 7:
264 return QFont::WeightResolved;
265 case 3:
266 return QFont::StyleResolved;
267 case 4:
268 return QFont::UnderlineResolved;
269 case 5:
270 return QFont::StrikeOutResolved;
271 case 6:
272 return QFont::KerningResolved;
273 case 8:
274 return QFont::StyleStrategyResolved;
275 case 9:
276 return QFont::HintingPreferenceResolved;
277 }
278 return 0;
279 }
280
281 int FontPropertyManager::valueChanged(QtVariantPropertyManager *vm, QtProperty *property, const QVariant &value)
282 {
283 if (auto *antialiasingProperty = m_antialiasingToProperty.value(property, nullptr))
284 return antialiasingValueChanged(vm, antialiasingProperty, value);
285
286 if (auto *hintingPreferenceProperty = m_hintingPreferenceToProperty.value(property, nullptr))
287 return hintingPreferenceValueChanged(vm, hintingPreferenceProperty, value);
288
289 if (m_propertyToFontSubProperties.contains(property))
290 updateModifiedState(property, value);
291
292 return DesignerPropertyManager::NoMatch;
293 }
294
295 int FontPropertyManager::antialiasingValueChanged(QtVariantPropertyManager *vm,
296 QtProperty *antialiasingProperty,
297 const QVariant &value)
298 {
299 QtVariantProperty *fontProperty = vm->variantProperty(antialiasingProperty);
300 const QFont::StyleStrategy newValue = indexToAntialiasing(value.toInt());
301
302 QFont font = qvariant_cast<QFont>(fontProperty->value());
303 const QFont::StyleStrategy oldValue = font.styleStrategy();
304 if (newValue == oldValue)
305 return DesignerPropertyManager::Unchanged;
306
307 font.setStyleStrategy(newValue);
308 fontProperty->setValue(QVariant::fromValue(font));
309 return DesignerPropertyManager::Changed;
310 }
311
312 int FontPropertyManager::hintingPreferenceValueChanged(QtVariantPropertyManager *vm,
313 QtProperty *hintingPreferenceProperty,
314 const QVariant &value)
315 {
316 QtVariantProperty *fontProperty = vm->variantProperty(hintingPreferenceProperty);
317 const QFont::HintingPreference newValue = indexToHintingPreference(value.toInt());
318
319 QFont font = qvariant_cast<QFont>(fontProperty->value());
320 const QFont::HintingPreference oldValue = font.hintingPreference();
321 if (newValue == oldValue)
322 return DesignerPropertyManager::Unchanged;
323
324 font.setHintingPreference(newValue);
325 fontProperty->setValue(QVariant::fromValue(font));
326 return DesignerPropertyManager::Changed;
327 }
328
329 void FontPropertyManager::updateModifiedState(QtProperty *property, const QVariant &value)
330 {
331 const auto it = m_propertyToFontSubProperties.find(property);
332 if (it == m_propertyToFontSubProperties.end())
333 return;
334
335 const PropertyList &subProperties = it.value();
336
337 QFont font = qvariant_cast<QFont>(value);
338 const unsigned mask = font.resolveMask();
339
340 const int count = subProperties.size();
341 for (int index = 0; index < count; index++) {
342 const unsigned flag = fontFlag(index);
343 subProperties.at(index)->setModified(mask & flag);
344 }
345 }
346
347 void FontPropertyManager::setValue(QtVariantPropertyManager *vm, QtProperty *property, const QVariant &value)
348 {
349 updateModifiedState(property, value);
350
351 if (QtProperty *antialiasingProperty = m_propertyToAntialiasing.value(property, 0)) {
352 QtVariantProperty *antialiasing = vm->variantProperty(antialiasingProperty);
353 if (antialiasing) {
354 QFont font = qvariant_cast<QFont>(value);
355 antialiasing->setValue(antialiasingToIndex(font.styleStrategy()));
356 }
357 }
358
359 if (QtProperty *hintingPreferenceProperty = m_propertyToHintingPreference.value(property, nullptr)) {
360 if (auto *hintingPreference = vm->variantProperty(hintingPreferenceProperty)) {
361 QFont font = qvariant_cast<QFont>(value);
362 hintingPreference->setValue(hintingPreferenceToIndex(font.hintingPreference()));
363 }
364 }
365
366 }
367
368 /* Parse a mappings file of the form:
369 * <fontmappings>
370 * <mapping><family>DejaVu Sans</family><display>DejaVu Sans [CE]</display></mapping>
371 * ... which is used to display on which platforms fonts are available.*/
372
373static constexpr auto rootTagC = "fontmappings"_L1;
374static constexpr auto mappingTagC = "mapping"_L1;
375static constexpr auto familyTagC = "family"_L1;
376static constexpr auto displayTagC = "display"_L1;
377
378 static QString msgXmlError(const QXmlStreamReader &r, const QString& fileName)
379 {
380 return u"An error has been encountered at line %1 of %2: %3:"_s.arg(r.lineNumber()).arg(fileName, r.errorString());
381 }
382
383 /* Switch stages when encountering a start element (state table) */
386
387 static ParseStage nextStage(ParseStage currentStage, QStringView startElement)
388 {
389 switch (currentStage) {
390 case ParseBeginning:
391 return startElement == rootTagC ? ParseWithinRoot : ParseError;
392 case ParseWithinRoot:
393 case ParseWithinDisplay: // Next mapping, was in <display>
394 return startElement == mappingTagC ? ParseWithinMapping : ParseError;
396 return startElement == familyTagC ? ParseWithinFamily : ParseError;
398 return startElement == displayTagC ? ParseWithinDisplay : ParseError;
399 case ParseError:
400 break;
401 }
402 return ParseError;
403 }
404
406 {
407 rc->clear();
408 const QString fileName = u":/qt-project.org/propertyeditor/fontmapping.xml"_s;
410 if (!file.open(QIODevice::ReadOnly)) {
411 *errorMessage = "Unable to open %1: %2"_L1.arg(fileName, file.errorString());
412 return false;
413 }
414
417
420 do {
422 switch (token) {
425 return false;
428 switch (stage) {
429 case ParseError:
430 reader.raiseError("Unexpected element <%1>."_L1.arg(reader.name()));
432 return false;
435 break;
438 break;
439 default:
440 break;
441 }
442 break;
443 default:
444 break;
445 }
446 } while (token != QXmlStreamReader::EndDocument);
447 return true;
448 }
449
450}
451
452QT_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