Skip to content

Kotatogram Settings: Quick developer reference

RadRussianRus edited this page Feb 14, 2022 · 1 revision

Step 1: add setting to definition map

File: Telegram/SourceFiles/kotato/kotato_settings.cpp

Find the following:

const std::map<QString, Definition, std::greater<QString>> DefinitionMap

and add new definition to it:

	{ "my_custom_setting", {
		.scope = SettingScope::Global,
		.storage = SettingStorage::MainJson,
		.type = SettingType::BoolSetting,
		.defaultValue = false,
		.fillerValue = false,
		.limitHandler = nullptr }},
  • key (in this example "my_custom_setting", QString): this is the name of option that will be used both in code and in JSON file.
  • scope (enum SettingScope): SettingScope::Global will apply setting to all accounts, SettingScope::Account will apply to current account only. If not set, SettingScope::Global is assumed.
  • storage (enum SettingStorage): SettingStorage::MainJson will save it to JSON settings file, SettingStorage::None can be used in app, but changes won't be saved. If not set, SettingStorage::MainJson is assumed.
  • type (enum SettingType): values SettingType::BoolSetting, SettingType::IntSetting, SettingType::QStringSetting, SettingType::QJsonArraySetting resemble the types bool, int, QString and QJsonArray. If not set, SettingType::BoolSetting is assumed.
  • defaultValue (QVariant): sets default value that will be used if it wasn't set earlier. Will be null if it's not set.
  • fillerValue (QVariant): used in default settings file as an example. If not set, it will use defaultValue.
  • limitHandler (CheckHandler, defined as Fn<QVariant(QVariant)>): this function takes user-provided value (QVariant) and returns filtered version of this value (QVariant). If it's nullptr, only basic type will be checked. If not set, nullptr is assumed.

Handler generators

Some handler generator functions that you can use as an example or value:

CheckHandler IntLimit(int min, int max, int defaultValue)

IntLimit generates handler that sets number to min if it's lower than min, and sets number to max if it's higher than max. If value can't be converted to int, sets it to defaultValue.


inline CheckHandler IntLimit(int min, int max)

Same IntLimit as previous one, but uses min instead of defaultValue.


CheckHandler IntLimitMin(int min)

Version of IntLimit that limits only from one side: it sets number to min if it's lower than min. If value can't be converted to int, sets it to min.


CheckHandler ScalesLimit() 

Handler generator used specifically in "scales" option. Limits array to 6 values, and scales to range from style::kScaleMin to style::kScaleMax.


CheckHandler ReplacesLimit()

Handler generator used specifically in "replaces" option. Checks if sub-values are QJsonArray's with two QString elements (from, to).


CheckHandler FileDialogLimit()

Handler generator used specifically in "file_dialog_type" option. Converts integer values to Platform::FileDialog::ImplementationType enum.


CheckHandler NetSpeedBoostConv(CheckHandler wrapped = nullptr)

Handler generator used specifically in "net_speed_boost" option. Maps string values (low, medium, high) to integer values. wrapped used as post-filter. In "net_speed_boost" it's used NetSpeedBoostConv(IntLimit(0, 3)).

Step 2: use your option in code

First, you must include settings header file, if it's not included:

#include "kotato/kotato_settings.h"

Getting the value

To get the value, you can use this:

::Kotato::JsonSettings::Get("my_custom_setting")

There are also two additonal parameters: account id (uint64, default is 0, which means "all accounts"), and "is test server" (bool, default is false, but it is used only when account id is not 0).

Example for account id 777 on test server:

::Kotato::JsonSettings::Get("my_custom_setting", 777, true)

Example for account id 555 on production server:

::Kotato::JsonSettings::Get("my_custom_setting", 555)

or

::Kotato::JsonSettings::Get("my_custom_setting", 555, false)

Usually you don't need to set those by hand, these examples are just for demonstration.

Get function caveat

There's the one caveat. ::Kotato::JsonSettings::Get, returns QVariant, so to use it correctly you should use QVariant's methods .toBool(), .toInt(), .toString() and .toJsonArray(), depending on type. You can also use shorthand methods:

::Kotato::JsonSettings::GetBool("my_custom_setting"); // returns bool
::Kotato::JsonSettings::GetInt("my_custom_setting"); // returns int
::Kotato::JsonSettings::GetString("my_custom_setting"); // returns QString
::Kotato::JsonSettings::GetJsonArray("my_custom_setting"); // returns QJsonArray

Parameters are the same as in original Get, only difference is that shorthands return type you need.

Setting the value

To set an option you can use a following method:

::Kotato::JsonSettings::Set("my_custom_setting", true);

In that case true is the value (QVariant). QVariant will accept any supported value.

Warning! Set is not doing type checks, so it's the developer responsiblity to use the correct type. You have been warned.

Set also supports account id and test server check parameters, explained in "Getting the value":

::Kotato::JsonSettings::Set("my_custom_setting", true /* value */, 777 /* account id */, true /* is test server */);

Don't forget to save your options after you've changed them:

::Kotato::JsonSettings::Write();

If called multiple times in short period of time, writing to file is delayed for 5 seconds to reduce file I/O operations, unless app is restarting.

Resetting the value to default

To reset an option you can use a following method:

::Kotato::JsonSettings::Reset("my_custom_setting");

Like with Set, account id and test server check parameters are also supported:

::Kotato::JsonSettings::Reset("my_custom_setting", 777 /* account id */, true /* is test server */);

Don't forget to save your options after you've changed them:

::Kotato::JsonSettings::Write();

After-restart options

Some options must be applied only after restart, because there are too many dependencies to change it on the go.

To set an option after restart you can use a following method:

::Kotato::JsonSettings::SetAfterRestart("my_custom_setting", true);

Reset also has AfterRestart version:

::Kotato::JsonSettings::ResetAfterRestart("my_custom_setting");

Note that Get method (along with shorthands) will return the value that was loaded on app start. If you want to know what value will be applied after restart, you can use GetWithPending method:

::Kotato::JsonSettings::GetWithPending("my_custom_setting");

Note that it returns QVariant that is needed to convert. Instead of that, you can use shorthands:

::Kotato::JsonSettings::GetBoolWithPending("my_custom_setting"); // returns bool
::Kotato::JsonSettings::GetIntWithPending("my_custom_setting"); // returns int
::Kotato::JsonSettings::GetStringWithPending("my_custom_setting"); // returns QString
::Kotato::JsonSettings::GetJsonArrayWithPending("my_custom_setting"); // returns QJsonArray

Account id and test server check parameters are also supported in all these methods.

RPL

TDesktop heavily relies on self-written RPL library. This library allows to listen to events, and do actions in widgets after they're triggered.

While RPL itself is out of scope of this page, there are methods that you can use.


::Kotato::JsonSettings::Events("my_custom_setting") // returns rpl::producer<QString>

This method, combined with, for example, rpl::start_with_next, will allow to run actions after it's changed. Actual implementation may be harder, so it's better to study code that already uses RPL. Also note that QString is not a value: it's a combined settings map key. Value should be obtained yourself by calling Get or GetWithPending (or their shorthands).

Events also supports account id and test server check parameters, explained in "Getting the value":

::Kotato::JsonSettings::Events("my_custom_setting", 777 /* account id */, true /* is test server */);

::Kotato::JsonSettings::RestartEvents() // returns rpl::producer<bool>

Triggers when SetAfterRestart/ResetAfterRestart is used. Contained value shows if restart is needed: true: needs restart, false: doesn't need restart.

This function is currently unused and may be changed or removed.