ACC SHELL

Path : /usr/share/YaST2/include/ntp-client/
File Upload :
Current File : //usr/share/YaST2/include/ntp-client/widgets.ycp

/**
 * File:	include/ntp-client/widgets.ycp
 * Package:	Configuration of ntp-client
 * Summary:	Widgets definitions
 * Authors:	Jiri Srain <jsrain@suse.cz>
 *
 * $Id: widgets.ycp 61623 2010-04-08 14:56:04Z varkoly $
 */

{

textdomain "ntp-client";

import "Confirm";
import "Popup";
import "Label";
import "LogView";
import "SLPAPI";
import "NetworkInterfaces";
import "NetworkService";
import "NtpClient";
import "CWMFirewallInterfaces";
import "Report";
import "Hostname";
import "IP";
import "Progress";

include "ntp-client/helps.ycp";
include "ntp-client/dialogs.ycp";

// selected type of peer
string peer_type_selected = nil;

/* List of NTP servers already found */
list <string> found_servers_cache = nil;

/* The 'Current Record' when NTP is being initialized, see bug 177575 */
map <string, any> selected_record_during_init = $[];

/**
 * Save the configuration and restart NTP deamon
 */
define boolean SilentWrite () {
    boolean orig_progress = Progress::set(false);
    boolean ret = NtpClient::Write();
    Progress::set(orig_progress);
    return ret;
}

/**
 * Show popup with NTP daemon's log
 */
define void showLogPopup () ``{
    LogView::Display ($[
	"file" : "/var/log/ntp",
	"save" : true,
	"actions" : [
	    // menubutton entry, try to keep short
	    [ _("Restart NTP Daemon"),
		restartNtpDaemon ],
	    // menubutton entry, try to keep short
	    [ _("Save Settings and Restart NTP Daemon"),
		SilentWrite ],
	],
    ]);
    return nil;
}

/**
 * Handle function of the widget
 * @param id string widget id
 * @param event map event that caused storing process
 * @return symbol always nil
 */
define symbol ntpEnabledOrDisabled (string id, map event) ``{
    any ev_id = event["ID"]:nil;
    if (ev_id == "boot" || ev_id == "never" || ev_id == "sync" )
    {
	boolean enabled = UI::QueryWidget (`id ("start"), `CurrentButton) != "never";
	UI::ChangeWidget (`id (id), `Enabled, enabled);
    }
}

/**
 * Handle function of the widget
 * @param id string widget id
 * @param event map event that caused storing process
 * @return symbol always nil
 */
define symbol timeSyncOrNo (string id, map event) ``{
    any ev_id = event["ID"]:nil;
    if (ev_id == "boot" || ev_id == "never" || ev_id == "sync" )
    {
	boolean enabled = UI::QueryWidget (`id ("start"), `CurrentButton) == "sync";
	UI::ChangeWidget (`id (id), `Enabled, enabled);
    }
}

/**
 * Initialize the widget
 * @param id any widget id
 */
define void intervalInit (string id) ``{
	UI::ChangeWidget (`id ("interval"), `Value, NtpClient::sync_interval);
}

/**
 * Store settings of the widget
 * @param id any widget id
 * @param event map event that caused storing process
 */
define void intervalStore (string id, map event) ``{
    NtpClient::sync_interval      = (integer)UI::QueryWidget (`id ("interval"), `Value);
}

/**
 * Initialize the widget
 * @param id any widget id
 */
define void startInit (string id) ``{
    if( NtpClient::synchronize_time )
    {
        UI::ChangeWidget (`id ("start"), `CurrentButton, "sync");
    }
    else if( NtpClient::run_service )
    {
        UI::ChangeWidget (`id ("start"), `CurrentButton, "boot");
    }
    else
    {
        UI::ChangeWidget (`id ("start"), `CurrentButton, "never");
    }
}

/**
 * Store settings of the widget
 * @param id any widget id
 * @param event map event that caused storing process
 */
define void startStore (string id, map event) ``{
    NtpClient::run_service      = UI::QueryWidget (`id ("start"), `CurrentButton) == "boot";
    NtpClient::synchronize_time = UI::QueryWidget (`id ("start"), `CurrentButton) == "sync";
}

/**
 * Handle function of the widget
 * @param id string widget id
 * @param event map event that caused storing process
 * @return any always nil
 */
define symbol startHandle (string id, map event) ``{
    boolean start = UI::QueryWidget (`id ("start"), `CurrentButton) == "boot";
    //All these network devices are possibly started on boot || managed by NM
    //hence do not display the message
    list<string> d1 = NetworkInterfaces::Locate ("STARTMODE", "onboot");
    list<string> d2 = NetworkInterfaces::Locate ("STARTMODE", "auto");
    list<string> d3 = NetworkInterfaces::Locate ("STARTMODE", "nfsroot");
    list<string> d4 = NetworkInterfaces::Locate ("STARTMODE", "managed");

    list<string> devices = (list <string>) union( union(d1,d2), union(d3,d4));
    devices = filter (string d, devices, ``(d != "lo"));
    //Do not display this warning if we use NetworkManager (#299666)
    if (start && !NetworkService::IsManaged() && size (devices) == 0 &&
        event["EventReason"]:"" != "" &&
	// continue-cancel popup
	! Popup::ContinueCancel (_("Warning!

If you do not have a permanent Internet connection,
starting the NTP daemon can take a very long time and 
the daemon might not run properly.")))
	UI::ChangeWidget (`id ("start"), `CurrentButton, "never");

    if (start != NtpClient::run_service)
	NtpClient::modified = true;

    if (start)
	CWMFirewallInterfaces::EnableOpenFirewallWidget ();
    else
	CWMFirewallInterfaces::DisableOpenFirewallWidget ();

    if (CWMFirewallInterfaces::OpenFirewallModified( "firewall" ))
	NtpClient::change_firewall = true;

    return nil;
}

/**
 * Checks the current simple configuration filled in UI.
 * Selected option RandomPoolServers returns true;
 * Selected valid server address also returns true;
 *
 * @return boolean whether the configuration is correct
 */
define boolean CheckCurrentSimpleConfiguration (boolean check_the_server) {
    // if the option "random_servers" is selected, do not check the server name
    if (UI::WidgetExists(`id("use_random_servers")) && (boolean) UI::QueryWidget(`id("use_random_servers"), `Value))
	return true;

    string server_1 = (string) UI::QueryWidget (`id ("server_address"), `Value);
    if (!check_the_server && server_1 == "") {
	y2milestone("Not checking an empty server...");
	return true;
    }

    string server_2 = server_1;
    if (regexpmatch(server_2, "(.*)\.$")) {
	server_2 = regexpsub (server_2, "(.*)\.$", "\\1");
    }
    
    if (
	(!Hostname::Check(server_1) && !Hostname::CheckFQ(server_1) && !IP::Check(server_1))
	&&
	(!Hostname::Check(server_2) && !Hostname::CheckFQ(server_2))
    ) {
	// TRANSLATORS: Popup error message
	Report::Error(sformat(_("NTP server '%1' is not a valid hostname,
fully qualified hostname, IPv4 address, or IPv6 address."), server_1));
	return false;
    }

    return true;
}

/**
 * Check the current confifuration and returns whether some server address is defined
 */
boolean ServerAddressIsInConfiguration () {
    boolean ret = false;
    boolean rss = NtpClient::IsRandomServersServiceEnabled();

    foreach (map<string, any> one_record, NtpClient::ntp_records, {
	// checking for server
	if (one_record["type"]:nil == "server") {
	    // RandomServersService is disabled
	    if (!rss) {
		ret = true;
		break;
	    // RandomServersService is enabled, don't take servers from RSS
	    } else if (!contains(NtpClient::random_pool_servers, one_record["address"]:"")) {
		ret = true;
		break;
	    }
	}
    });

    return ret;
}

/**
 * Handle function of the widget
 * @param key any widget id
 * @param event map event that caused storing process
 * @return symbol always `complex
 */
define symbol complexButtonHandle (string key, map event) ``{
    if (event["ID"]:nil == "complex_button") {
	// true  - check and report the missing server value
	// false - the opposite
	boolean handle_the_server = ((string) UI::QueryWidget (`id ("server_address"), `Value) != "");

	boolean conf_check = CheckCurrentSimpleConfiguration(handle_the_server);
	y2milestone("Checking the current simple configuration returned: %1", conf_check);

	NtpClient::selected_record["address"] = UI::QueryWidget (`id ("server_address"), `Value);
	// disabled in case of PoolNTPorg feature
	// and in case of missing server value
	if ((boolean) UI::QueryWidget (`id ("server_address"), `Enabled) &&
	  NtpClient::selected_record["address"]:nil != nil &&
	  NtpClient::selected_record["address"]:"" != "") {
	    // Save the server_address only when changed
	    // do not re-add it (with defaut values) - bug 177575
	    if (selected_record_during_init["address"]:"" == NtpClient::selected_record["address"]:"") {
		y2milestone("The currently selected server is the same as when starting the module...");
	    } else {
		NtpClient::selected_record["type"] = "server";
		y2milestone("Storing the current address record: %1", NtpClient::selected_record);
		NtpClient::storeSyncRecord();
	    }
	// deleting the current record if current server address is empty
	} else if (NtpClient::selected_record["address"]:"" == "") {
	    // delete only the server record if there is some current server record
	    if (ServerAddressIsInConfiguration()) {
		NtpClient::selected_record = nil;
		NtpClient::storeSyncRecord();
	    }
	}

	y2milestone("Switching to advanced configuration...");
	return `complex;
    }
    ntpEnabledOrDisabled (key, event);
    return nil;
}

/**
 * Handle function of the widget
 * @param key string widget id
 * @param event map event that caused storing process
 * @return symbol always `complex
 */
define symbol fudgeButtonHandle (string key, map event) ``{
    return `fudge;
}

/**
 * Initialize the widget
 * @param id any widget id
 */
define void chrootInit (string id) ``{
    UI::ChangeWidget (`id (id), `Value, NtpClient::run_chroot);
}

/**
 * Store settings of the widget
 * @param id any widget id
 * @param event map event that caused storing process
 */
define void chrootStore (string id, map event) ``{
    NtpClient::run_chroot = (boolean)(UI::QueryWidget (`id (id), `Value));
    NtpClient::modified = true;
}

define void secureInit (string id) ``{
    y2milestone("Restrict %1", NtpClient::restrict_map);
    if (NtpClient::PolicyIsNonstatic ())
	UI::ChangeWidget(`id("secure"), `Enabled, false);
    else
	UI::ChangeWidget(`id("secure"), `Value, ( NtpClient::restrict_map != $[]) );
}

define void secureStore (string id, map event) ``{
    boolean restrict = (boolean)(UI::QueryWidget(`id(id),`Value));

    if (restrict)
    {
	list <string> servers = NtpClient::GetUsedNtpServers();

	if( NtpClient::restrict_map == $[] )
	{
	    NtpClient::restrict_map["default"] = $[
		"mask" : "",
		"comment" : "",
		"options" : "ignore"
	    ];

	    NtpClient::restrict_map["127.0.0.1"] = $[
		"mask" : "",
		"comment" : "",
		"options" : ""
	    ];

	    foreach (string s, servers, {
		NtpClient::restrict_map[s] = $[
		    "mask" : "",
		    "comment" : "",
		    "options" : "nomodify notrap noquery"
		];
	    });
	}
    }
    else
    {
	NtpClient::restrict_map = $[];
    }
}

/**
 * Initialize the widget
 * @param id any widget id
 */
void PolicyInit(string id) {
    if (NtpClient::PolicyIsNomodify ())
    {
	UI::ChangeWidget(`id("policy_combo"), `Value, `id(`nomodify));
	UI::ChangeWidget(`id("custom_policy"), `Value, "");
	UI::ChangeWidget(`id("custom_policy"), `Enabled, false);
    }
    else if (NtpClient::PolicyIsAuto ())
    {
	UI::ChangeWidget(`id("policy_combo"), `Value, `id(`auto));
	UI::ChangeWidget(`id("custom_policy"), `Value, "");
	UI::ChangeWidget(`id("custom_policy"), `Enabled, false);
    }
    else
    {
	UI::ChangeWidget(`id("policy_combo"), `Value, `id(`custom));
	UI::ChangeWidget(`id("custom_policy"), `Value, NtpClient::ntp_policy);
	UI::ChangeWidget(`id("custom_policy"), `Enabled, true);
    }
}

/**
 * Store settings of the widget
 * @param id any widget id
 * @param event map event that caused storing process
 */
void PolicyStore(string id, map event) {
    if( UI::QueryWidget (`id ("policy_combo"), `Value) == `nomodify )
    {
	NtpClient::ntp_policy = "";
    }
    else if( UI::QueryWidget (`id ("policy_combo"), `Value) == `auto )
    {
	NtpClient::ntp_policy = "auto";
    }
    else
    {
	NtpClient::ntp_policy = (string)UI::QueryWidget (`id ("custom_policy"), `Value);
    }
    NtpClient::modified = true;
}


define void RandomServersInit (string id) {
    ntpEnabledOrDisabled(id, $[]);
    if (id != "use_random_servers") return nil;
    y2milestone("Initializing random servers");

    boolean rnd_servers = NtpClient::IsRandomServersServiceEnabled();
    if (rnd_servers) {
	// Random servers function is enabled
	UI::ChangeWidget(`id ("use_random_servers"), `Value, true);
	UI::ChangeWidget(`id ("server_address"), `Enabled, false);
	UI::ChangeWidget(`id (`select_server), `Enabled, false);
	UI::ChangeWidget(`id ("server_address"), `Value, "");
    } else {
	// Random servers function is disabled
	UI::ChangeWidget(`id ("use_random_servers"), `Value, false);
	if (NtpClient::run_service || NtpClient::synchronize_time) {
	    UI::ChangeWidget(`id ("server_address"), `Enabled, true);
	    UI::ChangeWidget(`id (`select_server), `Enabled, true);
	} else {
	    UI::ChangeWidget(`id ("server_address"), `Enabled, false);
	    UI::ChangeWidget(`id (`select_server), `Enabled, false);
	}
    }
}

define void RandomServersStore (string id, map event) {
    if (id != "use_random_servers") return nil;

    if ((boolean) UI::QueryWidget(`id("use_random_servers"), `Value)) {
	NtpClient::ActivateRandomPoolServersFunction();
    } else {
	NtpClient::DeActivateRandomPoolServersFunction();
    }
}

// if there was some server defined before pool_ntp_org was selected
string ntp_server_before_random_servers = "";

/**
 * Function handles the "use_random_servers" checkbox
 */
define symbol RandomServersHandle (string id, map event) {
    ntpEnabledOrDisabled(id, event);
    // do not handle anything when called by pressing the checkbox
    if (id != "use_random_servers") return nil;
    if (event["EventReason"]:"" != "ValueChanged") return nil;
    if (event["WidgetID"]:"" != "use_random_servers") return nil;

    y2milestone("Handling random_servers");
    boolean use_random_servers = (boolean) UI::QueryWidget(`id("use_random_servers"), `Value);
    // If random servers are selected, user is not allowed to enter his/her own NTP server
    if (use_random_servers) {
	y2milestone("Activating random servers");
	ntp_server_before_random_servers = (string) UI::QueryWidget(`id ("server_address"), `Value);
	// if there is already some server defined
	if (ntp_server_before_random_servers != "") {
	    if (!Popup::ContinueCancel(_("Enabling Random Servers from pool.ntp.org would
replace the current NTP server.

Really replace the current NTP server?"))) {
		// user has cancelled the operation, return it back
		UI::ChangeWidget(`id("use_random_servers"), `Value, false);
		return nil;
	    }
	}

	UI::ChangeWidget(`id ("server_address"), `Enabled, false);
	UI::ChangeWidget(`id (`select_server), `Enabled, false);
	UI::ChangeWidget(`id ("server_address"), `Value, "");
    } else {
	y2milestone("Deactivating random servers");
	UI::ChangeWidget(`id ("server_address"), `Enabled, true);
	UI::ChangeWidget(`id (`select_server), `Enabled, true);
	UI::ChangeWidget(`id ("server_address"), `Value, ntp_server_before_random_servers);
    }

    return nil;
}

/**
 * Redraw the overview table
 */
define void overviewRedraw () {
    map types = $[
	// table cell, NTP relationship type
	"server" : _("Server"),
	// table cell, NTP relationship type
	"peer" : _("Peer"),
	// table cell, NTP relationship type
	"broadcast" : _("Outgoing Broadcast"),
	// table cell, NTP relationship type
	"broadcastclient" : _("Incoming Broadcast"),
    ];
    list items = maplist (map<string,any> i, NtpClient::getSyncRecords (), ``{
	string type = i["type"]:"";
	string address = i["address"]:"";
	integer index = i["index"]:-1;
	if (type == "__clock")
	{
	    integer clock_type = getClockType (address);
	    integer unit_number = getClockUnitNumber (address);
	    string device = i["device"]:"";
	    if (device == "")
		// table cell, %1 is integer 0-3
		device = sformat (_("Unit Number: %1"), unit_number);
	    if (clock_type == 1 && unit_number == 0)
		device = "";
	    string clock_name = clock_types[clock_type, "name"]:"";
	    if (clock_name == "")
		// table cell, NTP relationship type
		clock_name = _("Local Radio Clock");
	    return `item (`id (index), clock_name, device);
	}
	return `item (`id (index), types[type]:"", address);
    });
    UI::ChangeWidget (`id (`overview), `Items, items);
    UI::SetFocus (`id (`overview));
}

/**
 * Handle events on the widget
 * @param id any widget id
 * @param event map event that caused storing process
 * @return any event to pass to WS or nil
 */
define symbol overviewHandle (string id, map event) ``{
//    ntpEnabledOrDisabled (id, event);
    if (event["ID"]:nil == `display_log)
    {
	showLogPopup ();
	return nil;
    }
    NtpClient::modified = true;
    any ev_id = event["ID"]:nil;
    if (ev_id == "boot" || ev_id == "never" || ev_id == "sync" || ev_id == "policy_combo" )
    {
	symbol pol = (symbol)UI::QueryWidget (`id ("policy_combo"), `Value);

	boolean enabled = UI::QueryWidget (`id ("start"), `CurrentButton)
	    != "never";
//	UI::ChangeWidget (`id (`advanced), `Enabled, enabled);
	enabled = (enabled && (pol != `nomodify));
	UI::ChangeWidget (`id (`add), `Enabled, enabled);
	UI::ChangeWidget (`id (`edit), `Enabled, enabled);
	UI::ChangeWidget (`id (`delete), `Enabled, enabled);
	UI::ChangeWidget (`id (`overview), `Enabled, enabled);

	if (enabled && (pol == `custom))
	{
	    UI::ChangeWidget (`id ("custom_policy"), `Enabled, true);
	    UI::ChangeWidget (`id ("custom_policy"), `Value, NtpClient::ntp_policy);
	}
	else
	{
	    UI::ChangeWidget (`id ("custom_policy"), `Enabled, false);
	    UI::ChangeWidget (`id ("custom_policy"), `Value, "");
	}
	return nil;
    }
    map<string,symbol> types = $[
	"server" : `server,
	"peer" : `peer,
	"__clock" : `clock,
	"broadcast" : `bcast,
	"broadcastclient" : `bcastclient,
    ];
    if (event["ID"]:nil == `add)
    {
	NtpClient::selectSyncRecord (-1);
	peer_type_selected = nil;
	return `add;
    }
    else if (event["ID"]:nil == `edit || event["ID"]:nil == `overview)
    {
	NtpClient::selectSyncRecord (
	    (integer)(UI::QueryWidget (`id (`overview), `CurrentItem))
	);
	string type = NtpClient::selected_record["type"]:"";
	return types[type]:nil;
    }
    else if (event["ID"]:nil == `delete)
    {
	// yes-no popup
	if (Confirm::DeleteSelected ())
	{
	    NtpClient::deleteSyncRecord (
		(integer)(UI::QueryWidget (`id (`overview), `CurrentItem))
	    );
	    overviewRedraw ();
	    sync_record_modified = true;
	}
    }
    return nil;
}

/**
 * Initialize the widget
 * @param id any widget id
 */
define void overviewInit (string id) ``{
    overviewRedraw ();
    overviewHandle (id, $["ID" : "boot"]);
}

/**
 * Initialize the widget
 * @param id any widget id
 */
define void addressInit (string id) ``{
    //remember selected_record_during_init only when the module is started
    //#230240
    if (selected_record_during_init == $[]){
        selected_record_during_init = NtpClient::selected_record;
    }

    string ad = NtpClient::ad_controller;
    if ( ad != "")
        UI::ChangeWidget(`id(id), `Value, ad);
    else {
        UI::ChangeWidget (`id (id), `Value,
	NtpClient::selected_record["address"]:"");
    }
    UI::SetFocus (`id (id));
}

/**
 * Store settings of the widget
 * @param id any widget id
 * @param event map event that caused storing process
 */
define void addressStore (string id, map event) ``{
    // Don't store anything in case of switching to the advanced configuration
    if (event["ID"]:nil == `complex) return;

    NtpClient::selected_record["address"] = UI::QueryWidget (`id (id), `Value);
    if (NtpClient::simple_dialog)
    {
	// Save the server_address only when changed
	// do not re-add it (with defaut values) - bug 177575
	if (selected_record_during_init["address"]:"" == NtpClient::selected_record["address"]:"")
	{
	    y2milestone("The currently selected server is the same as when starting the module...");
	}
	else
	{
	    y2milestone("Storing the server address in simple configuration");
	    NtpClient::selected_record["type"] = "server";
	}
    }
}

/**
 * Handle events on the widget
 * @param id string widget id
 * @param event map event that caused storing process
 * @return boolean is successful
 */
define boolean serverAddressValidate (string id, map event) {
    // NTP Client is disabled, do not check the server name
    if (event["ID"]:nil == `next
	&& UI::WidgetExists(`id ("start"))
	&& ((string) UI::QueryWidget (`id ("start"), `CurrentButton) == "never")
    ) {
	return true;
    }
    // do not check the server IP/Host when changing dialog to "Select"
    //   or when switching to the advanced configuration
    if (event["ID"]:nil == `select_local || event["ID"]:nil == `select_public || event["ID"]:nil == `complex) {
	return true;
    }
    
    return CheckCurrentSimpleConfiguration(true);
}

/**
 * Handle events on the widget
 * @param id string widget id
 * @param event map event that caused storing process
 * @return symbol event to pass to WS or nil
 */
define symbol serverAddressHandle (string id, map event) {
    any ev_id = event["ID"]:nil;
    string server = (string) UI::QueryWidget (`id (id), `Value);
    if (ev_id == "boot" || ev_id == "never")
    {
	boolean enabled = UI::QueryWidget (`id ("start"), `CurrentButton)
	    != "never";
	// checkbox selected - random servers feature
	if (UI::QueryWidget(`id ("use_random_servers"), `Value) == true) {
	    UI::ChangeWidget (`id (id), `Enabled, false);
	    UI::ChangeWidget (`id (`select_server), `Enabled, false);
	} else {
	    UI::ChangeWidget (`id (id), `Enabled, enabled);
	    UI::ChangeWidget (`id (`select_server), `Enabled, enabled);
	}
	UI::ChangeWidget (`id (`test_server), `Enabled, enabled);

	return nil;
    }
    if (ev_id == `test_server)
    {
	if (UI::WidgetExists(`id("use_random_servers")) && (boolean) UI::QueryWidget(`id("use_random_servers"), `Value)) {
	    NtpClient::TestNtpServer (NtpClient::random_pool_servers[random(4)]:"0.pool.ntp.org", `result_popup);
	} else {
	    if (serverAddressValidate("server_address",$[]))
		NtpClient::TestNtpServer (server, `result_popup);
	}
    }
    else if (ev_id == `select_local) {
	return `select_local;
    }
    else if (ev_id == `select_public) {
	return `select_public;
    }

    return nil;
}

/**
 * Initialize the widget
 * @param id any widget id
 */
define void optionsInit (string id) ``{
    // bnc#438704, add a recommended option
    UI::ChangeWidget (`id ("options"), `Value, NtpClient::selected_record["options"]:"iburst");
}

/**
 * Store settings of the widget
 * @param id any widget id
 * @param event map event that caused storing process
 */
define void optionsStore (string id, map event) ``{
    NtpClient::selected_record["options"] = UI::QueryWidget (`id ("options"), `Value);
}

define void restrictOptionsInit ( string id ) ``{
    string address = NtpClient::selected_record["address"]:"";
    if ( NtpClient::restrict_map == $[] || NtpClient::PolicyIsNonstatic ())
    {
	UI::ChangeWidget(`id("ac_options"), `Enabled, false);
    }
    else
    {
        if( haskey( NtpClient::restrict_map, address) )
	    UI::ChangeWidget(`id("ac_options"), `Value, NtpClient::restrict_map[address,"options"]:"");

	else
	    UI::ChangeWidget(`id("ac_options"), `Value, "notrap nomodify noquery");
    }
}

define void restrictOptionsStore (string id, map event ) ``{
    string address = NtpClient::selected_record["address"]:"";
    string opts = (string) UI::QueryWidget(`id("ac_options"), `Value);

    if( haskey( NtpClient::restrict_map, address) )
        NtpClient::restrict_map[address, "options"] = opts;
    else
    {
	NtpClient::restrict_map[address] = $[
	   "comment" : "",
	   "mask" : "",
	   "options" : opts,
	];
    }
}
/**
 * Initialize the widget
 * @param id any widget id
 */
define void peerTypesInit (string id) ``{
    if (peer_type_selected != nil)
	UI::ChangeWidget (`id ("peer_types"), `CurrentButton,
	    peer_type_selected);
    else
	UI::ChangeWidget (`id ("peer_types"), `CurrentButton, "server");
}

/**
 * Handle events on the widget
 * @param id any widget id
 * @param event map event that caused storing process
 * @return symbol event to pass to WS or nil
 */
define symbol peerTypesHandle (string id, map event) ``{
    peer_type_selected = (string)UI::QueryWidget (`id ("peer_types"), `CurrentButton);
    map<string,symbol> types = $[
	"server" : `server,
	"peer" : `peer,
	"__clock" : `clock,
	"broadcast" : `bcast,
	"broadcastclient" : `bcastclient,
    ];
    if (event["ID"]:nil == `next)
    {
	NtpClient::selected_record["type"] = peer_type_selected;
	return types[peer_type_selected]:nil;
    }
    return nil;
}

/**
 * Initialize the widget
 * @param id string widget id
 */
define void createSymlinkInit (string id) ``{
    UI::ChangeWidget (`id (id), `Value,
	NtpClient::selected_record["create_symlink"]:false);
}

/**
 * Handle function of the widget
 * @param id string widget id
 * @param event map event that caused storing process
 * @return symbol always nil
 */
define symbol createSymlinkHandle (string id, map event) ``{
    boolean active = (boolean)UI::QueryWidget (`id ("create_symlink"), `Value);
    integer current = 0;
    if (id == "clock_type") {
	current = tointeger ((string)UI::QueryWidget (`id (id), `Value));
	active = active && clock_types[current, "device"]:"" == "";
    }
    UI::ChangeWidget (`id ("device"), `Enabled, active);
    UI::ChangeWidget (`id ("browse"), `Enabled, active);
    return nil;
}

/**
 * Store settings of the widget
 * @param id string widget id
 * @param event map event that caused storing process
 */
define void createSymlinkStore (string id, map event) ``{
    NtpClient::selected_record["create_symlink"] = (boolean)
	UI::QueryWidget (`id (id), `Value);
}

/**
 * Handle function of the widget
 * @param id string widget id
 * @param event map event that caused storing process
 * @return symbol always nil
 */
define symbol clockTypeHandle (string id, map event) ``{
    integer current = tointeger ((string)UI::QueryWidget (`id (id), `Value));
    boolean hw_avail = clock_types[current, "device"]:"" != "";
    UI::ChangeWidget (`id ("create_symlink"), `Enabled, hw_avail);
    return createSymlinkHandle (id, event);
}

/**
 * Initialize the widget
 * @param id string widget id
 */
define void clockTypeInit (string id) ``{
    UI::ChangeWidget (`id (id), `Value, sformat ("%1",
	getClockType (NtpClient::selected_record["address"]:"")));
    clockTypeHandle (id, $[]);
}

/**
 * Store settings of the widget
 * @param id string widget id
 * @param event map event that caused storing process
 */
define void clockTypeStore (string id, map event) ``{
    NtpClient::selected_record["address"] = setClockType (
	NtpClient::selected_record["address"]:"",
	tointeger ((string)UI::QueryWidget (`id (id), `Value)));
}

/**
 * Initialize the widget
 * @param id string widget id
 */
define void unitNumberInit (string id) ``{
    UI::ChangeWidget (`id (id), `Value,
	getClockUnitNumber (NtpClient::selected_record["address"]:""));
}

/**
 * Store settings of the widget
 * @param id string widget id
 * @param event map event that caused storing process
 */
define void unitNumberStore (string id, map event) ``{
    NtpClient::selected_record["address"] = setClockUnitNumber (
	NtpClient::selected_record["address"]:"",
	(integer)UI::QueryWidget (`id (id), `Value));
}

/**
 * Handle function of the widget
 * @param id string widget id
 * @param event map event that caused storing process
 * @return symbol always nil
 */
define symbol browseButtonHandle (string id, map event) ``{
    string current = (string)UI::QueryWidget (`id ("device"), `Value);
    if (current == "")
	current = "/dev";
    // popup header
    current = UI::AskForExistingFile (current, "", _("Select the Device"));
    if (current != nil)
	UI::ChangeWidget (`id ("device"), `Value, current);
    return nil;
}

/**
 * Initialize the widget
 * @param id string widget id
 */
define void deviceInit (string id) ``{
    UI::ChangeWidget (`id (id), `Value, NtpClient::selected_record["device"]:"");
}

/**
 * Store settings of the widget
 * @param id string widget id
 * @param event map event that caused storing process
 */
define void deviceStore (string id, map event) ``{
    NtpClient::selected_record["device"] = (string)
	UI::QueryWidget (`id (id), `Value);
}

string last_country = nil;

/**
 * Handle function of the widget
 * @param id string widget id
 * @param event map event that caused storing process
 * @return symbol always nil
 */
symbol ServerListHandle (string id, map event) {
//    if (event["ID"]:nil == "list_rb" || event["ID"]:nil == "lookup_rb")
//    {
//	boolean enabled = (boolean)UI::QueryWidget (`id ("list_rb"), `Value);
//	UI::ChangeWidget (`id (`country), `Enabled, enabled);
//	UI::ChangeWidget (`id (`servers), `Enabled, enabled);
//	return nil;
//    }
    string country = (string)UI::QueryWidget (`id (`country), `Value);
    if (country == nil)
	country = "";
    y2milestone ("Handling server list change, last country: %1, current country: %2", last_country, country);
    if (country != last_country)
    {
	last_country = country;

	list items = NtpClient::GetNtpServersByCountry ( country, false); 
	UI::ReplaceWidget (`servers_rp,
	    `VBox(
		// Combobox has at least 40 characters
		// bug #97184
		`HSpacing(40),
		`ComboBox (
		    `id (`servers),
		    `opt (`hstretch),
		    // selection box header
		    _("Public NTP &Servers"),
		    items
		)
	    )
	);
	return nil;
    }
    if (event["ID"]:nil == `test || event["ID"]:nil == `info)
    {
	string server = (string)UI::QueryWidget (`id (`servers), `Value);
	if (server == nil || server == "")
	{
	    // message report (no server selected)
	    Report::Message (_("Select an NTP server."));
	    return nil;
	}
	if (event["ID"]:nil == `test)
	{
	    NtpClient::TestNtpServer (server, `result_popup);
	}
	return nil;
    }
    return nil;
}

/**
 * Initialize the widget
 * @param id string widget id
 */
void ServerListInit (string id) {
    map<string,string> country_names = NtpClient::GetCountryNames ();
    map<string,string> country_codes = mapmap (
	string k,
	string v,
	country_names,
    {
	return $[ v : k ];
    });
    list<string> country_name_list = maplist (
	string k,
	string v,
	country_codes,
    {
	return k;
    });
    country_name_list = lsort (country_name_list);
    list<string> countries_lst = toset (maplist (
	string s, map<string,string> m,
	NtpClient::GetNtpServers (),
    {
	string country = m["country"]:"";
	string label = country_names[country]:country;
	return label;
    }));
    countries_lst = lsort (countries_lst);
    list countries = maplist (string label, countries_lst, {
	string code = country_codes[label]:label;
	return `item (`id (code), label);
    });
    // combo box item
    countries = prepend (countries, `item (`id (""), _("All Countries")));
    UI::ReplaceWidget (`country_rp,
	`ComboBox (`id (`country), `opt (`notify, `hstretch),
	    // combo box header
	    _("&Country"), countries));
    last_country = nil;

    string lang =  NtpClient::GetCurrentLanguageCode();
    if (lang != nil)
    {
	y2milestone ("Current language: %1", lang);
	UI::ChangeWidget (`id (`country), `Value, lang);
    }
    ServerListHandle (id, $[]);
    ServerListHandle (id, $["ID" : "list_rb"]);
}

/**
 * Store settings of the widget
 * @param id string widget id
 * @param event map event that caused storing process
 */
void ServerListStore (string id, map event) {
    if (UI::WidgetExists (`id ("list_rb"))
	&& ! (boolean)UI::QueryWidget (`id ("list_rb"), `Value))
    {
	return;
    }
    string address = (string)UI::QueryWidget (`id (`servers), `Value);
    NtpClient::selected_record["address"] = address;
    //Do not forget to add type of the record - here we have 'server' (#216456)
    NtpClient::selected_record["type"] = "server";
}

/**
 * Validation function of a widget
 * @param id string widget id
 * @param event map event that caused validation
 * @return boolean true if validation succeeded
 */
boolean ServerListValidate (string id, map event) {
    if (UI::WidgetExists (`id ("list_rb"))
	&& ! (boolean)UI::QueryWidget (`id ("list_rb"), `Value))
    {
	return true;
    }
    string address = (string)UI::QueryWidget (`id (`servers), `Value);
    if (address == "" || address == nil)
    {
	// report message
	Report::Message (_("Select an NTP server."));
	return false;
    }
    return true;
}

/**
 * Initialize the widget
 * @param id string widget id
 */
void ServersSourceInit (string id) {
    UI::ChangeWidget (`id (id), `CurrentButton, "lookup_rb");
}


symbol FoundServersHandle (string id, map event) {
//    if (event["ID"]:nil == "list_rb" || event["ID"]:nil == "lookup_rb")
//    {
//	boolean enabled = (boolean)UI::QueryWidget (`id ("lookup_rb"), `Value);
//	UI::ChangeWidget (`id ("server_address"), `Enabled, enabled);
//	UI::ChangeWidget (`id (`lookup_server), `Enabled, enabled);
//	return nil;
//    }
    if (event["ID"]:nil == `lookup_server)
    {
	// TRANSLATORS: Busy message
	UI::OpenDialog(`Label(_("Scanning for NTP servers on your network...")));

	symbol method = `slp;
	list<string> server_names = sort(NtpClient::DetectNtpServers (method));
	found_servers_cache = server_names;

	UI::CloseDialog();

	// no server has been found
	if (server_names == [] || server_names == nil) {
	    // firewall probably blocks broadcast reply
	    if (SuSEFirewall::GetStartService()) {
		// TRANSLATORS: Popup error - no NTP server has been found during scanning the network.
		//              There is a very high possibility that is is because of running firewall.
		Report::Error(_("No NTP server has been found on your network.
This could be caused by a running SuSEfirewall2,
which probably blocks the network scanning."));
	    // no server is available on the network
	    } else {
		// TRANSLATORS: Popup error - no NTP server has been found during scanning the network.
		Report::Error(_("No NTP server has been found on your network."));
	    }
	    return nil;
	}

	UI::ReplaceWidget (`server_address_rp,
	    `ComboBox (`id ("server_address"),
		`opt (`editable, `hstretch),
		// combo box label
		_("Address"),
		server_names));
	return nil;
    }
    return nil;
}

/**
 * Initialize the widget
 * @param id string widget id
 */
void FoundServersInit (string id) {
    list <term> items = [];

    // fate#302863: suggest ntp.$domain
    if (found_servers_cache == nil) {
	string guessed = "ntp." + Hostname::CurrentDomain ();
	if (NtpClient::TestNtpServer (guessed, `transient_popup)) {
	    found_servers_cache = [ guessed ];
	}
	else {
	    found_servers_cache = [];
	}
    }

    foreach (string server, found_servers_cache, {
	items = add (items, `item(`id(server), server));
    });
    UI::ChangeWidget (`id ("server_address"), `Items, items);
    FoundServersHandle (id, $["ID" : "list_rb"]);
}

/**
 * Store settings of the widget
 * @param id string widget id
 * @param event map event that caused storing process
 */
void FoundServersStore (string id, map event) {
//    if (UI::WidgetExists (`id ("lookup_rb"))
//    	&& ! (boolean)UI::QueryWidget (`id ("lookup_rb"), `Value))
//    {
//    	return;
//    }
    string address = (string)UI::QueryWidget (`id ("server_address"), `Value);
    NtpClient::selected_record["address"] = address;
}

boolean FoundServersValidate (string id, map event) {
//    if (UI::WidgetExists (`id ("lookup_rb"))
//	&& ! (boolean)UI::QueryWidget (`id ("lookup_rb"), `Value))
//    {
//	return true;
//    }
    string server = (string)
	UI::QueryWidget (`id ("server_address"), `Value);
    if (server == nil || server == "")
    {
	UI::SetFocus (`id ("server_address"));
	// popup message
	Popup::Message (_("No server is selected."));
	return false;
    }
    return true;
}

symbol LocalSelectTestHandle (string id, map event) {
    string server = "";
//    if ((boolean)UI::QueryWidget (`id ("lookup_rb"), `Value))
//    {
	server = (string)UI::QueryWidget (`id ("server_address"), `Value);
//    }
//    else
//    {
//	server = (string)UI::QueryWidget (`id (`servers), `Value);
//    }
    NtpClient::TestNtpServer (server, `result_popup);
    return nil;
}

symbol PublicSelectTestHandle (string id, map event) {
    string server = "";
//    if ((boolean)UI::QueryWidget (`id ("lookup_rb"), `Value))
//    {
//	server = (string)UI::QueryWidget (`id ("server_address"), `Value);
//    }
//    else
//    {
	server = (string)UI::QueryWidget (`id (`servers), `Value);
//    }
    NtpClient::TestNtpServer (server, `result_popup);
    return nil;
}

/**
 * Initialize all widgets
 * @return a map of widgets
 */
define map<string,map<string,any> > InitWidgets () ``{
    map<string,any> address = $[
	    "widget" : `textentry,
	    // text entry label
	    "label" : _("A&ddress"),
	    "init" : addressInit,
	    "store" : addressStore,
    ];
    
    return $[
	"complex_button" : $[
	    "widget" : `push_button,
	    // push button label
	    "label" : _("Ad&vanced Configuration"),
	    "help" : HELPS["complex_button"]:"",
	    "handle_events" : [ "complex_button", "never", "boot" ],
	    "handle" : complexButtonHandle,
	],
	"fudge_button" : $[
	    "widget" : `push_button,
	    // push button label
	    "label" : _("&Driver Calibration"),
	    "help" : HELPS["fudge_button"]:"",
	    "handle_events" : [ "fudge_button" ],
	    "handle" : fudgeButtonHandle,
	],
	"interval" : $[
	    "widget" : `intfield,
	    "label" : _("&Interval of the Synchronization in Minutes"),
	    "minimum" : 1,
	    "maximum" : 60,
	    "init"    : intervalInit,
	    "store"   : intervalStore,
	    "help"    : HELPS["start"]:"",
	    "handle"  : timeSyncOrNo,
	],
	"start" : $[
	    "widget" : `radio_buttons,
	    // frame
	    "label" : _("Start NTP Daemon"),
	    "items" : [
		// radio button
		[ "never", _("Only &Manually") ],
		// radio button
		[ "sync", _("&Synchronize without Daemon") ],
		// radio button
		[ "boot", _("Now and On &Boot") ],
	    ],
	    "help" : HELPS["start"]:"",
	    "init" : startInit,
	    "store" : startStore,
	    "handle" : startHandle,
	    "handle_events" : [ "boot", "never","sync" ],
	    "opt" : [`notify],
	],
	"run_chroot" : $[
	    "widget" : `checkbox,
	    // check box
	    "label" : _("Run NTP Daemon in Chroot &Jail"),
	    "init" : chrootInit,
	    "store" : chrootStore,
	    "handle" : ntpEnabledOrDisabled,
	    "help" : HELPS["chroot_environment"]:"",
	],
	"secure"   : $[
	    "widget" : `checkbox,
	    //TRANSLATORS:
	    "label"  : _("&Restrict NTP Service to Configured Servers Only "),
	    "init"   : secureInit,
	    "store"  : secureStore,
	    "help"   : HELPS["secure"]:"",
        ],
	"policy_combo" : $[
	    "widget" : `combobox,
	    "opt"    : [ `notify ],
	    "items"  : [
		// combo box item FIXME usability
		[`nomodify, _("Manual")],
		// combo box item
		[`auto, _("Auto")],
		// combo box item
		[`custom, _("Custom")],
		],
	    "label"  : _("&Runtime Configuration Policy"),
	    "init"   : PolicyInit,
	    "store"  : PolicyStore,
	    "handle" : ntpEnabledOrDisabled,
	    "help"   : HELPS["policy_combo"]:"" // FIXME
	    ],
	"custom_policy" : $[
	    "widget": `textentry,
	    "label" : _("&Custom Policy"),
	    "handle" : ntpEnabledOrDisabled,
	    "help"   : HELPS["custom_policy"]:"" // FIXME
	    ],
	"use_random_servers" : $[
	    "widget" : `checkbox,
	    "opt" : [ `notify ],
	    // check box
	    "label" : _("&Use Random Servers from pool.ntp.org"),
	    "init" : RandomServersInit,
	    "store" : RandomServersStore,
	    "handle" : RandomServersHandle,
	    "help" : HELPS["use_random_servers"]:"",
	],
	"server_address" : union (address, $[
	    // text entry label
	    "label" : _("&Address"),
	    "help" : HELPS["server_address"]:"",
	    "handle" : serverAddressHandle,
	    "validate_type" : `function,
	    "validate_function" : serverAddressValidate,
	    "widget" : `custom,
	    "custom_widget" : `VBox (
		`HBox (
		    `TextEntry (`id ("server_address"),
			`opt(`hstretch),
			// text entry
			_("&Address")
		    ),
		    `VBox (
			`Label (" "),
			// push button
			`MenuButton (`id (`select_server), _("&Select..."), [
			    `item(`id(`select_local), _("Local NTP Server")),
			    `item(`id(`select_public), _("Public NTP Server"))
			])
		    )
		),
		`HBox (
		    `HStretch (),
		    // push button
		    `PushButton (`id (`test_server), _("&Test")),
		    `HStretch ()
		)
	    ),
	]),
	"overview" : $[
	    "widget" : `custom,
	    "custom_widget" : `VBox (
		`Table (`id (`overview), `opt (`notify), `header (
		    // table header
		    _("Synchronization Type"),
		    // table header
		    _("Address"))),
		`HBox (
		    `PushButton (`id (`add), Label::AddButton ()),
		    `PushButton (`id (`edit), Label::EditButton ()),
		    `PushButton (`id (`delete), Label::DeleteButton ()),
		    `HStretch (),
		    // push button
		    `PushButton (`id (`display_log), _("Display &Log..."))
		    // menu button
//		    `MenuButton (`id (`advanced), _("&Advanced..."), [
			// item of menu button
//			`item (`id (`display_log), _("Display &Log...")),
//		    ])
		)
	    ),
	    "help" : HELPS["overview"]:"",
	    "init" : overviewInit,
	    "handle" : overviewHandle,
	],
	"paddress" : union (address, $[
	    "help" : HELPS["paddress"]:"",
	]),
	"bcaddress" : union (address, $[
	    "help" : HELPS["bcaddress"]:"",
	]),
	"bccaddress" : union (address, $[
	    "help" : HELPS["bccaddress"]:"",
	]),
	"clock_type" : $[
	    "widget" : `combobox,
	    // combo box label
	    "label" : _("Clock &Type"),
	    "items" : getClockTypesCombo (),
	    "help" : HELPS["clock_type"]:"",
	    "opt" : [ `notify ],
	    "init" : clockTypeInit,
	    "handle" : clockTypeHandle,
	    "store" : clockTypeStore,
	],
	"unit_number" : $[
	    "widget" : `intfield,
	    // int field
	    "label" : _("Unit &Number"),
	    "help" : HELPS["unit_number"]:"",
	    "minimum" : 0,
	    "maximum" : 3,
	    "init" : unitNumberInit,
	    "store" : unitNumberStore,
	],
	"create_symlink" : $[
	    "widget" : `checkbox,
	    // check box
	    "label" : _("Create &Symlink"),
	    "opt" : [ `notify ],
	    "init" : createSymlinkHandle,
	    "handle_events" : [ "create_symlink" ],
	    "init" : createSymlinkInit,
	    "handle" : createSymlinkHandle,
	    "store" : createSymlinkStore,
	    "help" : " ",
	],
	"device" : $[
	    "widget" : `textentry,
	    // text entry
	    "label" : _("&Device"),
	    "init" : deviceInit,
	    "store" : deviceStore,
	    "help" : HELPS["device"]:"",
	],
	"browse" : $[
	    "widget" : `push_button,
	    "label" : Label::BrowseButton (),
	    "handle_events" : [ "browse" ],
	    "handle" : browseButtonHandle,
	    "help" : " ",
	],
	"options" : $[
	    "widget" : `textentry,
	    // text entry label
	    "label" : Label::Options (),
	    "init" : optionsInit,
	    "store" : optionsStore,
	    "help" : HELPS["options"]:"",
	],
        "ac_options" : $[
	    "widget" : `textentry,
	    "label"  : _("Access Control Options"),
	    "init" : restrictOptionsInit,
	    "store" : restrictOptionsStore,
	    "help": HELPS["restrict"]:"",
        ],
	"peer_types" : $[
	    "widget" : `radio_buttons,
	    "items" : [
		// radio button, NTP relationship type
                ["server", _("&Server")],
                // radio button, NTP relationship type
                ["peer", _("&Peer")],
                // radio button, NTP relationship type
                ["__clock", _("&Radio Clock")],
                // radio button, NTP relationship type
                ["broadcast", _("&Outgoing Broadcast")],
                // radio button, NTP relationship type
                ["broadcastclient", _("&Incoming Broadcast")]
	    ],
	    // frame
	    "label" : _("Type"),
	    "init" : peerTypesInit,
	    "handle" : peerTypesHandle,
	    "help" : HELPS["peer_types"]:"",
	    "hspacing" : 3,
	    "vspacing" : 1,
	],
	"servers_source" : $[
	    "widget" : `radio_buttons,
	    "items" : [
		// radio button
		["lookup_rb", _("Loc&al Network")],
		// radio button
		["list_rb", _("&Public NTP Server")],
	    ],
	    "opt" : [`notify],
	    "init" : ServersSourceInit,
	    // frame label
	    "label" : _("NTP Server Location"),
	    "help" : HELPS["servers_source"]:"",
	],
	"found_servers" : $[
	    "widget" : `custom,
	    "custom_widget" : `HBox (
		`HWeight (3,
		    `ReplacePoint (`id (`server_address_rp),
			`ComboBox (`id ("server_address"),
			    `opt (`editable, `hstretch),
			    // combo box label
			    _("&Address"), [])
		    )
		),
		`HWeight (1,
		    `VBox (
			`Label (" "),
			// push button
			`PushButton (`id (`lookup_server), _("&Lookup"))
		    )
		)
	    ),
	    "init" : FoundServersInit,
	    "handle" : FoundServersHandle,
	    "store" : FoundServersStore,
	    "validate_type" : `function,
	    "validate_function" : FoundServersValidate,
	    "help" : HELPS["found_servers"]:"",
	],
	"servers_list" : $[
	    "widget" : `custom,
	    "custom_widget" : `VBox (
		`ReplacePoint (`id (`country_rp),
		    `ComboBox (`id (`country), `opt (`notify, `hstretch),
			// combo box header
			_("&Country"), [])),
		`ReplacePoint (`id (`servers_rp), `ComboBox (`id (`servers),
		    `opt (`hstretch),
		    // selection box header
		    _("Public NTP &Servers"), []))
	    ),
	    "init" : ServerListInit,
	    "handle" : ServerListHandle,
	    "store" : ServerListStore,
	    "validate_type" : `function,
	    "validate_function" : ServerListValidate,
	    "help" : HELPS["servers_list"]:"",
	],
	"select_test_local" : $[
	    "widget" : `push_button,
	    // push button
	    "label" : _("&Test"),
	    "handle_events" : ["select_test_local"],
	    "handle" : LocalSelectTestHandle,
	    "help" : HELPS["selected_test"]:"",
	],
	"select_test_public" : $[
	    "widget" : `push_button,
	    // push button
	    "label" : _("&Test"),
	    "handle_events" : ["select_test_public"],
	    "handle" : PublicSelectTestHandle,
	    "help" : HELPS["selected_test"]:"",
	],
	"firewall" : CWMFirewallInterfaces::CreateOpenFirewallWidget ($[
	    "services" : NtpClient::firewall_services,
	    "display_details" : true,
	]),
    ];
}



}

ACC SHELL 2018