0
|
1 |
/****************************************************************************
|
|
2 |
**
|
|
3 |
** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
|
|
4 |
** All rights reserved.
|
|
5 |
** Contact: Nokia Corporation (qt-info@nokia.com)
|
|
6 |
**
|
|
7 |
** This file is part of the Qt Designer of the Qt Toolkit.
|
|
8 |
**
|
|
9 |
** $QT_BEGIN_LICENSE:LGPL$
|
|
10 |
** No Commercial Usage
|
|
11 |
** This file contains pre-release code and may not be distributed.
|
|
12 |
** You may use this file in accordance with the terms and conditions
|
|
13 |
** contained in the Technology Preview License Agreement accompanying
|
|
14 |
** this package.
|
|
15 |
**
|
|
16 |
** GNU Lesser General Public License Usage
|
|
17 |
** Alternatively, this file may be used under the terms of the GNU Lesser
|
|
18 |
** General Public License version 2.1 as published by the Free Software
|
|
19 |
** Foundation and appearing in the file LICENSE.LGPL included in the
|
|
20 |
** packaging of this file. Please review the following information to
|
|
21 |
** ensure the GNU Lesser General Public License version 2.1 requirements
|
|
22 |
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
|
|
23 |
**
|
|
24 |
** In addition, as a special exception, Nokia gives you certain additional
|
|
25 |
** rights. These rights are described in the Nokia Qt LGPL Exception
|
|
26 |
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
|
|
27 |
**
|
|
28 |
** If you have questions regarding the use of this file, please contact
|
|
29 |
** Nokia at qt-info@nokia.com.
|
|
30 |
**
|
|
31 |
**
|
|
32 |
**
|
|
33 |
**
|
|
34 |
**
|
|
35 |
**
|
|
36 |
**
|
|
37 |
**
|
|
38 |
** $QT_END_LICENSE$
|
|
39 |
**
|
|
40 |
****************************************************************************/
|
|
41 |
|
|
42 |
#include "fontpropertymanager.h"
|
|
43 |
#include "qtpropertymanager.h"
|
|
44 |
#include "qtvariantproperty.h"
|
|
45 |
#include "qtpropertybrowserutils_p.h"
|
|
46 |
|
|
47 |
#include <qdesigner_utils_p.h>
|
|
48 |
|
|
49 |
#include <QtCore/QCoreApplication>
|
|
50 |
#include <QtCore/QVariant>
|
|
51 |
#include <QtCore/QString>
|
|
52 |
#include <QtCore/QDebug>
|
|
53 |
#include <QtCore/QFile>
|
|
54 |
#include <QtCore/QTextStream>
|
|
55 |
#include <QtXml/QXmlStreamReader>
|
|
56 |
|
|
57 |
QT_BEGIN_NAMESPACE
|
|
58 |
|
|
59 |
namespace qdesigner_internal {
|
|
60 |
|
|
61 |
static const char *aliasingC[] = {
|
|
62 |
QT_TRANSLATE_NOOP("FontPropertyManager", "PreferDefault"),
|
|
63 |
QT_TRANSLATE_NOOP("FontPropertyManager", "NoAntialias"),
|
|
64 |
QT_TRANSLATE_NOOP("FontPropertyManager", "PreferAntialias")
|
|
65 |
};
|
|
66 |
|
|
67 |
FontPropertyManager::FontPropertyManager() :
|
|
68 |
m_createdFontProperty(0)
|
|
69 |
{
|
|
70 |
const int nameCount = sizeof(aliasingC)/sizeof(const char *);
|
|
71 |
for (int i = 0; i < nameCount; i++)
|
|
72 |
m_aliasingEnumNames.push_back(QCoreApplication::translate("FontPropertyManager", aliasingC[i]));
|
|
73 |
|
|
74 |
QString errorMessage;
|
|
75 |
if (!readFamilyMapping(&m_familyMappings, &errorMessage)) {
|
|
76 |
designerWarning(errorMessage);
|
|
77 |
}
|
|
78 |
|
|
79 |
}
|
|
80 |
|
|
81 |
void FontPropertyManager::preInitializeProperty(QtProperty *property,
|
|
82 |
int type,
|
|
83 |
ResetMap &resetMap)
|
|
84 |
{
|
|
85 |
if (m_createdFontProperty) {
|
|
86 |
PropertyToSubPropertiesMap::iterator it = m_propertyToFontSubProperties.find(m_createdFontProperty);
|
|
87 |
if (it == m_propertyToFontSubProperties.end())
|
|
88 |
it = m_propertyToFontSubProperties.insert(m_createdFontProperty, PropertyList());
|
|
89 |
const int index = it.value().size();
|
|
90 |
m_fontSubPropertyToFlag.insert(property, index);
|
|
91 |
it.value().push_back(property);
|
|
92 |
m_fontSubPropertyToProperty[property] = m_createdFontProperty;
|
|
93 |
resetMap[property] = true;
|
|
94 |
}
|
|
95 |
|
|
96 |
if (type == QVariant::Font)
|
|
97 |
m_createdFontProperty = property;
|
|
98 |
}
|
|
99 |
|
|
100 |
// Map the font family names to display names retrieved from the XML configuration
|
|
101 |
static QStringList designerFamilyNames(QStringList families, const FontPropertyManager::NameMap &nm)
|
|
102 |
{
|
|
103 |
if (nm.empty())
|
|
104 |
return families;
|
|
105 |
|
|
106 |
const FontPropertyManager::NameMap::const_iterator ncend = nm.constEnd();
|
|
107 |
const QStringList::iterator end = families.end();
|
|
108 |
for (QStringList::iterator it = families.begin(); it != end; ++it) {
|
|
109 |
const FontPropertyManager::NameMap::const_iterator nit = nm.constFind(*it);
|
|
110 |
if (nit != ncend)
|
|
111 |
*it = nit.value();
|
|
112 |
}
|
|
113 |
return families;
|
|
114 |
}
|
|
115 |
|
|
116 |
void FontPropertyManager::postInitializeProperty(QtVariantPropertyManager *vm,
|
|
117 |
QtProperty *property,
|
|
118 |
int type,
|
|
119 |
int enumTypeId)
|
|
120 |
{
|
|
121 |
if (type != QVariant::Font)
|
|
122 |
return;
|
|
123 |
|
|
124 |
// This will cause a recursion
|
|
125 |
QtVariantProperty *antialiasing = vm->addProperty(enumTypeId, QCoreApplication::translate("FontPropertyManager", "Antialiasing"));
|
|
126 |
const QFont font = qVariantValue<QFont>(vm->variantProperty(property)->value());
|
|
127 |
|
|
128 |
antialiasing->setAttribute(QLatin1String("enumNames"), m_aliasingEnumNames);
|
|
129 |
antialiasing->setValue(antialiasingToIndex(font.styleStrategy()));
|
|
130 |
property->addSubProperty(antialiasing);
|
|
131 |
|
|
132 |
m_propertyToAntialiasing[property] = antialiasing;
|
|
133 |
m_antialiasingToProperty[antialiasing] = property;
|
|
134 |
// Fiddle family names
|
|
135 |
if (!m_familyMappings.empty()) {
|
|
136 |
const PropertyToSubPropertiesMap::iterator it = m_propertyToFontSubProperties.find(m_createdFontProperty);
|
|
137 |
QtVariantProperty *familyProperty = vm->variantProperty(it.value().front());
|
|
138 |
const QString enumNamesAttribute = QLatin1String("enumNames");
|
|
139 |
QStringList plainFamilyNames = familyProperty->attributeValue(enumNamesAttribute).toStringList();
|
|
140 |
// Did someone load fonts or something?
|
|
141 |
if (m_designerFamilyNames.size() != plainFamilyNames.size())
|
|
142 |
m_designerFamilyNames = designerFamilyNames(plainFamilyNames, m_familyMappings);
|
|
143 |
familyProperty->setAttribute(enumNamesAttribute, m_designerFamilyNames);
|
|
144 |
}
|
|
145 |
// Next
|
|
146 |
m_createdFontProperty = 0;
|
|
147 |
}
|
|
148 |
|
|
149 |
bool FontPropertyManager::uninitializeProperty(QtProperty *property)
|
|
150 |
{
|
|
151 |
const PropertyToPropertyMap::iterator ait = m_propertyToAntialiasing.find(property);
|
|
152 |
if (ait != m_propertyToAntialiasing.end()) {
|
|
153 |
QtProperty *antialiasing = ait.value();
|
|
154 |
m_antialiasingToProperty.remove(antialiasing);
|
|
155 |
m_propertyToAntialiasing.erase(ait);
|
|
156 |
delete antialiasing;
|
|
157 |
}
|
|
158 |
|
|
159 |
PropertyToSubPropertiesMap::iterator sit = m_propertyToFontSubProperties.find(property);
|
|
160 |
if (sit == m_propertyToFontSubProperties.end())
|
|
161 |
return false;
|
|
162 |
|
|
163 |
m_propertyToFontSubProperties.erase(sit);
|
|
164 |
m_fontSubPropertyToFlag.remove(property);
|
|
165 |
m_fontSubPropertyToProperty.remove(property);
|
|
166 |
|
|
167 |
return true;
|
|
168 |
}
|
|
169 |
|
|
170 |
void FontPropertyManager::slotPropertyDestroyed(QtProperty *property)
|
|
171 |
{
|
|
172 |
removeAntialiasingProperty(property);
|
|
173 |
}
|
|
174 |
|
|
175 |
void FontPropertyManager::removeAntialiasingProperty(QtProperty *property)
|
|
176 |
{
|
|
177 |
const PropertyToPropertyMap::iterator ait = m_antialiasingToProperty.find(property);
|
|
178 |
if (ait == m_antialiasingToProperty.end())
|
|
179 |
return;
|
|
180 |
m_propertyToAntialiasing[ait.value()] = 0;
|
|
181 |
m_antialiasingToProperty.erase(ait);
|
|
182 |
}
|
|
183 |
|
|
184 |
bool FontPropertyManager::resetFontSubProperty(QtVariantPropertyManager *vm, QtProperty *property)
|
|
185 |
{
|
|
186 |
const PropertyToPropertyMap::iterator it = m_fontSubPropertyToProperty.find(property);
|
|
187 |
if (it == m_fontSubPropertyToProperty.end())
|
|
188 |
return false;
|
|
189 |
|
|
190 |
QtVariantProperty *fontProperty = vm->variantProperty(it.value());
|
|
191 |
|
|
192 |
QVariant v = fontProperty->value();
|
|
193 |
QFont font = qvariant_cast<QFont>(v);
|
|
194 |
unsigned mask = font.resolve();
|
|
195 |
const unsigned flag = fontFlag(m_fontSubPropertyToFlag.value(property));
|
|
196 |
|
|
197 |
mask &= ~flag;
|
|
198 |
font.resolve(mask);
|
|
199 |
qVariantSetValue(v, 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 |
unsigned FontPropertyManager::fontFlag(int idx)
|
|
226 |
{
|
|
227 |
switch (idx) {
|
|
228 |
case 0: return QFont::FamilyResolved;
|
|
229 |
case 1: return QFont::SizeResolved;
|
|
230 |
case 2: return QFont::WeightResolved;
|
|
231 |
case 3: return QFont::StyleResolved;
|
|
232 |
case 4: return QFont::UnderlineResolved;
|
|
233 |
case 5: return QFont::StrikeOutResolved;
|
|
234 |
case 6: return QFont::KerningResolved;
|
|
235 |
case 7: return QFont::StyleStrategyResolved;
|
|
236 |
}
|
|
237 |
return 0;
|
|
238 |
}
|
|
239 |
|
|
240 |
FontPropertyManager::ValueChangedResult FontPropertyManager::valueChanged(QtVariantPropertyManager *vm, QtProperty *property, const QVariant &value)
|
|
241 |
{
|
|
242 |
QtProperty *antialiasingProperty = m_antialiasingToProperty.value(property, 0);
|
|
243 |
if (!antialiasingProperty) {
|
|
244 |
if (m_propertyToFontSubProperties.contains(property)) {
|
|
245 |
updateModifiedState(property, value);
|
|
246 |
}
|
|
247 |
return NoMatch;
|
|
248 |
}
|
|
249 |
|
|
250 |
QtVariantProperty *fontProperty = vm->variantProperty(antialiasingProperty);
|
|
251 |
const QFont::StyleStrategy newValue = indexToAntialiasing(value.toInt());
|
|
252 |
|
|
253 |
QFont font = qVariantValue<QFont>(fontProperty->value());
|
|
254 |
const QFont::StyleStrategy oldValue = font.styleStrategy();
|
|
255 |
if (newValue == oldValue)
|
|
256 |
return Unchanged;
|
|
257 |
|
|
258 |
font.setStyleStrategy(newValue);
|
|
259 |
fontProperty->setValue(qVariantFromValue(font));
|
|
260 |
return Changed;
|
|
261 |
}
|
|
262 |
|
|
263 |
void FontPropertyManager::updateModifiedState(QtProperty *property, const QVariant &value)
|
|
264 |
{
|
|
265 |
const PropertyToSubPropertiesMap::iterator it = m_propertyToFontSubProperties.find(property);
|
|
266 |
if (it == m_propertyToFontSubProperties.end())
|
|
267 |
return;
|
|
268 |
|
|
269 |
const PropertyList &subProperties = it.value();
|
|
270 |
|
|
271 |
QFont font = qVariantValue<QFont>(value);
|
|
272 |
const unsigned mask = font.resolve();
|
|
273 |
|
|
274 |
const int count = subProperties.size();
|
|
275 |
for (int index = 0; index < count; index++) {
|
|
276 |
const unsigned flag = fontFlag(index);
|
|
277 |
subProperties.at(index)->setModified(mask & flag);
|
|
278 |
}
|
|
279 |
}
|
|
280 |
|
|
281 |
void FontPropertyManager::setValue(QtVariantPropertyManager *vm, QtProperty *property, const QVariant &value)
|
|
282 |
{
|
|
283 |
updateModifiedState(property, value);
|
|
284 |
|
|
285 |
if (QtProperty *antialiasingProperty = m_propertyToAntialiasing.value(property, 0)) {
|
|
286 |
QtVariantProperty *antialiasing = vm->variantProperty(antialiasingProperty);
|
|
287 |
if (antialiasing) {
|
|
288 |
QFont font = qVariantValue<QFont>(value);
|
|
289 |
antialiasing->setValue(antialiasingToIndex(font.styleStrategy()));
|
|
290 |
}
|
|
291 |
}
|
|
292 |
}
|
|
293 |
|
|
294 |
/* Parse a mappings file of the form:
|
|
295 |
* <fontmappings>
|
|
296 |
* <mapping><family>DejaVu Sans</family><display>DejaVu Sans [CE]</display></mapping>
|
|
297 |
* ... which is used to display on which platforms fonts are available.*/
|
|
298 |
|
|
299 |
static const char *rootTagC = "fontmappings";
|
|
300 |
static const char *mappingTagC = "mapping";
|
|
301 |
static const char *familyTagC = "family";
|
|
302 |
static const char *displayTagC = "display";
|
|
303 |
|
|
304 |
static QString msgXmlError(const QXmlStreamReader &r, const QString& fileName)
|
|
305 |
{
|
|
306 |
return QString::fromUtf8("An error has been encountered at line %1 of %2: %3:").arg(r.lineNumber()).arg(fileName, r.errorString());
|
|
307 |
}
|
|
308 |
|
|
309 |
/* Switch stages when encountering a start element (state table) */
|
|
310 |
enum ParseStage { ParseBeginning, ParseWithinRoot, ParseWithinMapping, ParseWithinFamily,
|
|
311 |
ParseWithinDisplay, ParseError };
|
|
312 |
|
|
313 |
static ParseStage nextStage(ParseStage currentStage, const QStringRef &startElement)
|
|
314 |
{
|
|
315 |
switch (currentStage) {
|
|
316 |
case ParseBeginning:
|
|
317 |
return startElement == QLatin1String(rootTagC) ? ParseWithinRoot : ParseError;
|
|
318 |
case ParseWithinRoot:
|
|
319 |
case ParseWithinDisplay: // Next mapping, was in <display>
|
|
320 |
return startElement == QLatin1String(mappingTagC) ? ParseWithinMapping : ParseError;
|
|
321 |
case ParseWithinMapping:
|
|
322 |
return startElement == QLatin1String(familyTagC) ? ParseWithinFamily : ParseError;
|
|
323 |
case ParseWithinFamily:
|
|
324 |
return startElement == QLatin1String(displayTagC) ? ParseWithinDisplay : ParseError;
|
|
325 |
case ParseError:
|
|
326 |
break;
|
|
327 |
}
|
|
328 |
return ParseError;
|
|
329 |
}
|
|
330 |
|
|
331 |
bool FontPropertyManager::readFamilyMapping(NameMap *rc, QString *errorMessage)
|
|
332 |
{
|
|
333 |
rc->clear();
|
|
334 |
const QString fileName = QLatin1String(":/trolltech/propertyeditor/fontmapping.xml");
|
|
335 |
QFile file(fileName);
|
|
336 |
if (!file.open(QIODevice::ReadOnly)) {
|
|
337 |
*errorMessage = QString::fromUtf8("Unable to open %1: %2").arg(fileName, file.errorString());
|
|
338 |
return false;
|
|
339 |
}
|
|
340 |
|
|
341 |
QXmlStreamReader reader(&file);
|
|
342 |
QXmlStreamReader::TokenType token;
|
|
343 |
|
|
344 |
QString family;
|
|
345 |
ParseStage stage = ParseBeginning;
|
|
346 |
do {
|
|
347 |
token = reader.readNext();
|
|
348 |
switch (token) {
|
|
349 |
case QXmlStreamReader::Invalid:
|
|
350 |
*errorMessage = msgXmlError(reader, fileName);
|
|
351 |
return false;
|
|
352 |
case QXmlStreamReader::StartElement:
|
|
353 |
stage = nextStage(stage, reader.name());
|
|
354 |
switch (stage) {
|
|
355 |
case ParseError:
|
|
356 |
reader.raiseError(QString::fromUtf8("Unexpected element <%1>.").arg(reader.name().toString()));
|
|
357 |
*errorMessage = msgXmlError(reader, fileName);
|
|
358 |
return false;
|
|
359 |
case ParseWithinFamily:
|
|
360 |
family = reader.readElementText();
|
|
361 |
break;
|
|
362 |
case ParseWithinDisplay:
|
|
363 |
rc->insert(family, reader.readElementText());
|
|
364 |
break;
|
|
365 |
default:
|
|
366 |
break;
|
|
367 |
}
|
|
368 |
default:
|
|
369 |
break;
|
|
370 |
}
|
|
371 |
} while (token != QXmlStreamReader::EndDocument);
|
|
372 |
return true;
|
|
373 |
}
|
|
374 |
|
|
375 |
}
|
|
376 |
|
|
377 |
QT_END_NAMESPACE
|