src/hbcore/cssparser/hbcssparser_p.cpp
changeset 30 80e4d18b72f5
parent 28 b7da29130b0e
equal deleted inserted replaced
28:b7da29130b0e 30:80e4d18b72f5
    23 **
    23 **
    24 ****************************************************************************/
    24 ****************************************************************************/
    25 
    25 
    26 #include "hbcssparser_p.h"
    26 #include "hbcssparser_p.h"
    27 
    27 
    28 #include <new>
    28 #include <QDebug>
    29 #include <qdebug.h>
    29 #include <QColor>
    30 #include <qcolor.h>
    30 #include <QFont>
    31 #include <qfont.h>
    31 #include <QGraphicsWidget>
    32 #include <qfileinfo.h>
    32 #include <QStack>
    33 #include <qfontmetrics.h>
       
    34 #include <qbrush.h>
       
    35 #include <qimagereader.h>
       
    36 #include <qgraphicswidget.h>
       
    37 
    33 
    38 //QT_BEGIN_NAMESPACE
    34 //QT_BEGIN_NAMESPACE
    39 
    35 
    40 //#define CSSPARSER_DEBUG 
    36 //#define CSSPARSER_DEBUG 
    41 
    37 
    47 #include "hbhash_p.h"
    43 #include "hbhash_p.h"
    48 
    44 
    49 using namespace HbCss;
    45 using namespace HbCss;
    50 
    46 
    51 const QString GLOBAL_CSS_SELECTOR = "*";
    47 const QString GLOBAL_CSS_SELECTOR = "*";
       
    48 const uint GLOBAL_CSS_SELECTOR_HASH = qHash(GLOBAL_CSS_SELECTOR.toLatin1());
    52 
    49 
    53 struct HbCssKnownValue
    50 struct HbCssKnownValue
    54 {
    51 {
    55     const char *name;
    52     const char *name;
    56     quint64 id;
    53     quint64 id;
   196     if ( currentProfile.isNull() ) {
   193     if ( currentProfile.isNull() ) {
   197         currentProfile = HbDeviceProfile::current();
   194         currentProfile = HbDeviceProfile::current();
   198     }
   195     }
   199 }
   196 }
   200 
   197 
   201 qreal ValueExtractor::asReal(const Value& v, bool *ok)
   198 qreal ValueExtractor::asReal(const Value& v, bool *ok) const
   202 {
   199 {
   203     if (ok) {
   200     if (ok) {
   204         *ok = true;
   201         *ok = true;
   205     }
   202     }
   206 
   203 
   220         bool tempOk = extractVariableValue((quint32)v.variant.toInt(), variableValue);
   217         bool tempOk = extractVariableValue((quint32)v.variant.toInt(), variableValue);
   221         if (ok) {
   218         if (ok) {
   222             *ok = tempOk;
   219             *ok = tempOk;
   223         }
   220         }
   224         return factor * variableValue;
   221         return factor * variableValue;
       
   222     } else if (v.type == Value::Expression || v.type == Value::ExpressionNegative) {
       
   223         qreal factor = (v.type == Value::Expression) ? 1.0 : -1.0;
       
   224         qreal variableValue(0.0);
       
   225         bool tempOk = extractExpressionValue(v.variant.toIntList(), variableValue);
       
   226         if (ok) {
       
   227             *ok = tempOk;
       
   228         }
       
   229         return factor * variableValue;
   225     }
   230     }
   226 
   231 
   227     QString s = v.variant.toString();
   232     QString s = v.variant.toString();
   228     s.reserve(s.length());
   233     s.reserve(s.length());
   229 
   234 
   230     if (v.type == Value::Expression || v.type == Value::ExpressionNegative) {
       
   231         qreal factor = (v.type == Value::Expression) ? 1.0 : -1.0;
       
   232         qreal value = 0;
       
   233         extractExpressionValue(s, value);
       
   234         return factor * value;
       
   235     }
       
   236     return asReal(s, v.type, ok);
   235     return asReal(s, v.type, ok);
   237 }
   236 }
   238 
   237 
   239 qreal ValueExtractor::asReal(QString &s, Value::Type type, bool *ok)
   238 qreal ValueExtractor::asReal(int token, HbExpressionParser::Token type, bool &ok) const
       
   239 {
       
   240     ok = true;
       
   241     qreal result(0.0);
       
   242     switch (type) {
       
   243         case HbExpressionParser::Variable:
       
   244             ok = extractVariableValue((quint32)token, result);
       
   245             break;
       
   246         case HbExpressionParser::LengthInUnits:
       
   247             result = HbExpressionParser::fromFixed(token) * currentProfile.unitValue();
       
   248             break;
       
   249         case HbExpressionParser::LengthInPixels:
       
   250             result = HbExpressionParser::fromFixed(token);
       
   251             break;
       
   252         case HbExpressionParser::LengthInMillimeters:
       
   253             result = HbExpressionParser::fromFixed(token) * currentProfile.ppmValue();
       
   254             break;
       
   255         default:
       
   256             ok = false;
       
   257             break;
       
   258     }
       
   259     return result;
       
   260 }
       
   261 
       
   262 qreal ValueExtractor::asReal(QString &s, Value::Type type, bool *ok) const
   240 {
   263 {
   241     if (ok) {
   264     if (ok) {
   242         *ok = true;
   265         *ok = true;
   243     }
   266     }
   244 
   267 
   286         result = currentProfile.ppmValue() * result;
   309         result = currentProfile.ppmValue() * result;
   287     } // else -> already in pixels
   310     } // else -> already in pixels
   288     return result;
   311     return result;
   289 }
   312 }
   290 
   313 
   291 qreal ValueExtractor::asReal(const Declaration &decl, bool *ok)
   314 qreal ValueExtractor::asReal(const Declaration &decl, bool *ok) const
   292 {
   315 {
   293     if (decl.values.count() < 1) {
   316     if (decl.values.count() < 1) {
   294         if (ok) {
   317         if (ok) {
   295             *ok = false;
   318             *ok = false;
   296         }
   319         }
   297         return 0;
   320         return 0;
   298     }
   321     }
   299     return asReal(decl.values.first(), ok);
   322     return asReal(decl.values.first(), ok);
   300 }
   323 }
   301 
   324 
   302 bool ValueExtractor::asReals(const Declaration &decl, qreal *m)
   325 bool ValueExtractor::asReals(const Declaration &decl, qreal *m) const
   303 {
   326 {
   304     bool ok = true;
   327     bool ok = true;
   305     int i;
   328     int i;
   306     for (i = 0; i < qMin(decl.values.count(), 4); i++) {
   329     for (i = 0; i < qMin(decl.values.count(), 4); i++) {
   307         m[i] = asReal(decl.values[i], &ok);
   330         m[i] = asReal(decl.values[i], &ok);
   485     QString family;
   508     QString family;
   486     for (int i = 0; i < decl.values.count(); ++i) {
   509     for (int i = 0; i < decl.values.count(); ++i) {
   487         const Value &v = decl.values.at(i);
   510         const Value &v = decl.values.at(i);
   488         if (v.type == Value::TermOperatorComma)
   511         if (v.type == Value::TermOperatorComma)
   489             break;
   512             break;
   490         const QString str = v.variant.toString();
   513         const QString &str = v.variant.toString();
   491         if (str.isEmpty())
   514         if (str.isEmpty())
   492             break;
   515             break;
   493         family += str;
   516         family += str;
   494         family += QLatin1Char(' ');
   517         family += QLatin1Char(' ');
   495     }
   518     }
   537         setFontSizeFromValue(decl.values.at(i), font);
   560         setFontSizeFromValue(decl.values.at(i), font);
   538         ++i;
   561         ++i;
   539     }
   562     }
   540 
   563 
   541     if (i < decl.values.count()) {
   564     if (i < decl.values.count()) {
   542         QString fam = decl.values.at(i).variant.toString();
   565         const QString &fam = decl.values.at(i).variant.toString();
   543         if (!fam.isEmpty())
   566         if (!fam.isEmpty())
   544             font.setFamily(fam);
   567             font.setFamily(fam);
   545     }
   568     }
   546 }
   569 }
   547 
   570 
   576             default: break;
   599             default: break;
   577         }
   600         }
   578     }
   601     }
   579 }
   602 }
   580 
   603 
   581 bool ValueExtractor::extractKnownProperties(KnownProperties &prop)
   604 bool ValueExtractor::extractKnownProperties(KnownProperties &prop) const
   582 {
   605 {
   583     KnownPropertyFlags flags(0);
   606     KnownPropertyFlags flags(0);
   584     bool hit = false;
   607     bool hit = false;
   585     bool tphSet = false;
   608     bool tphSet = false;
   586 
   609 
   802     }
   825     }
   803     return variableFound;
   826     return variableFound;
   804 }
   827 }
   805 
   828 
   806 
   829 
   807 bool ValueExtractor::extractVariableValue(quint32 hashValue, qreal& value)
   830 bool ValueExtractor::extractVariableValue(quint32 hashValue, qreal& value) const
   808 {
   831 {
   809     bool variableFound = false;
   832     bool variableFound = false;
   810     HbCss::Value v;
   833     HbCss::Value v;
   811     if (extractVariableValue(hashValue, v)) {
   834     if (extractVariableValue(hashValue, v)) {
   812         value = asReal(v);
   835         value = asReal(v);
   818 bool ValueExtractor::extractVariableValue(const QString& variableName, HbCss::Value &value) const
   841 bool ValueExtractor::extractVariableValue(const QString& variableName, HbCss::Value &value) const
   819 {
   842 {
   820     return extractVariableValue(hbHash(variableName), value);
   843     return extractVariableValue(hbHash(variableName), value);
   821 }
   844 }
   822 
   845 
   823 bool ValueExtractor::extractVariableValue(const QString& variableName, qreal& value)
   846 bool ValueExtractor::extractVariableValue(const QString& variableName, qreal& value) const
   824 {
   847 {
   825     return extractVariableValue(hbHash(variableName), value);
   848     return extractVariableValue(hbHash(variableName), value);
   826 }
   849 }
   827 
   850 
   828 bool ValueExtractor::extractExpressionValue(QString &expression, qreal &value)
   851 bool ValueExtractor::extractExpressionValue(const QList<int> &tokens, qreal &value) const
   829 {
   852 {
   830     // todo: invalid global variables are not checked because asReal() doesn't check them
   853     // The expression is in RPN format
   831     value = 0;
   854     bool ok(true);
   832     const QChar SPACE(' ');
   855     QStack<qreal> values;
   833     const QChar LPARENTHESIS('(');
   856     for (int i=0; i<tokens.count(); i++) {
   834     const QChar RPARENTHESIS(')');
   857         HbExpressionParser::Token t = (HbExpressionParser::Token)tokens.at(i);
   835     const QChar MINUS('-');
   858         switch (t) {
   836     const QChar PLUS('+');
   859             case HbExpressionParser::Variable:
   837     const QChar STAR('*');
   860             case HbExpressionParser::LengthInPixels:
   838     const QChar SLASH('/');
   861             case HbExpressionParser::LengthInUnits:
   839 
   862             case HbExpressionParser::LengthInMillimeters:
   840     int position = 0;
   863                 {
   841     int begin = -1;
   864                 i++;
   842     // + and - are level 0, * and / in level 1, unary - is level 2
   865                 int val = tokens.at(i);
   843     // every parenthesis add 10 to (base) precedence level
   866                 values.push(asReal(val, t, ok));
   844     int precedenceLevel = 0; 
   867                 if (!ok) {
   845     bool parseVariable = false;
       
   846     bool endMark = false;
       
   847     int operatorCount = 1;//there can only be 2 sequental operators if the latter one is unary '-'
       
   848     while (position < expression.size()) {
       
   849         endMark = false;
       
   850         if (expression.at(position) == SPACE) {
       
   851             endMark = true;
       
   852         } else if ((expression.at(position) == LPARENTHESIS) && !parseVariable) {
       
   853             precedenceLevel+=10;
       
   854             position++;
       
   855             operatorCount = 1;
       
   856             continue;
       
   857         } else if (expression.at(position) == RPARENTHESIS) {
       
   858             if (parseVariable) {
       
   859                 parseVariable = false;
       
   860                 operatorCount = 0;
       
   861                 position++;
       
   862                 continue;
       
   863             }
       
   864             precedenceLevel-=10;
       
   865             operatorCount = 0;
       
   866             endMark = true;
       
   867         } else if ((expression.at(position) == MINUS) && !parseVariable) {
       
   868             endMark = true;
       
   869         } else if ((expression.at(position) == PLUS) ||
       
   870                    (expression.at(position) == STAR) ||
       
   871                    (expression.at(position) == SLASH)) {
       
   872             endMark = true;
       
   873         }
       
   874 
       
   875         if (endMark) {
       
   876             if (begin >= 0) {
       
   877                 // parse value
       
   878                 QString valueString = expression.mid(begin, position - begin);
       
   879                 qreal val = 0;
       
   880                 if (valueString.startsWith("var(") && valueString.endsWith(")")) {
       
   881                     // remove var( and last )
       
   882                     QString variableString = valueString.mid(4, valueString.size()-5);
       
   883                     if (!extractVariableValue(variableString, val)) {
       
   884                         expressionValues.clear();
       
   885                         return false;
       
   886                     }
       
   887                 } else {
       
   888                     bool real_ok = true;
       
   889                     val = asReal(valueString, Value::String, &real_ok);
       
   890                     if (!real_ok) {
       
   891                         expressionValues.clear();
       
   892                         return false;
       
   893                     }
       
   894                 }
       
   895                 expressionValues.append(ExpressionValue(ExpressionValue::None, 0, val));
       
   896                 operatorCount = 0;
       
   897             }
       
   898             begin = -1;
       
   899             if (expression.at(position) == MINUS) {
       
   900                 if (operatorCount == 1) {
       
   901                     expressionValues.append(
       
   902                         ExpressionValue(ExpressionValue::UnaryMinus,precedenceLevel+2,0));
       
   903                 } else if (operatorCount > 1) {
       
   904                     expressionValues.clear();
       
   905                     return false;
       
   906                 } else {
       
   907                     expressionValues.append(
       
   908                         ExpressionValue(ExpressionValue::Minus,precedenceLevel,0));
       
   909                 }
       
   910                 operatorCount++;
       
   911             } else if (expression.at(position) == PLUS) {
       
   912                 if (operatorCount > 0) {
       
   913                     expressionValues.clear();
       
   914                     return false;
   868                     return false;
   915                 }
   869                 }
   916                 expressionValues.append(
   870                 break;
   917                     ExpressionValue(ExpressionValue::Plus,precedenceLevel,0));
   871                 }
   918                 operatorCount++;
   872             case HbExpressionParser::Addition:
   919             } else if (expression.at(position) == STAR) {
   873                 {
   920                 if (operatorCount > 0) {
   874                 qreal op1 = values.pop();
   921                     expressionValues.clear();
   875                 qreal op2 = values.pop();
       
   876                 values.push(op2+op1);
       
   877                 break;
       
   878                 }
       
   879             case HbExpressionParser::Subtraction:
       
   880                 {
       
   881                 qreal op1 = values.pop();
       
   882                 qreal op2 = values.pop();
       
   883                 values.push(op2-op1);
       
   884                 break;
       
   885                 }
       
   886             case HbExpressionParser::Multiplication:
       
   887                 {
       
   888                 qreal op1 = values.pop();
       
   889                 qreal op2 = values.pop();
       
   890                 values.push(op2*op1);
       
   891                 break;
       
   892                 }
       
   893             case HbExpressionParser::Division:
       
   894                 {
       
   895                 qreal op1 = values.pop();
       
   896                 qreal op2 = values.pop();
       
   897                 if (op1 == 0) {
   922                     return false;
   898                     return false;
   923                 }
   899                 }
   924                 expressionValues.append(
   900                 values.push(op2/op1);
   925                     ExpressionValue(ExpressionValue::Star,precedenceLevel+1,0));
   901                 break;
   926                 operatorCount++;
       
   927             } else if (expression.at(position) == SLASH) {
       
   928                 if (operatorCount > 0) {
       
   929                     expressionValues.clear();
       
   930                     return false;
       
   931                 }
   902                 }
   932                 expressionValues.append(
   903             case HbExpressionParser::Negation:
   933                     ExpressionValue(ExpressionValue::Slash,precedenceLevel+1,0));
   904                 {
   934                 operatorCount++;
   905                 qreal op1 = values.pop();
   935             }
   906                 values.push(-op1);
   936             position++;
   907                 break;
   937             continue;
   908                 }
   938         }
   909             default:
   939 
   910                 return false;;
   940         if (begin == -1) {
   911         }
   941             begin = position;
   912     }
   942         }
   913 
   943 
   914     if (values.count() != 1) {
   944         // flag variable parsing (variable syntax contains parenthesis)
       
   945         if ((expression.at(position) == QChar('v')) && !parseVariable) {
       
   946             parseVariable = true;
       
   947             position++;
       
   948             continue;
       
   949         }
       
   950         position++;
       
   951     }
       
   952 
       
   953     // check for unmatching parentheses
       
   954     if (precedenceLevel != 0) {
       
   955         expressionValues.clear();
       
   956         return false;
   915         return false;
   957     }
   916     }
   958 
   917     value = values.at(0);
   959     // parse last value
   918     return true;
   960     if (begin >= 0) {
   919 }
   961         QString valueString = expression.mid(begin, position - begin);
   920 
   962         qreal val = 0;
   921 bool ValueExtractor::extractExpressionValue(const QString &expression, qreal &value) const
   963         if (valueString.startsWith("var(") && valueString.endsWith(")")) {
   922 {
   964             // remove var( and last )
   923     QList<int> tokens;
   965             QString variableString = valueString.mid(4, valueString.size()-5);
   924     if (!HbExpressionParser::parse(expression, tokens)) {
   966             if (!extractVariableValue(variableString, val)) {
       
   967                 expressionValues.clear();
       
   968                 return false;
       
   969             }
       
   970         } else {
       
   971             bool real_ok = true;
       
   972             val = asReal(valueString, Value::String, &real_ok);
       
   973             if (!real_ok) {
       
   974                 expressionValues.clear();
       
   975                 return false;
       
   976             }
       
   977         }
       
   978         expressionValues.append(ExpressionValue(ExpressionValue::None, 0, val));
       
   979     }
       
   980 
       
   981     if(expressionValues.isEmpty()) {
       
   982         expressionValues.clear();
       
   983         return false;
   925         return false;
   984     }
   926     }
   985         
   927     return extractExpressionValue(tokens, value);
   986     // if last value is operator, fail
   928 }
   987     if (expressionValues[expressionValues.size()-1].mToken != ExpressionValue::None) {
   929 
   988         expressionValues.clear();
   930 
   989         return false;
   931 bool ValueExtractor::extractCustomProperties( const QList<QString> &keys, QList<QVariant> &values ) const
   990     }
       
   991 
       
   992 
       
   993     while (expressionValues.size() > 1) { // we have an answer when size = 1
       
   994         int maxPrecedence = -1;
       
   995         int calculateIndex = -1;
       
   996         for (int i = 0; i < expressionValues.size(); i++) {
       
   997             if ((expressionValues[i].mToken != ExpressionValue::None) &&
       
   998                 (expressionValues[i].mPrecedence > maxPrecedence)) {
       
   999                 maxPrecedence = expressionValues[i].mPrecedence;
       
  1000                 calculateIndex = i; // contains operator with highest precedence
       
  1001             }
       
  1002         }
       
  1003         qreal answer = 0;
       
  1004 
       
  1005         if(calculateIndex < 0){
       
  1006             return false;
       
  1007         }
       
  1008 
       
  1009         switch (expressionValues[calculateIndex].mToken) {
       
  1010             case ExpressionValue::Minus:
       
  1011                 answer = expressionValues[calculateIndex-1].mValue -
       
  1012                          expressionValues[calculateIndex+1].mValue;
       
  1013                 break;
       
  1014             case ExpressionValue::Plus:
       
  1015                 answer = expressionValues[calculateIndex-1].mValue +
       
  1016                          expressionValues[calculateIndex+1].mValue;
       
  1017                 break;
       
  1018             case ExpressionValue::Star:
       
  1019                 answer = expressionValues[calculateIndex-1].mValue *
       
  1020                          expressionValues[calculateIndex+1].mValue;
       
  1021                 break;
       
  1022             case ExpressionValue::Slash:
       
  1023                 if (expressionValues[calculateIndex+1].mValue == 0) {
       
  1024                     expressionValues.clear();
       
  1025                     return false;
       
  1026                 }
       
  1027                 answer = expressionValues[calculateIndex-1].mValue /
       
  1028                          expressionValues[calculateIndex+1].mValue;
       
  1029                 break;
       
  1030             default:
       
  1031                 break;
       
  1032         }
       
  1033         if (expressionValues[calculateIndex].mToken == ExpressionValue::UnaryMinus) {
       
  1034             expressionValues[calculateIndex+1].mValue = 
       
  1035                 -expressionValues[calculateIndex+1].mValue;
       
  1036             expressionValues.removeAt(calculateIndex);
       
  1037         } else {
       
  1038             expressionValues[calculateIndex-1].mValue = answer;
       
  1039             expressionValues.removeAt(calculateIndex+1);
       
  1040             expressionValues.removeAt(calculateIndex);
       
  1041         }
       
  1042     }
       
  1043 
       
  1044     value = expressionValues[0].mValue;
       
  1045     expressionValues.clear();
       
  1046 
       
  1047     return true;    
       
  1048 }
       
  1049 
       
  1050 
       
  1051 bool ValueExtractor::extractCustomProperties( const QList<QString> &keys, QList<QVariant> &values )
       
  1052 {
   932 {
  1053     if ( keys.count() != values.count() ) {
   933     if ( keys.count() != values.count() ) {
  1054         return false;
   934         return false;
  1055     }
   935     }
  1056     for ( int i = 0; i < declarations.count(); i++ ) {
   936     for ( int i = 0; i < declarations.count(); i++ ) {
  1081         }
   961         }
  1082     }
   962     }
  1083     return true;
   963     return true;
  1084 }
   964 }
  1085 
   965 
  1086 bool ValueExtractor::extractLayout(QString &layoutName, QString &sectionName)
   966 bool ValueExtractor::extractLayout(QString &layoutName, QString &sectionName) const
  1087 {
   967 {
  1088     QString tempSectionName;
   968     QString tempSectionName;
  1089     bool hit = false;
   969     bool hit = false;
  1090     for (int i = 0; i < declarations.count(); ++i) {
   970     for (int i = 0; i < declarations.count(); ++i) {
  1091         const Declaration &decl = declarations.at(i);
   971         const Declaration &decl = declarations.at(i);
  1211     styleSheets.clear();
  1091     styleSheets.clear();
  1212     widgetSheets.clear();
  1092     widgetSheets.clear();
  1213 }
  1093 }
  1214 
  1094 
  1215 int StyleSelector::selectorMatches(
  1095 int StyleSelector::selectorMatches(
  1216     const Selector &selector, NodePtr node, bool nameCheckNeeded) const
  1096     const Selector &selector, 
  1217 {
  1097     NodePtr node, 
       
  1098     QSet<NodePtr> *dirtyNodes,
       
  1099     bool nameCheckNeeded) const
       
  1100 {
       
  1101     Q_ASSERT(dirtyNodes);
       
  1102 
  1218     if (selector.basicSelectors.isEmpty()) {
  1103     if (selector.basicSelectors.isEmpty()) {
  1219         return -1;
  1104         return -1;
  1220     }
  1105     }
  1221 
  1106 
  1222     if (selector.basicSelectors.first().relationToNext == BasicSelector::NoRelation) {
  1107     if (selector.basicSelectors.first().relationToNext == BasicSelector::NoRelation) {
  1223         if (selector.basicSelectors.count() != 1) {
  1108         if (selector.basicSelectors.count() != 1) {
  1224             return -1;
  1109             return -1;
  1225         }
  1110         }
  1226         return basicSelectorMatches(selector.basicSelectors.first(), node, nameCheckNeeded);
  1111         return basicSelectorMatches(selector.basicSelectors.first(), node, dirtyNodes, nameCheckNeeded);
  1227     }
  1112     }
  1228 
  1113 
  1229     if (selector.basicSelectors.count() <= 1) {
  1114     if (selector.basicSelectors.count() <= 1) {
  1230         return -1;
  1115         return -1;
  1231     }
  1116     }
  1235     int firstMatchLevel(-1);
  1120     int firstMatchLevel(-1);
  1236 
  1121 
  1237     BasicSelector sel = selector.basicSelectors.at(i);
  1122     BasicSelector sel = selector.basicSelectors.at(i);
  1238     bool firstLoop = true;
  1123     bool firstLoop = true;
  1239     do {
  1124     do {
  1240         matchLevel = basicSelectorMatches(sel, node, (nameCheckNeeded || !firstLoop));
  1125         matchLevel = basicSelectorMatches(sel, node, dirtyNodes, (nameCheckNeeded || !firstLoop));
  1241         if (firstLoop) {
  1126         if (firstLoop) {
  1242             firstMatchLevel = matchLevel;
  1127             firstMatchLevel = matchLevel;
  1243         }
  1128         }
  1244         if (matchLevel < 0) {
  1129         if (matchLevel < 0) {
  1245             if (sel.relationToNext == BasicSelector::MatchNextSelectorIfParent
  1130             if (sel.relationToNext == BasicSelector::MatchNextSelectorIfParent
  1290 }
  1175 }
  1291 
  1176 
  1292 const uint CLASS_HASH = qHash(QString("class"));
  1177 const uint CLASS_HASH = qHash(QString("class"));
  1293 
  1178 
  1294 int StyleSelector::basicSelectorMatches(
  1179 int StyleSelector::basicSelectorMatches(
  1295     const BasicSelector &sel, NodePtr node, bool nameCheckNeeded) const
  1180     const BasicSelector &sel, 
  1296 {
  1181     NodePtr node, 
       
  1182     QSet<NodePtr> *dirtyNodes,
       
  1183     bool nameCheckNeeded) const
       
  1184 {
       
  1185     Q_ASSERT(dirtyNodes);
       
  1186 
  1297     int matchLevel = 0;
  1187     int matchLevel = 0;
  1298     HbString elementName(HbMemoryManager::HeapMemory);
  1188     HbString elementName(HbMemoryManager::HeapMemory);
  1299 
  1189 
  1300     if (!sel.attributeSelectors.isEmpty()) {
  1190     if (!sel.attributeSelectors.isEmpty()) {
  1301         if (!hasAttributes(node))
  1191         if (!hasAttributes(node))
  1302             return -1;
  1192             return -1;
       
  1193 
       
  1194         dirtyNodes->insert(node);
  1303 
  1195 
  1304         for (int i = 0; i < sel.attributeSelectors.count(); ++i) {
  1196         for (int i = 0; i < sel.attributeSelectors.count(); ++i) {
  1305             const AttributeSelector &a = sel.attributeSelectors.at(i);
  1197             const AttributeSelector &a = sel.attributeSelectors.at(i);
  1306             if (a.nameHash == CLASS_HASH) {
  1198             if (a.nameHash == CLASS_HASH) {
  1307                 elementName = a.value;
  1199                 elementName = a.value;
  1342 {
  1234 {
  1343     return lhs.first < rhs.first;
  1235     return lhs.first < rhs.first;
  1344 }
  1236 }
  1345 
  1237 
  1346 void StyleSelector::matchRules(
  1238 void StyleSelector::matchRules(
  1347     NodePtr node, const HbVector<StyleRule> &rules, StyleSheetOrigin origin,
  1239     NodePtr node, 
  1348     int depth, QVector<WeightedRule> *weightedRules, bool nameCheckNeeded) const
  1240     const HbVector<StyleRule> &rules, 
  1349 {
  1241     StyleSheetOrigin origin,
       
  1242     int depth, 
       
  1243     QList<WeightedRule> *weightedRules, 
       
  1244     QSet<NodePtr> *dirtyNodes,
       
  1245     bool nameCheckNeeded) const
       
  1246 {
       
  1247     Q_ASSERT(weightedRules);
       
  1248     Q_ASSERT(dirtyNodes);
       
  1249 
  1350     for (int i = 0; i < rules.count(); ++i) {
  1250     for (int i = 0; i < rules.count(); ++i) {
  1351         const StyleRule &rule = rules.at(i);
  1251         const StyleRule &rule = rules.at(i);
  1352         for (int j = 0; j < rule.selectors.count(); ++j) {
  1252         int selectorCount = rule.selectors.count();
       
  1253         for (int j = 0; j < selectorCount; ++j) {
  1353             const Selector& selector = rule.selectors.at(j);
  1254             const Selector& selector = rule.selectors.at(j);
  1354             int matchLevel = selectorMatches(selector, node, nameCheckNeeded);
  1255             int matchLevel = selectorMatches(selector, node, dirtyNodes, nameCheckNeeded);
  1355             if ( matchLevel >= 0 ) {
  1256             if ( matchLevel >= 0 ) {
  1356                 WeightedRule wRule;
  1257                 int specificity = selector.specificity()
  1357                 wRule.first = selector.specificity()
       
  1358                     + 0x1000* matchLevel
  1258                     + 0x1000* matchLevel
  1359                     + (origin == StyleSheetOrigin_Inline)*0x10000*depth;
  1259                     + (origin == StyleSheetOrigin_Inline)*0x10000*depth;
  1360                 wRule.second.selectors.append(selector);
  1260                 if (selectorCount > 1) {
  1361                 wRule.second.declarations = rule.declarations;
  1261                     WeightedRule wRule;
       
  1262                     wRule.first = specificity;
       
  1263                     wRule.second.selectors.append(selector);
       
  1264                     wRule.second.declarations = rule.declarations;
  1362 #ifdef HB_CSS_INSPECTOR
  1265 #ifdef HB_CSS_INSPECTOR
  1363                 wRule.second.owningStyleSheet = rule.owningStyleSheet;
  1266                     wRule.second.owningStyleSheet = rule.owningStyleSheet;
  1364 #endif
  1267 #endif
  1365                 weightedRules->append(wRule);
  1268                     weightedRules->append(wRule);
       
  1269                 } else {
       
  1270                     WeightedRule wRule(specificity, rule);
       
  1271                     weightedRules->append(wRule);
       
  1272                 }
  1366             }
  1273             }
  1367         }
  1274         }
  1368     }
  1275     }
  1369 }
  1276 }
  1370 
  1277 
  1375 {
  1282 {
  1376     HbVector<StyleRule> rules;
  1283     HbVector<StyleRule> rules;
  1377     if (styleSheets.isEmpty())
  1284     if (styleSheets.isEmpty())
  1378         return rules;
  1285         return rules;
  1379 
  1286 
  1380     QVector<WeightedRule> weightedRules = weightedStyleRulesForNode(node, orientation);
  1287     QList<WeightedRule> weightedRules;
       
  1288     weightedStyleRulesForNode(node, orientation, &weightedRules);
  1381 
  1289 
  1382     qStableSort(weightedRules.begin(), weightedRules.end(), qcss_selectorStyleRuleLessThan);
  1290     qStableSort(weightedRules.begin(), weightedRules.end(), qcss_selectorStyleRuleLessThan);
  1383 
  1291 
  1384     for (int j = 0; j < weightedRules.count(); j++)
  1292     for (int j = 0; j < weightedRules.count(); j++)
  1385         rules += weightedRules.at(j).second;
  1293         rules += weightedRules.at(j).second;
  1386 
  1294 
  1387     return rules;
  1295     return rules;
  1388 }
  1296 }
  1389 
  1297 
       
  1298 // Generate inheritance list (reverse order)
       
  1299 static QList<uint> generateAncestorHashList(const StyleSelector::NodePtr &node)
       
  1300 {
       
  1301     QList<uint> ancestorList;
       
  1302     static QHash<uint, QList<uint> > ancestorsCache;
       
  1303     const QGraphicsWidget *widgetPtr = static_cast<const QGraphicsWidget*>(node.ptr);
       
  1304     if (widgetPtr) {
       
  1305         const QMetaObject *metaObject = widgetPtr->metaObject();
       
  1306         const char *className = metaObject->className();
       
  1307         uint classHash = qHash(className);
       
  1308         if (ancestorsCache.contains(classHash)) {
       
  1309             ancestorList = ancestorsCache[classHash];
       
  1310         } else {
       
  1311             do {
       
  1312                 className = metaObject->className();
       
  1313                 const QByteArray classNameBA = QByteArray::fromRawData(className, strlen(className));
       
  1314                 ancestorList << qHash(classNameBA);
       
  1315                 metaObject = metaObject->superClass();
       
  1316             } while (metaObject != 0);
       
  1317             ancestorList << GLOBAL_CSS_SELECTOR_HASH;
       
  1318             ancestorsCache[classHash] = ancestorList;
       
  1319         }
       
  1320     }
       
  1321     return ancestorList;
       
  1322 }
  1390 
  1323 
  1391 // Returns style rules and specificity values (unordered)
  1324 // Returns style rules and specificity values (unordered)
  1392 QVector<WeightedRule> StyleSelector::weightedStyleRulesForNode(
  1325 void StyleSelector::weightedStyleRulesForNode(
  1393     NodePtr node, const Qt::Orientation orientation) const
  1326     NodePtr node, 
       
  1327     const Qt::Orientation orientation,
       
  1328     QList<HbCss::WeightedRule> *matchedRules) const
  1394 {
  1329 {
  1395     initNode(node);
  1330     initNode(node);
  1396     QVector<WeightedRule> weightedRules; // (spec, rule) that will be sorted below
  1331     QSet<NodePtr> dirtyNodes;
  1397 
  1332     
  1398     // Generate inheritance list (reverse order)
  1333     QList<uint> ancestorClasses = generateAncestorHashList(node);
  1399     QStringList classNames;
       
  1400     QGraphicsWidget *widgetPtr = static_cast<QGraphicsWidget*> (node.ptr);
       
  1401     const QMetaObject *metaObject = widgetPtr->metaObject();
       
  1402     do {
       
  1403         const QString className = metaObject->className();
       
  1404         classNames << className;
       
  1405         metaObject = metaObject->superClass();
       
  1406     } while (metaObject != 0);
       
  1407     classNames << GLOBAL_CSS_SELECTOR;
       
  1408 
       
  1409     // Iterate backwards through list to append most-derived classes last
  1334     // Iterate backwards through list to append most-derived classes last
  1410     int count = classNames.count();
  1335     int count = ancestorClasses.count();
  1411     bool firstLoop = true;
  1336     bool firstLoop = true;
  1412     while(count--){
  1337     while(count--){
  1413         const QString &className = classNames.at(count);
  1338         uint classNameHash = ancestorClasses.at(count);
  1414         uint classNameHash = qHash(className);
       
  1415         QVectorIterator<StyleSheet*> iter(widgetSheets[classNameHash]);
  1339         QVectorIterator<StyleSheet*> iter(widgetSheets[classNameHash]);
  1416         while (iter.hasNext()) {
  1340         while (iter.hasNext()) {
  1417             const StyleSheet *styleSheet = iter.next();
  1341             const StyleSheet *styleSheet = iter.next();
  1418             if(styleSheet) {
  1342             if (!styleSheet)
  1419                 WidgetStyleRules* widgetStack = styleSheet->widgetStack(classNameHash);
  1343                 continue;
  1420                 if (widgetStack) {
  1344 
  1421                     matchRules(node, widgetStack->styleRules, styleSheet->origin, 
  1345             WidgetStyleRules* widgetStack = styleSheet->widgetStack(classNameHash);
  1422                                 styleSheet->depth, &weightedRules, false);
  1346             if (widgetStack) {
  1423                     // Append orientation-specific rules
  1347                 matchRules(node, widgetStack->styleRules, styleSheet->origin, 
  1424                     if (orientation == Qt::Vertical) {
  1348                             styleSheet->depth, matchedRules, &dirtyNodes, false);
  1425                         matchRules(node, widgetStack->portraitRules, styleSheet->origin, 
  1349                 // Append orientation-specific rules
  1426                                     styleSheet->depth, &weightedRules, false);
  1350                 if (orientation == Qt::Vertical) {
  1427                     }else if (orientation == Qt::Horizontal) {
  1351                     matchRules(node, widgetStack->portraitRules, styleSheet->origin, 
  1428                         matchRules(node, widgetStack->landscapeRules, styleSheet->origin, 
  1352                                 styleSheet->depth, matchedRules, &dirtyNodes, false);
  1429                                     styleSheet->depth, &weightedRules, false);
  1353                 }else if (orientation == Qt::Horizontal) {
       
  1354                     matchRules(node, widgetStack->landscapeRules, styleSheet->origin, 
       
  1355                                 styleSheet->depth, matchedRules, &dirtyNodes, false);
       
  1356                 }
       
  1357             }
       
  1358             if (firstLoop && !medium.isEmpty()) { // Media rules are only added to global widget stack
       
  1359                 int mediaRuleCount = styleSheet->mediaRules.count();
       
  1360                 for (int i = 0; i < mediaRuleCount; ++i) {
       
  1361                     if (styleSheet->mediaRules.at(i).media.contains(
       
  1362                             HbString(medium, HbMemoryManager::HeapMemory),
       
  1363                             Qt::CaseInsensitive)) {
       
  1364                         matchRules(node, styleSheet->mediaRules.at(i).styleRules, 
       
  1365                             styleSheet->origin, styleSheet->depth, matchedRules, &dirtyNodes);
  1430                     }
  1366                     }
  1431                 }
  1367                 }
  1432                 if (firstLoop && !medium.isEmpty()) { // Media rules are only added to global widget stack
  1368             }// End medium.isEmpty loop
  1433                     int mediaRuleCount = styleSheet->mediaRules.count();
       
  1434                     for (int i = 0; i < mediaRuleCount; ++i) {
       
  1435                         if (styleSheet->mediaRules.at(i).media.contains(
       
  1436                                 HbString(medium, HbMemoryManager::HeapMemory),
       
  1437                                 Qt::CaseInsensitive)) {
       
  1438                             matchRules(node, styleSheet->mediaRules.at(i).styleRules, 
       
  1439                                 styleSheet->origin, styleSheet->depth, &weightedRules);
       
  1440                         }
       
  1441                     }
       
  1442                 }// End medium.isEmpty loop
       
  1443             }// End styleSheet
       
  1444         }
  1369         }
  1445         firstLoop = false;
  1370         firstLoop = false;
  1446     }
  1371     }
  1447     cleanupNode(node);
  1372     QSet<NodePtr>::const_iterator dirtyNode;
  1448     return weightedRules;
  1373     for (dirtyNode = dirtyNodes.begin(); dirtyNode != dirtyNodes.end(); ++dirtyNode)
       
  1374         cleanupNode(*dirtyNode);
  1449 }
  1375 }
  1450 
  1376 
  1451 bool StyleSelector::hasOrientationSpecificStyleRules(NodePtr node) const
  1377 bool StyleSelector::hasOrientationSpecificStyleRules(NodePtr node) const
  1452 {
  1378 {
  1453     // Generate inheritance list (reverse order)
  1379     QList<uint> ancestorClasses = generateAncestorHashList(node);
  1454     QStringList classNames;
  1380     int count = ancestorClasses.count();
  1455     QGraphicsWidget *widgetPtr = static_cast<QGraphicsWidget*> (node.ptr);
       
  1456     const QMetaObject *metaObject = widgetPtr->metaObject();
       
  1457     do {
       
  1458         const QString className = metaObject->className();
       
  1459         classNames << className;
       
  1460         metaObject = metaObject->superClass();
       
  1461     } while (metaObject != 0);
       
  1462     classNames << GLOBAL_CSS_SELECTOR;
       
  1463 
       
  1464     int count = classNames.count();
       
  1465     while (count--) {
  1381     while (count--) {
  1466         const QString &className = classNames.at(count);
  1382         uint classNameHash = ancestorClasses.at(count);
  1467         uint classNameHash = qHash(className);
       
  1468         QVectorIterator<StyleSheet*> iter(widgetSheets[classNameHash]);
  1383         QVectorIterator<StyleSheet*> iter(widgetSheets[classNameHash]);
  1469         while (iter.hasNext()) {
  1384         while (iter.hasNext()) {
  1470             const StyleSheet *styleSheet = iter.next();
  1385             const StyleSheet *styleSheet = iter.next();
  1471             if (styleSheet) {
  1386             if (styleSheet) {
  1472                 WidgetStyleRules* widgetStack = styleSheet->widgetStack(classNameHash);
  1387                 WidgetStyleRules* widgetStack = styleSheet->widgetStack(classNameHash);
  1483 }
  1398 }
  1484 
  1399 
  1485 
  1400 
  1486 
  1401 
  1487 // Returns declarations and specificity values (unordered)
  1402 // Returns declarations and specificity values (unordered)
  1488 QVector<WeightedDeclaration> StyleSelector::weightedDeclarationsForNode(
  1403 void StyleSelector::weightedDeclarationsForNode(
  1489     NodePtr node, 
  1404     NodePtr node, 
  1490     const Qt::Orientation orientation,
  1405     const Qt::Orientation orientation,
       
  1406     QList<WeightedDeclaration> *matchedDecls,
  1491     const char *extraPseudo) const
  1407     const char *extraPseudo) const
  1492 {
  1408 {
  1493     QVector<WeightedDeclaration> decls;
  1409     QList<WeightedRule> rules;
  1494     QVector<WeightedRule> rules = weightedStyleRulesForNode(node, orientation);
  1410     weightedStyleRulesForNode(node, orientation, &rules);
  1495     for (int i = 0; i < rules.count(); i++) {
  1411     for (int i = 0; i < rules.count(); i++) {
  1496         const Selector& selector = rules.at(i).second.selectors.at(0);
  1412         const Selector& selector = rules.at(i).second.selectors.at(0);
  1497         const QString pseudoElement = selector.pseudoElement();
  1413         const QString &pseudoElement = selector.pseudoElement();
  1498 
  1414 
  1499         bool pseudoElementMatches = (extraPseudo && pseudoElement == QLatin1String(extraPseudo));
  1415         bool pseudoElementMatches = (extraPseudo && pseudoElement == QLatin1String(extraPseudo));
  1500 
  1416 
  1501         // skip rules with non-matching pseudo elements
  1417         // skip rules with non-matching pseudo elements
  1502         if (!pseudoElement.isEmpty() && !pseudoElementMatches)
  1418         if (!pseudoElement.isEmpty() && !pseudoElementMatches)
  1509             || pseudoClass == PseudoClass_Portrait;
  1425             || pseudoClass == PseudoClass_Portrait;
  1510 
  1426 
  1511         if (pseudoClassIsValid || pseudoElementMatches) {
  1427         if (pseudoClassIsValid || pseudoElementMatches) {
  1512             HbVector<Declaration> ruleDecls = rules.at(i).second.declarations;
  1428             HbVector<Declaration> ruleDecls = rules.at(i).second.declarations;
  1513             for (int j=0; j<ruleDecls.count(); j++) {
  1429             for (int j=0; j<ruleDecls.count(); j++) {
  1514                 WeightedDeclaration wDecl;
  1430                 WeightedDeclaration wDecl(rules.at(i).first, ruleDecls.at(j));
  1515                 wDecl.first = rules.at(i).first;
  1431                 matchedDecls->append(wDecl);
  1516                 wDecl.second = ruleDecls.at(j);
       
  1517                 decls.append(wDecl);
       
  1518             }
  1432             }
  1519         }
  1433         }
  1520     }
  1434     }
  1521     return decls;
       
  1522 }
  1435 }
  1523 
  1436 
  1524 // for qtexthtmlparser which requires just the declarations with Enabled state
  1437 // for qtexthtmlparser which requires just the declarations with Enabled state
  1525 // and without pseudo elements
  1438 // and without pseudo elements
  1526 HbVector<Declaration> StyleSelector::declarationsForNode(
  1439 HbVector<Declaration> StyleSelector::declarationsForNode(
  1530 {
  1443 {
  1531     HbVector<Declaration> decls;
  1444     HbVector<Declaration> decls;
  1532     if (styleSheets.isEmpty())
  1445     if (styleSheets.isEmpty())
  1533         return decls;
  1446         return decls;
  1534 
  1447 
  1535     QVector<WeightedDeclaration> weightedDecls = 
  1448     QList<WeightedDeclaration> weightedDecls;
  1536         weightedDeclarationsForNode(node, orientation, extraPseudo);
  1449     weightedDeclarationsForNode(node, orientation, &weightedDecls, extraPseudo);
  1537 
  1450 
  1538     qStableSort(weightedDecls.begin(), weightedDecls.end(), qcss_selectorDeclarationLessThan);
  1451     qStableSort(weightedDecls.begin(), weightedDecls.end(), qcss_selectorDeclarationLessThan);
  1539 
  1452 
  1540     for (int j = 0; j < weightedDecls.count(); j++)
  1453     for (int j = 0; j < weightedDecls.count(); j++)
  1541         decls += weightedDecls.at(j).second;
  1454         decls += weightedDecls.at(j).second;
  1758 #ifdef HB_CSS_INSPECTOR
  1671 #ifdef HB_CSS_INSPECTOR
  1759                 rule.owningStyleSheet = styleSheet;
  1672                 rule.owningStyleSheet = styleSheet;
  1760 #endif
  1673 #endif
  1761                 if(rule.selectors.count() > 1){
  1674                 if(rule.selectors.count() > 1){
  1762                     foreach(const HbCss::Selector &selector, rule.selectors){
  1675                     foreach(const HbCss::Selector &selector, rule.selectors){
  1763                         QString stackName = selector.basicSelectors.last().elementName;
  1676                         uint stackNameHash = GLOBAL_CSS_SELECTOR_HASH; // Default to global selector value
  1764                         if(stackName.length() < 1){
  1677                         const QString &stackName = selector.basicSelectors.last().elementName;
  1765                             stackName = GLOBAL_CSS_SELECTOR;
  1678                         if(stackName.length() > 0){
       
  1679                             stackNameHash = qHash(stackName.toLatin1());
  1766                         }
  1680                         }
  1767                         StyleRule newRule(rule.memoryType);
  1681                         StyleRule newRule(rule.memoryType);
  1768                         newRule.declarations = rule.declarations;
  1682                         newRule.declarations = rule.declarations;
  1769                         newRule.selectors.append(selector);
  1683                         newRule.selectors.append(selector);
  1770 #ifdef HB_CSS_INSPECTOR
  1684 #ifdef HB_CSS_INSPECTOR
  1771                         newRule.owningStyleSheet = styleSheet;
  1685                         newRule.owningStyleSheet = styleSheet;
  1772 #endif
  1686 #endif
  1773                         addRuleToWidgetStack(styleSheet, stackName, newRule);
  1687                         addRuleToWidgetStack(styleSheet, stackNameHash, newRule);
  1774                     }
  1688                     }
  1775                 } else {
  1689                 } else {
  1776                     QString stackName = rule.selectors.at(0).basicSelectors.last().elementName;
  1690                     uint stackNameHash = GLOBAL_CSS_SELECTOR_HASH; // Default to global selector value
  1777                     if(stackName.length() < 1){
  1691                     const QString &stackName = rule.selectors.at(0).basicSelectors.last().elementName;
  1778                         stackName = GLOBAL_CSS_SELECTOR;
  1692                     if(stackName.length() > 0){
       
  1693                         stackNameHash = qHash(stackName.toLatin1());
  1779                     }
  1694                     }
  1780                     addRuleToWidgetStack(styleSheet, stackName, rule);
  1695                     addRuleToWidgetStack(styleSheet, stackNameHash, rule);
  1781                 }
  1696                 }
  1782             } else if (test(ATKEYWORD_SYM)) {
  1697             } else if (test(ATKEYWORD_SYM)) {
  1783                 if (!until(RBRACE)) return false;
  1698                 if (!until(RBRACE)) return false;
  1784             } else if (hasNext()) {
  1699             } else if (hasNext()) {
  1785                 return false;
  1700                 return false;
  1796 
  1711 
  1797     errorCode = NoError;
  1712     errorCode = NoError;
  1798     return true;
  1713     return true;
  1799 }
  1714 }
  1800 
  1715 
  1801 void Parser::addRuleToWidgetStack(StyleSheet *sheet, const QString &stackName, StyleRule &rule)
  1716 void Parser::addRuleToWidgetStack(StyleSheet *sheet, uint stackNameHash, StyleRule &rule)
  1802 {
  1717 {
  1803     uint stackNameHash = qHash(stackName);
       
  1804     WidgetStyleRules* widgetStack = sheet->widgetStack(stackNameHash);
  1718     WidgetStyleRules* widgetStack = sheet->widgetStack(stackNameHash);
  1805 
  1719 
  1806     if (!widgetStack) {
  1720     if (!widgetStack) {
  1807 #ifdef CSSPARSER_DEBUG
       
  1808         qDebug() << "Creating stack for classname" << stackName;
       
  1809 #endif
       
  1810         HbCss::WidgetStyleRules rules(stackNameHash, sheet->memoryType);
  1721         HbCss::WidgetStyleRules rules(stackNameHash, sheet->memoryType);
  1811         widgetStack = sheet->addWidgetStack(rules);
  1722         widgetStack = sheet->addWidgetStack(rules);
  1812     }
  1723     }
  1813 
  1724 
  1814     // Add rule into correct (portrait/landscape/any) list
  1725     // Add rule into correct (portrait/landscape/any) list
  2380                     removeOptionalQuotes(&args);
  2291                     removeOptionalQuotes(&args);
  2381                     if (QFileInfo(args).isRelative() && !sourcePath.isEmpty()) {
  2292                     if (QFileInfo(args).isRelative() && !sourcePath.isEmpty()) {
  2382                         args.prepend(sourcePath);
  2293                         args.prepend(sourcePath);
  2383                     }
  2294                     }
  2384                     value->variant = args;
  2295                     value->variant = args;
  2385                 }
  2296                 } else if (name == QLatin1String("var") || name == QLatin1String("-var")) {
  2386                 //changes for variable support
  2297                     value->type = name.startsWith(QLatin1Char('-'))
  2387                 else if (name == QLatin1String("var")) {
  2298                         ? Value::VariableNegative
  2388                     value->type = Value::Variable;
  2299                         : Value::Variable;
  2389                     value->variant = (int)hbHash( args );
  2300                     value->variant = (int)hbHash( args );
  2390                 } else if (name == QLatin1String("-var")) {                    
  2301 #ifdef HB_CSS_INSPECTOR
  2391                     value->type = Value::VariableNegative;
  2302                     value->original = args;
  2392                     value->variant = (int)hbHash( args );
  2303 #endif
  2393                 } //change end
  2304                 } else if (name == QLatin1String("expr") || name == QLatin1String("-expr")) {
  2394                 //changes for expression support
  2305                     value->type = name.startsWith(QLatin1Char('-'))
  2395                 else if (name == QLatin1String("expr")) {
  2306                         ? Value::ExpressionNegative
  2396                     value->type = Value::Expression;
  2307                         : Value::Expression;
  2397                     value->variant = args;
  2308                     QList<int> tokens;
  2398                 } else if (name == QLatin1String("-expr")) {
  2309                     if (!HbExpressionParser::parse(args, tokens)) {
  2399                     value->type = Value::ExpressionNegative;
  2310                         return false;
  2400                     value->variant = args;
  2311                     }
  2401                 } //change end
  2312                     value->variant = tokens;
  2402                 else {
  2313 #ifdef HB_CSS_INSPECTOR
       
  2314                     value->original = args;
       
  2315 #endif
       
  2316                 } else {
  2403                     value->type = Value::Function;
  2317                     value->type = Value::Function;
  2404                     value->variant = QStringList() << name << args;
  2318                     value->variant = QStringList() << name << args;
  2405                 }
  2319                 }
  2406             } else {
  2320             } else {
  2407                 return recordError();
  2321                 return recordError();