Один из способов реализации приведен ниже.
Если вы хотите, центральное место для настроек может быть одноэлементным, полученным из QAbstractItemModel
, и вы можете легко подключать сигнал dataChanged(...)
к различным объектам по мере необходимости, чтобы получать уведомления об измененных настройках. Эти объекты могут решить, был ли изменен применимый параметр. Разумное использование вспомогательных классов и классов-прокладок позволяет очень легко связать ваши «маленькие классы» с уведомлениями. Это позволит решить две проблемы, присущие подходу к настройкам на основе модели.
Возможно большое количество подписчиков, все получают уведомления о настройках, которые им обычно не нужны (проблема filtering ).
Дополнительный код, необходимый для связи подписчика с моделью изделия, и дублирование информации о том, какие индексы модели актуальны (проблема selection ).
Как с фильтрацией, так и с выбором может заниматься класс shim, который получает все уведомления dataChanged
, и для каждого полезного индекса ведет список подписчиков. Тогда будут задействованы только слоты «заинтересованных» объектов. Этот класс будет самостоятельно поддерживать список пар абонент-слот, не предлагая никаких сигналов для подключения других. Он будет использовать invokeMethod
или аналогичный механизм для вызова слотов.
Проблема выбора может быть решена путем наблюдения, что классы подписчиков будут, после инициализации, запрашивать модель для начальных значений всех параметров, которые влияют на их работу - что они «заинтересованы». Все, что вам нужно, это модель временного прокси, которую вы создаете на время инициализации подписчика. Прокси-модель берет экземпляр вызывающего абонента QObject*
и записывает все запрашиваемые индексы модели (передавая их в модель настроек синглтона). Когда прокси-модель окончательно уничтожается по возвращении из инициализации класса подписчика, она передает информацию об индексах модели для этого QObject
в синглтон. Один дополнительный вызов необходим, чтобы синглтон узнал о слоте для вызова, но это все равно, что позвонить connect()
.