diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/core/kcoreconfigskeleton.cpp | 74 | ||||
| -rw-r--r-- | src/core/kcoreconfigskeleton.h | 51 | ||||
| -rw-r--r-- | src/kconfig_compiler/kconfig_compiler.cpp | 79 | 
3 files changed, 184 insertions, 20 deletions
| diff --git a/src/core/kcoreconfigskeleton.cpp b/src/core/kcoreconfigskeleton.cpp index d9b95b4b..98d9cdcc 100644 --- a/src/core/kcoreconfigskeleton.cpp +++ b/src/core/kcoreconfigskeleton.cpp @@ -1339,3 +1339,77 @@ KConfigSkeletonItem *KCoreConfigSkeleton::findItem(const QString &name) const      return d->mItemDict.value(name);  } +KConfigCompilerSignallingItem::KConfigCompilerSignallingItem(KConfigSkeletonItem* item, QObject* object, +        KConfigCompilerSignallingItem::NotifyFunction targetFunction, quint64 userData) +    : KConfigSkeletonItem(item->group(), item->key()), mItem(item), mTargetFunction(targetFunction), +    mObject(object), mUserData(userData) +{ +    Q_ASSERT(mTargetFunction); +    Q_ASSERT(mItem); +    Q_ASSERT(mObject); +} + +KConfigCompilerSignallingItem::~KConfigCompilerSignallingItem() +{ +} + +bool KConfigCompilerSignallingItem::isEqual(const QVariant& p) const +{ +    return mItem->isEqual(p); +} + +QVariant KConfigCompilerSignallingItem::property() const +{ +    return mItem->property(); +} + +void KConfigCompilerSignallingItem::readConfig(KConfig* c) +{ +    QVariant oldValue = mItem->property(); +    mItem->readConfig(c); +    //readConfig() changes mIsImmutable, update it here as well +    KConfigGroup cg(c, mGroup ); +    readImmutability(cg); +    if (!mItem->isEqual(oldValue)) { +        invokeNotifyFunction(); +    } +} + +void KConfigCompilerSignallingItem::readDefault(KConfig* c) +{ +    mItem->readDefault(c); +    //readDefault() changes mIsImmutable, update it here as well +    KConfigGroup cg(c, mGroup ); +    readImmutability(cg); +} + +void KConfigCompilerSignallingItem::writeConfig(KConfig* c) +{ +    mItem->writeConfig(c); +} + +void KConfigCompilerSignallingItem::setDefault() +{ +    QVariant oldValue = mItem->property(); +    mItem->setDefault(); +    if (!mItem->isEqual(oldValue)) { +        invokeNotifyFunction(); +    } +} + +void KConfigCompilerSignallingItem::setProperty(const QVariant& p) +{ +    if (!mItem->isEqual(p)) { +        mItem->setProperty(p); +        invokeNotifyFunction(); +    } +} + +void KConfigCompilerSignallingItem::swapDefault() +{ +    QVariant oldValue = mItem->property(); +    mItem->swapDefault(); +    if (!mItem->isEqual(oldValue)) { +        invokeNotifyFunction(); +    } +} diff --git a/src/core/kcoreconfigskeleton.h b/src/core/kcoreconfigskeleton.h index c1a15877..9cd07994 100644 --- a/src/core/kcoreconfigskeleton.h +++ b/src/core/kcoreconfigskeleton.h @@ -304,6 +304,57 @@ protected:  };  /** + * \class KConfigSkeletonChangeNotifyingItem kcoreconfigskeleton.h <KConfigSkeletonChangeNotifyingItem> + * + * @author Alex Richardson + * @see KConfigSkeletonItem + * + * + * This class wraps a @ref KConfigSkeletonItem and invokes a function whenever the value changes. + * That function must take one quint64 parameter. Whenever the property value of the wrapped KConfigSkeletonItem + * changes this function will be invoked with the stored user data passed in the constructor. + * It does not call a function with the new value since this class is designed solely for the kconfig_compiler generated + * code and is therefore probably not suited for any other usecases. + */ +class KCONFIGCORE_EXPORT KConfigCompilerSignallingItem : public KConfigSkeletonItem +{ +public: +    typedef void (QObject::* NotifyFunction)(quint64 arg); +    /** +    * Constructor. +    * +    * @param item the KConfigSkeletonItem to wrap +    * @param targetFunction the method to invoke whenever the value of @p item changes +    * @param object The object on which the method is invoked. +    * @param userData This data will be passed to @p targetFunction on every property change +    */ +    KConfigCompilerSignallingItem(KConfigSkeletonItem *item, QObject* object, +            NotifyFunction targetFunction, quint64 userData); +    virtual ~KConfigCompilerSignallingItem(); + +    virtual void readConfig(KConfig *) Q_DECL_OVERRIDE; +    virtual void writeConfig(KConfig *) Q_DECL_OVERRIDE; +    virtual void readDefault(KConfig *) Q_DECL_OVERRIDE; +    virtual void setProperty(const QVariant &p) Q_DECL_OVERRIDE; +    virtual bool isEqual(const QVariant &p) const Q_DECL_OVERRIDE; +    virtual QVariant property() const Q_DECL_OVERRIDE; +    virtual void setDefault() Q_DECL_OVERRIDE; +    virtual void swapDefault() Q_DECL_OVERRIDE; +private: +    inline void invokeNotifyFunction() +    { +        // call the pointer to member function using the strange ->* operator +        (mObject->*mTargetFunction)(mUserData); +    } +private: +    QScopedPointer<KConfigSkeletonItem> mItem; +    NotifyFunction mTargetFunction; +    QObject* mObject; +    quint64 mUserData; +}; + + +/**   * \class KCoreConfigSkeleton kcoreconfigskeleton.h <KCoreConfigSkeleton>   *   * @short Class for handling preferences settings for an application. diff --git a/src/kconfig_compiler/kconfig_compiler.cpp b/src/kconfig_compiler/kconfig_compiler.cpp index 0c4254a2..7d84cfbc 100644 --- a/src/kconfig_compiler/kconfig_compiler.cpp +++ b/src/kconfig_compiler/kconfig_compiler.cpp @@ -1152,12 +1152,17 @@ static QString itemDeclaration(const CfgEntry *e, const CfgConfig &cfg)          return QString();      } +    QString type; +    if (!e->signalList().isEmpty()) { +        type = "KConfigCompilerSignallingItem"; +    } else { +        type = cfg.inherits + "::Item" + itemType(e->type()); +    } +      QString fCap = e->name();      fCap[0] = fCap[0].toUpper(); -    return "  " + cfg.inherits + "::Item" + itemType(e->type()) + -           "  *item" + fCap + -           ((!e->param().isEmpty()) ? (QString("[%1]").arg(e->paramMax() + 1)) : QString()) + -           ";\n"; +    return "  " + type + "  *item" + fCap + +            ( (!e->param().isEmpty())?(QString("[%1]").arg(e->paramMax()+1)) : QString()) + ";\n";  }  // returns the name of an item variable @@ -1192,24 +1197,41 @@ static QString itemPath(const CfgEntry *e, const CfgConfig &cfg)      return result;  } -QString newItem(const QString &type, const QString &name, const QString &key, -                const QString &defaultValue, const CfgConfig &cfg, const QString ¶m = QString()) -{ -    QString t = "new " + cfg.inherits + "::Item" + itemType(type) + -                "( currentGroup(), " + key + ", " + varPath(name, cfg) + param; -    if (type == "Enum") { -        t += ", values" + name; +QString newItem(const CfgEntry* entry, const QString &key, const QString& defaultValue, +                const CfgConfig &cfg, const QString ¶m = QString()) { + +    QList<Signal> sigs = entry->signalList(); +    QString t; +    if (!sigs.isEmpty()) { +        t += "new KConfigCompilerSignallingItem("; +    } +    t += "new "+ cfg.inherits + "::Item" + itemType(entry->type()) + "( currentGroup(), " +            + key + ", " + varPath( entry->name(), cfg ) + param; + +    if (entry->type() == "Enum") { +        t += ", values" + entry->name();      }      if (!defaultValue.isEmpty()) {          t += ", "; -        if (type == "String") { +        if (entry->type() == "String") {              t += defaultValue;          } else {              t += defaultValue;          }      } -    t += " );"; +    t += " )"; +    if (!sigs.isEmpty()) { +        t += ", this, notifyFunction, "; +        //append the signal flags +        for (int i = 0; i < sigs.size(); ++i) { +            if (i != 0) +                t += " | "; +            t += signalEnumName(sigs[i].name); +        } +        t += ")"; +    } +    t += ";";      return t;  } @@ -2019,6 +2041,10 @@ int main(int argc, char **argv)              h << ");" << endl;          }          h << endl; + +        h << "  private:" << endl; +        h << "    void itemChanged(quint64 flags);" << endl; +        h << endl;      }      h << "  protected:" << endl; @@ -2185,7 +2211,10 @@ int main(int argc, char **argv)          }          cpp << endl << "    // items" << endl;          for (itEntry = entries.constBegin(); itEntry != entries.constEnd(); ++itEntry) { -            cpp << "    " + cfg.inherits + "::Item" << itemType((*itEntry)->type()) << " *" << itemVar(*itEntry, cfg); +            const QString declType = (*itEntry)->signalList().isEmpty() +                    ? QString(cfg.inherits + "::Item" + itemType((*itEntry)->type())) +                    : "KConfigCompilerSignallingItem"; +            cpp << "    " << declType << " *" << itemVar( *itEntry, cfg );              if (!(*itEntry)->param().isEmpty()) {                  cpp << QString("[%1]").arg((*itEntry)->paramMax() + 1);              } @@ -2302,6 +2331,14 @@ int main(int argc, char **argv)      group.clear(); +    if (hasSignals) { +        // this cast to base-class pointer-to-member is valid C++ +        // http://stackoverflow.com/questions/4272909/is-it-safe-to-upcast-a-method-pointer-and-use-it-with-base-class-pointer/ +        cpp << "  KConfigCompilerSignallingItem::NotifyFunction notifyFunction =" +            << " static_cast<KConfigCompilerSignallingItem::NotifyFunction>(&" +            << cfg.className << "::itemChanged);" << endl << endl; +    } +      for (itEntry = entries.constBegin(); itEntry != entries.constEnd(); ++itEntry) {          if ((*itEntry)->group() != group) {              if (!group.isEmpty()) { @@ -2353,7 +2390,7 @@ int main(int argc, char **argv)          if ((*itEntry)->param().isEmpty()) {              // Normal case              cpp << "  " << itemPath(*itEntry, cfg) << " = " -                << newItem((*itEntry)->type(), (*itEntry)->name(), key, (*itEntry)->defaultValue(), cfg) << endl; +                << newItem((*itEntry), key, (*itEntry)->defaultValue(), cfg) << endl;              if (!(*itEntry)->minValue().isEmpty()) {                  cpp << "  " << itemPath(*itEntry, cfg) << "->setMinValue(" << (*itEntry)->minValue() << ");" << endl; @@ -2388,8 +2425,7 @@ int main(int argc, char **argv)                  }                  cpp << "  " << itemVarStr << " = " -                    << newItem((*itEntry)->type(), (*itEntry)->name(), paramString(key, *itEntry, i), defaultStr, cfg,  QString("[%1]").arg(i)) -                    << endl; +                    << newItem((*itEntry), paramString(key, *itEntry, i), defaultStr, cfg, QString("[%1]").arg(i)) << endl;                  if (cfg.setUserTexts) {                      cpp << userTextsFunctions(*itEntry, cfg, itemVarStr, (*itEntry)->paramName()); @@ -2537,10 +2573,13 @@ int main(int argc, char **argv)          cpp << "  " << varPath("settingsChanged", cfg) << " = 0;" << endl;          cpp << "  return true;" << endl;          cpp << "}" << endl; -    } -    // Add includemoc if they are signals defined. -    if (hasSignals) { +        cpp << endl; +        cpp << "void " << cfg.className << "::" << "itemChanged(quint64 flags) {" << endl; +        cpp << "  " << varPath("settingsChanged", cfg) << " |= flags;" << endl; +        cpp << "}" << endl; + +        // Add includemoc if they are signals defined.          cpp << endl;          cpp << "#include \"" << mocFileName << "\"" << endl;          cpp << endl; | 
