0

Hello I'm currently designing an GUI application who's main job is to update and display settings and some other data. For context, I'm using QT framework. I'm starting to refactor the settings because the list of settings has grown and now we're having an issue where there's inter-setting dependencies. For example, there's a switch setting (enable/disable) which affects other settings by disabling or enabling them. Or there's a value of one setting that affects the value of its dependent settings. There are several types of settings (integer, stringInput, toggleSwitch, timer, combobox). Currently, I have a god class(I know bad practice) called SettingPresenter which contains a list of all the settings, does the saving & dependency setting(which is a bunch of if else statements), and connects with the setting model. It also handles the setting values that are modified on screen and then sends them upstream as requests to another application. There are multiple setting pages which contain only a subset of all settings. Some dependencies are local to just that page, others are more global and could affect settings on other pages.

As I'm refactoring I'm removing certain aspects out of this class into others. I'm still trying to wrap my brain around how to implement a good design for setting dependency. I think a manager type class is good for call updateValue and handling the dependency. Please see below.

class SettingsManager {
public:
// Method to add a setting to the manager
void addSetting(const SettingIdentifier& identifier, Setting* setting);

// Method to update the value of a setting
void updateSettingValue(const SettingIdentifier& identifier, int newValue);

// Method to add dependency between settings
void addDependency(const SettingIdentifier& sourceIdentifier, const SettingIdentifier& dependentIdentifier);


private:
QMap<SettingIdentifier, Setting*> settingsMap;
QMap<SettingIdentifier, QVector<SettingIdentifier>> dependenciesMap;
};

// Implementation of SettingsManager

void SettingsManager::addSetting(const SettingIdentifier& identifier, Setting* setting) {
settingsMap.insert(identifier, setting);
}

void SettingsManager::updateSettingValue(const SettingIdentifier& identifier, int newValue) {
auto it = settingsMap.find(identifier);
if (it != settingsMap.end()) {
    Setting* setting = it.value();
    setting->setValue(newValue);
 }
}

void SettingsManager::addDependency(const SettingIdentifier& sourceIdentifier, const SettingIdentifier& dependentIdentifier) {
 dependenciesMap[sourceIdentifier].append(dependentIdentifier);
}


class Setting : public QObject {
Q_OBJECT

public:
    Setting(const SettingIdentifier& identifier, int initialValue);
    virtual ~Setting() = default;

    // Getters
    QVariant getValue() const;
    const SettingIdentifier& getIdentifier() const;

    // Method to set the value and notify dependents
    void setValue(QVariant newValue);

signals:
    // Signal emitted when the setting value changes
    void valueChanged(const SettingIdentifier& identifier, int newValue);

private:
    SettingIdentifier identifier;
    int value;
};

Is there any design patterns I should be looking into for this kind of dependency handling? Is this a reasonable approach? Because another issue I'm struggling to figure out is how to map the actions of each dependent when it's parent setting changes. For example, a toggle switch setting may just enable and disable its dependents. But a different toggle switch when toggled (ex Daylight Savings) requires a time calculation from timers on the page and sent upstream via request. Any feedback is appreciated and I can supply more code/thoughts if needed.

Another approach could be having the setting class use a notifyDependents signal and have the settings handle that. However as explained above the actual logic of updating the dependents would then need to in the Settings class which i feel could be messy since there's several different types of settings.

class Setting : public QObject {
Q_OBJECT

public:
    // Constructor, methods, etc. as before...

signals:
    // Signal emitted to notify dependents of value changes
    void notifyDependents(const SettingIdentifier& identifier, int newValue);

private:
    // Method to notify dependents
    void notifyDependents();
};

// Implementation of notifyDependents method
void Setting::notifyDependents() {
 for (Setting* dependent : dependents) {
     emit notifyDependents(identifier, value);
    }
}

0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.