tools/designer/src/components/propertyeditor/fontpropertymanager.cpp
changeset 0 1918ee327afb
child 4 3b1da2848fc7
equal deleted inserted replaced
-1:000000000000 0:1918ee327afb
       
     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