diff options
author | Friedemann Kleint <Friedemann.Kleint@nokia.com> | 2010-07-08 11:46:05 +0200 |
---|---|---|
committer | Friedemann Kleint <Friedemann.Kleint@nokia.com> | 2010-07-08 11:46:11 +0200 |
commit | 280541aec9f438a42e1321f536445a29e71417f5 (patch) | |
tree | c53b79fb8dd66b91968d2876e2735bea6161cc38 /src/plugins/projectexplorer | |
parent | cdf7dbeada9008aceeb83fe070430bed66c625f0 (diff) | |
download | qt-creator-280541aec9f438a42e1321f536445a29e71417f5.tar.gz |
Template-CustomWizard: Make QComboBox parameters more flexible.
Separate value and display text for the entries, use
in ListModel example.
Rubber-stamped-by: aportale <alessandro.portale@trolltech.com>
Diffstat (limited to 'src/plugins/projectexplorer')
4 files changed, 193 insertions, 40 deletions
diff --git a/src/plugins/projectexplorer/customwizard/customwizardpage.cpp b/src/plugins/projectexplorer/customwizard/customwizardpage.cpp index 3be2644667..74e595d25c 100644 --- a/src/plugins/projectexplorer/customwizard/customwizardpage.cpp +++ b/src/plugins/projectexplorer/customwizard/customwizardpage.cpp @@ -54,16 +54,43 @@ TextFieldComboBox::TextFieldComboBox(QWidget *parent) : QComboBox(parent) { setEditable(false); - connect(this, SIGNAL(currentIndexChanged(QString)), this, SIGNAL(textChanged(QString))); + connect(this, SIGNAL(currentIndexChanged(int)), + this, SLOT(slotCurrentIndexChanged(int))); +} + +QString TextFieldComboBox::text() const +{ + return valueAt(currentIndex()); } void TextFieldComboBox::setText(const QString &s) { - const int index = findText(s); + const int index = findData(QVariant(s), Qt::UserRole); if (index != -1 && index != currentIndex()) setCurrentIndex(index); } +void TextFieldComboBox::slotCurrentIndexChanged(int i) +{ + emit text4Changed(valueAt(i)); +} + +void TextFieldComboBox::setItems(const QStringList &displayTexts, + const QStringList &values) +{ + QTC_ASSERT(displayTexts.size() == values.size(), return) + clear(); + addItems(displayTexts); + const int count = values.count(); + for (int i = 0; i < count; i++) + setItemData(i, QVariant(values.at(i)), Qt::UserRole); +} + +QString TextFieldComboBox::valueAt(int i) const +{ + return i >= 0 && i < count() ? itemData(i, Qt::UserRole).toString() : QString(); +} + // -------------- TextCheckBox TextFieldCheckBox::TextFieldCheckBox(const QString &text, QWidget *parent) : QCheckBox(text, parent), @@ -154,15 +181,45 @@ void CustomWizardFieldPage::addField(const CustomWizardField &field)\ } } +// Return the list of values and display texts for combo +static void comboChoices(const CustomWizardField::ControlAttributeMap &controlAttributes, + QStringList *values, QStringList *displayTexts) +{ + typedef CustomWizardField::ControlAttributeMap::ConstIterator AttribMapConstIt; + + values->clear(); + displayTexts->clear(); + // Pre 2.2 Legacy: "combochoices" attribute with a comma-separated list, for + // display == value. + const AttribMapConstIt attribConstEnd = controlAttributes.constEnd(); + const AttribMapConstIt choicesIt = controlAttributes.constFind(QLatin1String("combochoices")); + if (choicesIt != attribConstEnd) { + const QString &choices = choicesIt.value(); + if (!choices.isEmpty()) + *values = *displayTexts = choices.split(QLatin1Char(',')); + return; + } + // From 2.2 on: Separate lists of value and text. Add all values found. + for (int i = 0; ; i++) { + const QString valueKey = CustomWizardField::comboEntryValueKey(i); + const AttribMapConstIt valueIt = controlAttributes.constFind(valueKey); + if (valueIt == attribConstEnd) + break; + values->push_back(valueIt.value()); + const QString textKey = CustomWizardField::comboEntryTextKey(i); + displayTexts->push_back(controlAttributes.value(textKey)); + } +} + QWidget *CustomWizardFieldPage::registerComboBox(const QString &fieldName, const CustomWizardField &field) { TextFieldComboBox *combo = new TextFieldComboBox; do { // Set up items and current index - const QString choices = field.controlAttributes.value(QLatin1String("combochoices")); - if (choices.isEmpty()) - break; - combo->addItems(choices.split(QLatin1Char(','))); + QStringList values; + QStringList displayTexts; + comboChoices(field.controlAttributes, &values, &displayTexts); + combo->setItems(displayTexts, values); bool ok; const QString currentIndexS = field.controlAttributes.value(QLatin1String("defaultindex")); if (currentIndexS.isEmpty()) @@ -201,6 +258,8 @@ QWidget *CustomWizardFieldPage::registerCheckBox(const QString &fieldName, typedef CustomWizardField::ControlAttributeMap::const_iterator AttributeMapConstIt; TextFieldCheckBox *checkBox = new TextFieldCheckBox(fieldDescription); + const bool defaultValue = field.controlAttributes.value(QLatin1String("defaultvalue")) == QLatin1String("true"); + checkBox->setChecked(defaultValue); const AttributeMapConstIt trueTextIt = field.controlAttributes.constFind(QLatin1String("truevalue")); if (trueTextIt != field.controlAttributes.constEnd()) // Also set empty texts checkBox->setTrueText(trueTextIt.value()); diff --git a/src/plugins/projectexplorer/customwizard/customwizardpage.h b/src/plugins/projectexplorer/customwizard/customwizardpage.h index ccf27ae198..741ee99989 100644 --- a/src/plugins/projectexplorer/customwizard/customwizardpage.h +++ b/src/plugins/projectexplorer/customwizard/customwizardpage.h @@ -54,17 +54,27 @@ struct CustomWizardContext; // A non-editable combo for text editing purposes that plays // with QWizard::registerField (providing a settable 'text' property). +// Allows for a separation of values to be used for wizard fields replacement +// and display texts. class TextFieldComboBox : public QComboBox { Q_PROPERTY(QString text READ text WRITE setText) Q_OBJECT public: explicit TextFieldComboBox(QWidget *parent = 0); - QString text() const { return currentText(); } + QString text() const; void setText(const QString &s); + void setItems(const QStringList &displayTexts, const QStringList &values); + signals: void text4Changed(const QString &); // Do not conflict with Qt 3 compat signal. + +private slots: + void slotCurrentIndexChanged(int); + +private: + inline QString valueAt(int) const; }; // A Checkbox that plays with QWizard::registerField (providing a settable diff --git a/src/plugins/projectexplorer/customwizard/customwizardparameters.cpp b/src/plugins/projectexplorer/customwizard/customwizardparameters.cpp index 2f3d902c88..487c3aef37 100644 --- a/src/plugins/projectexplorer/customwizard/customwizardparameters.cpp +++ b/src/plugins/projectexplorer/customwizard/customwizardparameters.cpp @@ -58,6 +58,9 @@ static const char displayCategoryElementC[] = "displaycategory"; static const char fieldPageTitleElementC[] = "fieldpagetitle"; static const char fieldsElementC[] = "fields"; static const char fieldElementC[] = "field"; +static const char comboEntriesElementC[] = "comboentries"; +static const char comboEntryElementC[] = "comboentry"; +static const char comboEntryTextElementC[] = "comboentrytext"; static const char fieldDescriptionElementC[] = "fielddescription"; static const char fieldNameAttributeC[] = "name"; @@ -77,6 +80,11 @@ enum ParseState { ParseWithinWizard, ParseWithinFields, ParseWithinField, + ParseWithinFieldDescription, + ParseWithinFieldControl, + ParseWithinComboEntries, + ParseWithinComboEntry, + ParseWithinComboEntryText, ParseWithinFiles, ParseWithinFile, ParseError @@ -98,6 +106,17 @@ void CustomWizardField::clear() controlAttributes.clear(); } +// Attribute map keys for combo entries +QString CustomWizardField::comboEntryValueKey(int i) +{ + return QLatin1String("comboValue") + QString::number(i); +} + +QString CustomWizardField::comboEntryTextKey(int i) +{ + return QLatin1String("comboText") + QString::number(i); +} + CustomWizardFile::CustomWizardFile() : openEditor(false), openProject(false) { @@ -148,7 +167,7 @@ static inline bool skipOverElementText(QXmlStreamReader &reader) // Assign the element text to the string passed on if the language matches, // that is, the element has no language attribute or there is an exact match. // If there is no match, skip over the element text. -static inline void assignLanguageElementText(QXmlStreamReader &reader, +static inline bool assignLanguageElementText(QXmlStreamReader &reader, const QString &desiredLanguage, QString *target) { @@ -156,18 +175,21 @@ static inline void assignLanguageElementText(QXmlStreamReader &reader, if (elementLanguage.isEmpty()) { // Try to find a translation for our built-in Wizards *target = QCoreApplication::translate("ProjectExplorer::CustomWizard", reader.readElementText().toLatin1().constData()); - } else if (elementLanguage == desiredLanguage) { + return true; + } + if (elementLanguage == desiredLanguage) { *target = reader.readElementText(); - } else { - // Language mismatch: forward to end element. - skipOverElementText(reader); + return true; } + // Language mismatch: forward to end element. + skipOverElementText(reader); + return false; } // Copy&paste from above to call a setter of BaseFileParameters. // Implementation of a sophisticated mem_fun pattern is left // as an exercise to the reader. -static inline void assignLanguageElementText(QXmlStreamReader &reader, +static inline bool assignLanguageElementText(QXmlStreamReader &reader, const QString &desiredLanguage, Core::BaseFileWizardParameters *bp, void (Core::BaseFileWizardParameters::*setter)(const QString &)) @@ -177,12 +199,15 @@ static inline void assignLanguageElementText(QXmlStreamReader &reader, // Try to find a translation for our built-in Wizards const QString translated = QCoreApplication::translate("ProjectExplorer::CustomWizard", reader.readElementText().toLatin1().constData()); (bp->*setter)(translated); - } else if (elementLanguage == desiredLanguage) { + return true; + } + if (elementLanguage == desiredLanguage) { (bp->*setter)(reader.readElementText()); - } else { - // Language mismatch: forward to end element. - skipOverElementText(reader); + return true; } + // Language mismatch: forward to end element. + skipOverElementText(reader); + return false; } // Read level sub-elements of "wizard" @@ -226,24 +251,12 @@ static bool parseCustomProjectElement(QXmlStreamReader &reader, return false; } -// Read sub-elements of "fields" -static bool parseFieldElement(QXmlStreamReader &reader, - const QString &language, - CustomWizardField *m) +static inline QMap<QString, QString> attributesToStringMap(const QXmlStreamAttributes &attributes) { - const QStringRef elementName = reader.name(); - if (elementName == QLatin1String(fieldDescriptionElementC)) { - assignLanguageElementText(reader, language, &m->description); - return true; - } - // Copy widget control attributes - if (elementName == QLatin1String(fieldControlElementC)) { - foreach(const QXmlStreamAttribute &attribute, reader.attributes()) - m->controlAttributes.insert(attribute.name().toString(), attribute.value().toString()); - skipOverElementText(reader); - return true; - } - return false; + QMap<QString, QString> rc; + foreach(const QXmlStreamAttribute &attribute, attributes) + rc.insert(attribute.name().toString(), attribute.value().toString()); + return rc; } // Switch parser state depending on opening element name. @@ -264,11 +277,30 @@ static ParseState nextOpeningState(ParseState in, const QStringRef &name) if (name == QLatin1String(fieldElementC)) return ParseWithinField; break; + case ParseWithinField: + if (name == QLatin1String(fieldDescriptionElementC)) + return ParseWithinFieldDescription; + if (name == QLatin1String(fieldControlElementC)) + return ParseWithinFieldControl; + break; + case ParseWithinFieldControl: + if (name == QLatin1String(comboEntriesElementC)) + return ParseWithinComboEntries; + break; + case ParseWithinComboEntries: + if (name == QLatin1String(comboEntryElementC)) + return ParseWithinComboEntry; + break; + case ParseWithinComboEntry: + if (name == QLatin1String(comboEntryTextElementC)) + return ParseWithinComboEntryText; + break; case ParseWithinFiles: if (name == QLatin1String(fileElementC)) return ParseWithinFile; break; - case ParseWithinField: + case ParseWithinFieldDescription: // No subelements + case ParseWithinComboEntryText: case ParseWithinFile: case ParseError: break; @@ -302,6 +334,26 @@ static ParseState nextClosingState(ParseState in, const QStringRef &name) if (name == QLatin1String(fileElementC)) return ParseWithinFiles; break; + case ParseWithinFieldDescription: + if (name == QLatin1String(fieldDescriptionElementC)) + return ParseWithinField; + break; + case ParseWithinFieldControl: + if (name == QLatin1String(fieldControlElementC)) + return ParseWithinField; + break; + case ParseWithinComboEntries: + if (name == QLatin1String(comboEntriesElementC)) + return ParseWithinFieldControl; + break; + case ParseWithinComboEntry: + if (name == QLatin1String(comboEntryElementC)) + return ParseWithinComboEntries; + break; + case ParseWithinComboEntryText: + if (name == QLatin1String(comboEntryTextElementC)) + return ParseWithinComboEntry; + break; case ParseError: break; } @@ -373,6 +425,7 @@ bool CustomWizardParameters::parse(QIODevice &device, Core::BaseFileWizardParameters *bp, QString *errorMessage) { + int comboEntryCount = 0; QXmlStreamReader reader(&device); QXmlStreamReader::TokenType token = QXmlStreamReader::EndDocument; ParseState state = ParseBeginning; @@ -392,8 +445,6 @@ bool CustomWizardParameters::parse(QIODevice &device, // Read out subelements applicable to current state if (state == ParseWithinWizard && parseCustomProjectElement(reader, configFileFullPath, language, this, bp)) break; - if (state == ParseWithinField && parseFieldElement(reader, language, &field)) - break; // switch to next state state = nextOpeningState(state, reader.name()); // Read attributes post state-switching @@ -413,6 +464,29 @@ bool CustomWizardParameters::parse(QIODevice &device, field.name = attributeValue(reader, fieldNameAttributeC); field.mandatory = booleanAttributeValue(reader, fieldMandatoryAttributeC); break; + case ParseWithinFieldDescription: + assignLanguageElementText(reader, language, &field.description); + state = ParseWithinField; // The above reads away the end tag, set state. + break; + case ParseWithinFieldControl: // Copy widget control attributes + field.controlAttributes = attributesToStringMap(reader.attributes()); + break; + case ParseWithinComboEntries: + break; + case ParseWithinComboEntry: // Combo entry with 'value' attribute + field.controlAttributes.insert(CustomWizardField::comboEntryValueKey(comboEntryCount), + attributeValue(reader, "value")); + break; + case ParseWithinComboEntryText: { + + // This reads away the end tag, set state here. + QString text; + if (assignLanguageElementText(reader, language, &text)) + field.controlAttributes.insert(CustomWizardField::comboEntryTextKey(comboEntryCount), + text); + state = ParseWithinComboEntry; + } + break; case ParseWithinFile: { // file attribute CustomWizardFile file; file.source = attributeValue(reader, fileNameSourceAttributeC); @@ -435,14 +509,20 @@ bool CustomWizardParameters::parse(QIODevice &device, break; case QXmlStreamReader::EndElement: state = nextClosingState(state, reader.name()); - if (state == ParseError) { + switch (state) { + case ParseError: *errorMessage = msgError(reader, configFileFullPath, QString::fromLatin1("Unexpected end element %1").arg(reader.name().toString())); return false; - } - if (state == ParseWithinFields) { // Leaving a field element + case ParseWithinFields: // Leaving a field element fields.push_back(field); field.clear(); + break; + case ParseWithinComboEntries: + comboEntryCount++; + break; + default: + break; } break; default: diff --git a/src/plugins/projectexplorer/customwizard/customwizardparameters.h b/src/plugins/projectexplorer/customwizard/customwizardparameters.h index f71de2b612..e5c26abf3f 100644 --- a/src/plugins/projectexplorer/customwizard/customwizardparameters.h +++ b/src/plugins/projectexplorer/customwizard/customwizardparameters.h @@ -49,6 +49,10 @@ struct CustomWizardField { CustomWizardField(); void clear(); + // Attribute map keys for combo entries + static QString comboEntryValueKey(int i); + static QString comboEntryTextKey(int i); + QString description; QString name; ControlAttributeMap controlAttributes; |