--Boundary-00=_xPK2F89kOIQY3mD Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit Content-Disposition: inline I'd like to add two extra options to kconfig_compiler for enum type items. The aim of the changes is to make it more straightforward for application code to use enums rather than int values when handling enum config options. Using enums is more type-safe, so it should encourage safer coding. Note that the proposed changes are backwards compatible - existing .kcfg and .kcfgc files and their generated code will be unchanged. 1) the option to use enum types instead of int for the parameter of the manipulator and the return value of the accessor. This would be specified by the use of a new option in the .kcfgc file, "UseEnumTypes=true". This option would be ignored unless GlobalEnums=false is also specified. The method signatures would become void setFoo( EnumFoo::type v ); EnumFoo::type foo(); This option removes the need for application code to cast from int to enum. 2) the option to specify the name of the enum. The reason for this is that generated enum type names can currently be rather long and cumbersome, and the new option would allow shorter enum names to be used, and possibly for the names to be more understandable in the context of the application code. Again, this option would be ignored unless GlobalEnums=false is specified. The option is specified using an optional parameter to the element: When this option is used, the generated enum class would be "Bar". A typedef will also be generated: typedef Bar::type BarEnum; When used together with UseEnumTypes=true, the method signatures would become: void setFoo( BarEnum v ); BarEnum foo(); I attach a patch - is it okay to apply? If so, I'll also amend the KConfig_XT tutorial on developernew.kde.org for KDE 4. -- David Jarvie. KAlarm author and maintainer. http://www.astrojar.org.uk/linux/kalarm.html --Boundary-00=_xPK2F89kOIQY3mD Content-Type: text/x-diff; charset="us-ascii"; name="diff" Content-Transfer-Encoding: 7bit Content-Disposition: attachment; filename="diff" Index: kcfg.xsd =================================================================== --- kcfg.xsd (revision 633699) +++ kcfg.xsd (working copy) @@ -94,6 +94,8 @@ + + Index: kconfig_compiler.cpp =================================================================== --- kconfig_compiler.cpp (revision 633699) +++ kconfig_compiler.cpp (working copy) @@ -95,6 +95,7 @@ } bool globalEnums; +bool useEnumTypes; bool itemAccessors; bool dpointer; QStringList allNames; @@ -124,11 +125,16 @@ QString label; QString whatsThis; }; + struct Choices + { + QString name; + QList choices; + }; CfgEntry( const QString &group, const QString &type, const QString &key, const QString &name, const QString &label, const QString &whatsThis, const QString &code, - const QString &defaultValue, const QList &choices, const QList signalList, + const QString &defaultValue, const Choices &choices, const QList signalList, bool hidden ) : mGroup( group ), mType( type ), mKey( key ), mName( name ), mLabel( label ), mWhatsThis( whatsThis ), mCode( code ), @@ -176,8 +182,8 @@ void setParamType( const QString &d ) { mParamType = d; } QString paramType() const { return mParamType; } - void setChoices( const QList &d ) { mChoices = d; } - QList choices() const { return mChoices; } + void setChoices( const QList &d, const QString &n ) { mChoices.choices = d; mChoices.name = n; } + Choices choices() const { return mChoices; } void setParamValues( const QStringList &d ) { mParamValues = d; } QStringList paramValues() const { return mParamValues; } @@ -230,7 +236,7 @@ QString mParam; QString mParamName; QString mParamType; - QList mChoices; + Choices mChoices; QList mSignalList; QStringList mParamValues; QStringList mParamDefaultValues; @@ -275,13 +281,44 @@ return result; } -static QString enumName(const QString &n) +static QString enumPrefix(const QString &n) { QString result = "Enum"+n; result[4] = result[4].toUpper(); return result; } +static QString enumName(const QString &n, const CfgEntry::Choices &c) +{ + QString result; + if ( c.name.isEmpty() ) + { + result = "Enum" + n; + result[4] = result[4].toUpper(); + } + else + result = c.name; + return result; +} + +static QString enumName(const CfgEntry *e) +{ + return enumName(e->name(), e->choices()); +} + +static QString enumType(const CfgEntry *e) +{ + QString result; + if ( e->choices().name.isEmpty() ) + { + result = "Enum" + e->name() + "::type"; + result[4] = result[4].toUpper(); + } + else + result = e->choices().name + "Enum"; + return result; +} + static QString setFunction(const QString &n, const QString &className = QString()) { QString result = "set"+n; @@ -363,7 +400,7 @@ static void preProcessDefault( QString &defaultValue, const QString &name, const QString &type, - const QList &choices, + const CfgEntry::Choices &choices, QString &code ) { if ( type == "String" && !defaultValue.isEmpty() ) { @@ -400,9 +437,9 @@ } else if ( type == "Enum" ) { if ( !globalEnums ) { QList::ConstIterator it; - for( it = choices.begin(); it != choices.end(); ++it ) { + for( it = choices.choices.begin(); it != choices.choices.end(); ++it ) { if ( (*it).name == defaultValue ) { - defaultValue.prepend( enumName(name) + "::"); + defaultValue.prepend( enumName(name, choices) + "::"); break; } } @@ -442,7 +479,7 @@ QString param; QString paramName; QString paramType; - QList choices; + CfgEntry::Choices choices; QList signalList; QStringList paramValues; QStringList paramDefaultValues; @@ -519,6 +556,7 @@ } } else if ( tag == "choices" ) { + choices.name = e.attribute( "enum" ); for( QDomElement e2 = e.firstChildElement(); !e2.isNull(); e2 = e2.nextSiblingElement() ) { if ( e2.tagName() == "choice" ) { CfgEntry::Choice choice; @@ -530,7 +568,7 @@ if ( e3.tagName() == "label" ) choice.label = e3.text(); if ( e3.tagName() == "whatsthis" ) choice.whatsThis = e3.text(); } - choices.append( choice ); + choices.choices.append( choice ); } } } @@ -917,8 +955,13 @@ QString n = e->name(); QString t = e->type(); - out << "return " << This << varPath(n); + out << "return "; + if (useEnumTypes && t == "Enum") + out << "static_cast<" << enumType(e) << ">("; + out << This << varPath(n); if (!e->param().isEmpty()) out << "[i]"; + if (useEnumTypes && t == "Enum") + out << ")"; out << ";" << endl; return result; @@ -964,9 +1007,9 @@ out << "QLatin1String( "; if (globalEnums) - out << enumName(e->param()) << "ToString[i]"; + out << enumPrefix(e->param()) << "ToString[i]"; else - out << enumName(e->param()) << "::enumToString[i]"; + out << enumPrefix(e->param()) << "::enumToString[i]"; out << " )"; } @@ -1076,6 +1119,7 @@ bool setUserTexts = codegenConfig.value("SetUserTexts", false).toBool(); globalEnums = codegenConfig.value("GlobalEnums", false).toBool(); + useEnumTypes = !globalEnums && codegenConfig.value("UseEnumTypes", false).toBool(); dpointer = (memberVariables == "dpointer"); @@ -1262,7 +1306,8 @@ // enums QList::ConstIterator itEntry; for( itEntry = entries.begin(); itEntry != entries.end(); ++itEntry ) { - QList choices = (*itEntry)->choices(); + QString choicesName = (*itEntry)->choices().name; + QList choices = (*itEntry)->choices().choices; if ( !choices.isEmpty() ) { QStringList values; QList::ConstIterator itChoice; @@ -1272,11 +1317,13 @@ if ( globalEnums ) { h << " enum { " << values.join( ", " ) << " };" << endl; } else { - h << " class " << enumName( (*itEntry)->name() ) << endl; + h << " class " << enumName( *itEntry ) << endl; h << " {" << endl; h << " public:" << endl; h << " enum type { " << values.join( ", " ) << ", COUNT };" << endl; h << " };" << endl; + if ( !(*itEntry)->choices().name.isEmpty() ) + h << " typedef " << enumName( *itEntry ) << "::type " << enumType( *itEntry ) << ";" << endl; } } QStringList values = (*itEntry)->paramValues(); @@ -1286,17 +1333,19 @@ // make the following string table an index-based string search! // ### h << " enum { " << values.join( ", " ) << " };" << endl; - h << " static const char* const " << enumName( (*itEntry)->param() ) << "ToString[];" << endl; - cppPreamble += "const char* const " + className + "::" + enumName( (*itEntry)->param() ) + + h << " static const char* const " << enumPrefix( (*itEntry)->param() ) << "ToString[];" << endl; + cppPreamble += "const char* const " + className + "::" + enumPrefix( (*itEntry)->param() ) + "ToString[] = { \"" + values.join( "\", \"" ) + "\" };\n"; } else { - h << " class " << enumName( (*itEntry)->param() ) << endl; + h << " class " << enumName( *itEntry ) << endl; h << " {" << endl; h << " public:" << endl; h << " enum type { " << values.join( ", " ) << ", COUNT };" << endl; h << " static const char* const enumToString[];" << endl; h << " };" << endl; - cppPreamble += "const char* const " + className + "::" + enumName( (*itEntry)->param() ) + + if ( !(*itEntry)->choices().name.isEmpty() ) + h << " typedef " << enumName( *itEntry ) << "::type " << enumType( *itEntry ) << ";" << endl; + cppPreamble += "const char* const " + className + "::" + enumPrefix( (*itEntry)->param() ) + "::enumToString[] = { \"" + values.join( "\", \"" ) + "\" };\n"; } } @@ -1358,7 +1407,11 @@ h << " void " << setFunction(n) << "( "; if (!(*itEntry)->param().isEmpty()) h << cppType((*itEntry)->paramType()) << " i, "; - h << param( t ) << " v )"; + if (useEnumTypes && t == "Enum") + h << enumType(*itEntry); + else + h << param( t ); + h << " v )"; // function body inline only if not using dpointer // for BC mode if ( !dpointer ) @@ -1379,7 +1432,12 @@ h << " */" << endl; if (staticAccessors) h << " static" << endl; - h << " " << cppType(t) << " " << getFunction(n) << "("; + h << " "; + if (useEnumTypes && t == "Enum") + h << enumType(*itEntry); + else + h << cppType(t); + h << " " << getFunction(n) << "("; if (!(*itEntry)->param().isEmpty()) h << " " << cppType((*itEntry)->paramType()) <<" i "; h << ")" << Const; @@ -1689,7 +1747,7 @@ if ( (*itEntry)->type() == "Enum" ) { cpp << " QList values" << (*itEntry)->name() << ";" << endl; - QList choices = (*itEntry)->choices(); + QList choices = (*itEntry)->choices().choices; QList::ConstIterator it; for( it = choices.begin(); it != choices.end(); ++it ) { cpp << " {" << endl; @@ -1780,7 +1838,11 @@ cpp << "void " << setFunction(n, className) << "( "; if ( !(*itEntry)->param().isEmpty() ) cpp << cppType( (*itEntry)->paramType() ) << " i, "; - cpp << param( t ) << " v )" << endl; + if (useEnumTypes && t == "Enum") + cpp << enumType(*itEntry); + else + cpp << param( t ); + cpp << " v )"; // function body inline only if not using dpointer // for BC mode cpp << "{" << endl; @@ -1789,7 +1851,11 @@ } // Accessor - cpp << cppType(t) << " " << getFunction(n, className) << "("; + if (useEnumTypes && t == "Enum") + cpp << enumType(*itEntry); + else + cpp << cppType(t); + cpp << " " << getFunction(n, className) << "("; if ( !(*itEntry)->param().isEmpty() ) cpp << " " << cppType( (*itEntry)->paramType() ) <<" i "; cpp << ")" << Const << endl; --Boundary-00=_xPK2F89kOIQY3mD--