aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/core/kcoreconfigskeleton.cpp74
-rw-r--r--src/core/kcoreconfigskeleton.h51
-rw-r--r--src/kconfig_compiler/kconfig_compiler.cpp79
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 &param = 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 &param = 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;