• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

yast / yast-country / 15159331325

21 May 2025 10:03AM UTC coverage: 42.791% (-0.2%) from 43.025%
15159331325

Pull #328

github

shundhammer
Disabled tests that need an X11 connection and DISPLAY
Pull Request #328: Load required "setxkbmap" package on demand (bsc#1243088)

1484 of 3468 relevant lines covered (42.79%)

12.04 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

7.96
/timezone/src/include/timezone/dialogs.rb
1
# encoding: utf-8
2

3
# ------------------------------------------------------------------------------
4
# Copyright (c) 2012 Novell, Inc. All Rights Reserved.
5
#
6
#
7
# This program is free software; you can redistribute it and/or modify it under
8
# the terms of version 2 of the GNU General Public License as published by the
9
# Free Software Foundation.
10
#
11
# This program is distributed in the hope that it will be useful, but WITHOUT
12
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
13
# FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
14
#
15
# You should have received a copy of the GNU General Public License along with
16
# this program; if not, contact Novell, Inc.
17
#
18
# To contact Novell about this file by physical or electronic mail, you may find
19
# current contact information at www.novell.com.
20
# ------------------------------------------------------------------------------
21

22
# File:
23
#        timezone/dialogs.ycp
24
#
25
# Authors:
26
#        Klaus   Kämpf <kkaempf@suse.de>
27
#        Michael Hager <mike@suse.de>
28
#        Stefan  Hundhammer <sh@suse.de>
29
#        Jiri Suchomel <jsuchome@suse.cz>
30
#
31
# Summary:
32
#        Dialogs for timeone and time configuration.
33
#
34
# $Id$
35

36
module Yast
1✔
37
  module TimezoneDialogsInclude
1✔
38
    def initialize_timezone_dialogs(include_target)
1✔
39
      Yast.import "UI"
14✔
40
      textdomain "country"
14✔
41

42
      Yast.import "Arch"
14✔
43
      Yast.import "Directory"
14✔
44
      Yast.import "GetInstArgs"
14✔
45
      Yast.import "Label"
14✔
46
      Yast.import "Language"
14✔
47
      Yast.import "Mode"
14✔
48
      Yast.import "NetworkService"
14✔
49
      Yast.import "Package"
14✔
50
      Yast.import "Popup"
14✔
51
      Yast.import "ProductFeatures"
14✔
52
      Yast.import "Service"
14✔
53
      Yast.import "Stage"
14✔
54
      Yast.import "Timezone"
14✔
55
      Yast.import "Wizard"
14✔
56

57
      @hwclock_s = @hwclock_s_initial = :none
14✔
58

59
      # if system clock is configured to sync with NTP
60
      @ntp_used = false
14✔
61

62
      # ntp server configured to sync with
63
      @ntp_server = ""
14✔
64

65
      # if packages for NTP configuration are installed
66
      @ntp_installed = false
14✔
67

68
      # when checking for NTP status for first time, check the service status
69
      @ntp_first_time = true
14✔
70
    end
71

72
    # helper function for seting the time related stuff in module and possibly
73
    # adapting current time according to it
74
    def SetTimezone(hwclock, timezone, really, changed_time)
1✔
75
      Builtins.y2milestone(
×
76
        "SetTimezone hw %1, tz %2 really %3 tchanged %4 initial:%5",
77
        hwclock,
78
        timezone,
79
        really,
80
        changed_time,
81
        @hwclock_s_initial
82
      )
83

84
      # simulate the time change
85
      if !really && hwclock != @hwclock_s_initial
×
86
        Timezone.diff = hwclock == :hwclock_utc ? 1 : -1
×
87
      else
88
        Timezone.diff = 0
×
89
      end
90

91
      Builtins.y2milestone("SetTimezone diff %1", Timezone.diff)
×
92

93
      Timezone.hwclock = hwclock == :hwclock_utc ? "-u" : "--localtime"
×
94
      Timezone.Set(timezone, really)
×
95

96
      # Redisplay date/time.
97
      #
98
      UI.ChangeWidget(Id(:date), :Value, Timezone.GetDateTime(really, false))
×
99

100
      nil
×
101
    end
102

103
    def utc_helptext
1✔
104
      # help for time calculation basis:
105
      # hardware clock references local time or UTC?
106
      utc_help = _(
×
107
          "<p>\n" +
108
            "Specify whether your machine is set to local time or UTC in <b>Hardware Clock Set To</b>.\n" +
109
            "Most PCs that also have other operating systems installed (such as Microsoft\n" +
110
            "Windows) use local time.\n" +
111
            "Machines that have only Linux installed are usually\n" +
112
            "set to Universal Time Coordinated (UTC).\n" +
113
            "If the hardware clock is set to UTC, your system can switch from standard time\n" +
114
            "to daylight saving time and back automatically.\n" +
115
            "</p>\n"
116
      )
117

118
      # help text: extra note about localtime
119
      utc_help = utc_help + _(
×
120
          "<p>\n" +
121
            "Note: The internal system clock as used by the Linux kernel must\n" +
122
            "always be in UTC, because this is the reference for the correct localtime\n" +
123
            "in user space. If you are choosing localtime for CMOS clock,\n" +
124
            "check the user manual for background information about side effects.\n" +
125
            "</p>"
126
      )
127
      utc_help
×
128
    end
129

130
    def confirm_local_time
1✔
131
      # warning popup, in case local time is selected (bnc#732769)
132
      Popup.ContinueCancel(_(
×
133
          "\n" +
134
            "You selected local time, but only Linux  seems to be installed on your system.\n" +
135
            "In such case, it is strongly recommended to use UTC, and to click Cancel.\n" +
136
            "\n" +
137
            "If you want to keep local time, you must adjust the CMOS clock twice the year\n" +
138
            "because of Day Light Saving switches. If you miss to adjust the clock, backups may fail,\n" +
139
            "your mail system may drop mail messages, etc.\n" +
140
            "\n" +
141
            "If you use UTC, Linux will adjust the time automatically.\n" +
142
            "\n" +
143
            "Do you want to continue with your selection (local time)?"
144
        )
145
      )
146
    end
147

148
    # handles the complication that the package yast2-ntp-client may not be present
149
    def ntp_call(acall, args)
1✔
150
      args = deep_copy(args)
×
151
      if !@ntp_installed
×
152
        # replace "replace_point" by the widgets
153
        if acall == "ui_init"
×
154
          return false # deselect the RB
×
155
        # the help text
156
        elsif acall == "ui_help_text"
×
157
          return "" # or say "will install"? TODO recompute help text
×
158
        # save settings, return false if dialog should not exit
159
        elsif acall == "ui_try_save"
×
160
          return true # success, exit loop
×
161
        # Service::Enabled. FIXME too smart?
162
        elsif acall == "GetNTPEnabled"
×
163
          return false
×
164
        end
165

166
        # default: do nothing
167
        return nil 
×
168
        #   other API for completeness:
169
        # // before UserInput
170
        # else if (acall == "ui_enable_disable_widgets")
171
        # else if (acall == "SetUseNTP")
172
        # else if (acall == "Write")
173
      end
174

175
      ret = WFM.CallFunction("ntp-client_proposal", [acall, args])
×
176
      deep_copy(ret)
×
177
    end
178

179
    # Dialog for setinge system date and time
180
    # @return true if user changed the time (dialog accepted)
181
    def SetTimeDialog
1✔
182
      ntp_help_text = Convert.to_string(ntp_call("ui_help_text", {}))
×
183

184
      # help text for set time dialog
185
      htext = Ops.add(
×
186
        _(
187
          "<p>The current system time and date are displayed. If required, change them to the correct values manually or use Network Time Protocol (NTP).</p>"
188
        ) +
189
          # help text, cont.
190
          _("<p>Press <b>Accept</b> to save your changes.</p>"),
191
        ntp_help_text
192
      )
193

194
      dt_widgets = false
×
195

196
      hour = ""
×
197
      minute = ""
×
198
      second = ""
×
199
      day = ""
×
200
      month = ""
×
201
      year = ""
×
202

203
      # check current time and show it in the time widgets
204
      show_current_time = lambda do
×
205
        val = Timezone.GetDateTimeMap
×
206
        hour = Ops.get_string(val, "hour", "")
×
207
        minute = Ops.get_string(val, "minute", "")
×
208
        second = Ops.get_string(val, "second", "")
×
209
        day = Ops.get_string(val, "day", "")
×
210
        month = Ops.get_string(val, "month", "")
×
211
        year = Ops.get_string(val, "year", "")
×
212

213
        if dt_widgets
×
214
          UI.ChangeWidget(
×
215
            Id(:date),
216
            :Value,
217
            Builtins.sformat("%1-%2-%3", year, month, day)
218
          )
219
          UI.ChangeWidget(
×
220
            Id(:time),
221
            :Value,
222
            Builtins.sformat("%1:%2:%3", hour, minute, second)
223
          )
224
        else
225
          UI.ChangeWidget(Id(:hour), :Value, hour)
×
226
          UI.ChangeWidget(Id(:minute), :Value, minute)
×
227
          UI.ChangeWidget(Id(:second), :Value, second)
×
228
          UI.ChangeWidget(Id(:day), :Value, day)
×
229
          UI.ChangeWidget(Id(:month), :Value, month)
×
230
          UI.ChangeWidget(Id(:year), :Value, year)
×
231
        end
232

233
        nil
×
234
      end
235

236
      enable_disable_time_widgets = lambda do |enable|
×
237
        UI.ChangeWidget(Id(:change_now), :Enabled, enable)
×
238

239
        enable = enable &&
×
240
          Convert.to_boolean(UI.QueryWidget(Id(:change_now), :Value))
241

242
        if dt_widgets
×
243
          UI.ChangeWidget(Id(:date), :Enabled, enable)
×
244
          UI.ChangeWidget(Id(:time), :Enabled, enable)
×
245
        else
246
          UI.ChangeWidget(Id(:hour), :Enabled, enable)
×
247
          UI.ChangeWidget(Id(:minute), :Enabled, enable)
×
248
          UI.ChangeWidget(Id(:second), :Enabled, enable)
×
249
          UI.ChangeWidget(Id(:day), :Enabled, enable)
×
250
          UI.ChangeWidget(Id(:month), :Enabled, enable)
×
251
          UI.ChangeWidget(Id(:year), :Enabled, enable)
×
252
        end
253

254
        nil
×
255
      end
256

257
      dateterm = VBox(
×
258
        HBox(
259
          HSpacing(1),
260
          # label text, do not change "DD-MM-YYYY"
261
          Left(Label(_("Current Date in DD-MM-YYYY Format")))
262
        ),
263
        HBox(
264
          HSpacing(10),
265
          InputField(Id(:day), Opt(:shrinkable), ""),
266
          HSpacing(),
267
          InputField(Id(:month), Opt(:shrinkable), ""),
268
          HSpacing(),
269
          InputField(Id(:year), Opt(:shrinkable), ""),
270
          HSpacing(30)
271
        )
272
      )
273
      timeterm = VBox(
×
274
        HBox(
275
          HSpacing(1),
276
          # label text, do not change "HH:MM:SS"
277
          Left(Label(_("Current Time in HH:MM:SS Format")))
278
        ),
279
        HBox(
280
          HSpacing(10),
281
          InputField(Id(:hour), Opt(:shrinkable), ""),
282
          HSpacing(),
283
          InputField(Id(:minute), Opt(:shrinkable), ""),
284
          HSpacing(),
285
          InputField(Id(:second), Opt(:shrinkable), ""),
286
          HSpacing(30)
287
        )
288
      )
289
      if UI.HasSpecialWidget(:DateField) && UI.HasSpecialWidget(:TimeField)
×
290
        dateterm = HBox(
×
291
          # label text
292
          DateField(Id(:date), _("Current Date"), "")
293
        )
294
        timeterm = HBox(
×
295
          # label text
296
          TimeField(Id(:time), _("Current Time"), "")
297
        )
298
        dt_widgets = true
×
299
      end
300

301

302
      cont = VBox(
×
303
          VSpacing(UI.TextMode ? 1 : 0),
×
304
          HBox(
305
          HWeight(1, VBox()),
306
          HWeight(
307
            6,
308
            RadioButtonGroup(
309
              Id(:rb),
310
              VBox(
311
                # radio button label (= how to setup time)
312
                Left(RadioButton(Id(:manual), Opt(:notify), _("Manually"))),
313
                VSpacing(0.5),
314
                HBox(
315
                  HSpacing(3),
316
                  VBox(
317
                    Left(timeterm),
318
                    VSpacing(UI.TextMode ? 0 : 1),
×
319
                    Left(dateterm),
320
                    VSpacing(),
321
                    HBox(
322
                      HSpacing(0.5),
323
                      Left(
324
                        # check box label
325
                        CheckBox(
326
                          Id(:change_now),
327
                          Opt(:notify),
328
                          _("Change the Time Now"),
329
                          true
330
                        )
331
                      )
332
                    )
333
                  )
334
                ),
335
                VSpacing(1),
336
                Left(
337
                  RadioButton(
338
                    Id(:ntp),
339
                    Opt(:notify),
340
                    # radio button label
341
                    _("Synchronize with NTP Server"),
342
                    false
343
                  )
344
                ),
345
                ReplacePoint(Id(:rp), Empty())
346
              )
347
            )
348
          ),
349
          HWeight(1, VBox())
350
        ),
351
        VSpacing(UI.TextMode ? 0 : 2),
×
352
      )
353

354
      Wizard.OpenAcceptDialog
×
355
      # TODO replace help text after ntp_installed, is.
356
      Wizard.SetContents(_("Change Date and Time"), cont, htext, true, true)
×
357

358
      Wizard.SetDesktopTitleAndIcon("org.opensuse.yast.Timezone") if Mode.normal
×
359

360
      show_current_time.call
×
361

362
      ntp_rb = Convert.to_boolean(
×
363
        ntp_call(
364
          "ui_init",
365
          {
366
            "replace_point" => Id(:rp),
367
            "country"       => Language.GetLanguageCountry,
368
            "first_time"    => @ntp_first_time
369
          }
370
        )
371
      )
372
      @ntp_first_time = false
×
373
      UI.ChangeWidget(Id(:rb), :CurrentButton, ntp_rb ? :ntp : :manual)
×
374

375
      if !dt_widgets
×
376
        Builtins.foreach([:hour, :minute, :second, :day, :month, :year]) do |widget|
×
377
          UI.ChangeWidget(Id(widget), :ValidChars, "0123456789")
×
378
          UI.ChangeWidget(Id(widget), :InputMaxLength, widget == :year ? 4 : 2)
×
379
        end
380
      end
381

382
      ret = nil
×
383
      begin
×
384
        ntp_call("ui_enable_disable_widgets", { "enabled" => ntp_rb })
×
385
        enable_disable_time_widgets.call(!ntp_rb)
×
386

387
        ret = UI.UserInput
×
388
        Builtins.y2debug("UserInput ret:%1", ret)
×
389

390
        ntp_handled = Convert.to_symbol(ntp_call("ui_handle", { "ui" => ret }))
×
391
        ret = ntp_handled if ntp_handled != nil
×
392
        show_current_time.call if ret == :redraw
×
393

394
        if ret == :ntp || ret == :manual
×
395
          ntp_rb = ret == :ntp
×
396
          # need to install it first?
397
          if ntp_rb && !Stage.initial && !@ntp_installed
×
398
            @ntp_installed = Package.InstallAll(["yast2-ntp-client", "chrony"])
×
399
            # succeeded? create UI, otherwise revert the click
400
            if !@ntp_installed
×
401
              ntp_rb = false
×
402
              UI.ChangeWidget(Id(:rb), :CurrentButton, :manual)
×
403
            else
404
              # ignore retval, user clicked to use ntp
405
              ntp_call(
×
406
                "ui_init",
407
                {
408
                  "replace_point" => Id(:rp),
409
                  "country"       => Language.GetLanguageCountry,
410
                  "first_time"    => false
411
                }
412
              )
413
            end
414
          end
415
        end
416

417
        if ret == :accept && ntp_rb
×
418
          # before the sync, save the time zone (bnc#467318)
419
          Timezone.Set(
×
420
            Timezone.timezone,
421
            Stage.initial && !Mode.live_installation
422
          )
423
          # true: go on, exit; false: loop on
424
          ntp_handled2 = Convert.to_boolean(ntp_call("ui_try_save", {}))
×
425
          if !ntp_handled2
×
426
            ret = :retry
×
427
          else
428
            # `ntp_address is constructed by ntp-client_proposal.ycp... :-(
429
            @ntp_server = Convert.to_string(
×
430
              UI.QueryWidget(Id(:ntp_address), :Value)
431
            )
432
            # after sync, show real time in the widget
433
            Timezone.diff = 0
×
434
          end
435
        end
436
        if ret == :accept && !ntp_rb &&
×
437
            UI.QueryWidget(Id(:change_now), :Value) == true
438
          if dt_widgets
×
439
            datel = Builtins.splitstring(
×
440
              Convert.to_string(UI.QueryWidget(Id(:date), :Value)),
441
              "-"
442
            )
443
            year = Ops.get_string(datel, 0, "")
×
444
            month = Ops.get_string(datel, 1, "")
×
445
            day = Ops.get_string(datel, 2, "")
×
446
            timel = Builtins.splitstring(
×
447
              Convert.to_string(UI.QueryWidget(Id(:time), :Value)),
448
              ":"
449
            )
450
            hour = Ops.get_string(timel, 0, "")
×
451
            minute = Ops.get_string(timel, 1, "")
×
452
            second = Ops.get_string(timel, 2, "")
×
453
          else
454
            hour = Convert.to_string(UI.QueryWidget(Id(:hour), :Value))
×
455
            minute = Convert.to_string(UI.QueryWidget(Id(:minute), :Value))
×
456
            second = Convert.to_string(UI.QueryWidget(Id(:second), :Value))
×
457
            day = Convert.to_string(UI.QueryWidget(Id(:day), :Value))
×
458
            month = Convert.to_string(UI.QueryWidget(Id(:month), :Value))
×
459
            year = Convert.to_string(UI.QueryWidget(Id(:year), :Value))
×
460
          end
461
          if !Timezone.CheckTime(hour, minute, second)
×
462
            tmp = Builtins.sformat("%1:%2:%3", hour, minute, second)
×
463
            # popup text, %1 is entered value
464
            tmp = Builtins.sformat(
×
465
              _("Invalid time (HH:MM:SS) %1.\nEnter the correct time.\n"),
466
              tmp
467
            )
468
            Popup.Error(tmp)
×
469
            ret = :retry
×
470
          elsif !Timezone.CheckDate(day, month, year)
×
471
            tmp = Builtins.sformat("%1-%2-%3", day, month, year)
×
472
            # popup text, %1 is entered value
473
            tmp = Builtins.sformat(
×
474
              _("Invalid date (DD-MM-YYYY) %1.\nEnter the correct date.\n"),
475
              tmp
476
            )
477
            Popup.Error(tmp)
×
478
            ret = :retry
×
479
          else
480
            # in case of local time, we need to call mkinitrd (after setting timezone)
481
            if Timezone.hwclock == "--localtime" && !Stage.initial
×
482
              Timezone.Set(Timezone.timezone, true)
×
483
              Timezone.call_mkinitrd = true
×
484
            end
485

486
            Timezone.SetTime(year, month, day, hour, minute, second)
×
487
          end
488
        end
489
      end until ret == :accept || ret == :cancel
490

491
      if ret == :accept
×
492
        # new system time from ntpdate must be saved to hw clock
493
        Timezone.SystemTime2HWClock if ntp_rb
×
494
        # remember ui
495
        ntp_call("SetUseNTP", { "ntp_used" => ntp_rb })
×
496
        @ntp_used = ntp_rb
×
497
      end
498

499
      Wizard.CloseDialog
×
500
      ret == :accept
×
501
    end
502

503
    # Main dialog for time zone configuration
504
    # @param [Hash] args arguments passwd from the called (back/next buttons etc.)
505
    def TimezoneDialog(args)
1✔
506
      args = deep_copy(args)
×
507
      first_run = Ops.get_string(args, "first_run", "no") == "yes"
×
508
      # inst_timezone as a part of installation sequence
509
      if first_run && Stage.initial
×
510
        Timezone.hwclock = "--localtime" if Timezone.ProposeLocaltime
×
511
      end
512

513

514
      # get current timezone and clock setting
515
      changed_time = false
×
516
      timezone = Timezone.timezone
×
517
      timezone_old = timezone
×
518
      timezone_initial = timezone
×
519
      hwclock = Timezone.hwclock
×
520

521
      Builtins.y2milestone("timezone_old %1", timezone_old)
×
522

523
      timezone = Timezone.UpdateTimezone(timezone)
×
524

525
      # Initially set the current timezone to establish a consistent state.
526
      sel = Timezone.Set(timezone, Stage.initial && !Mode.live_installation)
×
527

528
      utc_only = Timezone.utc_only
×
529
      Builtins.y2milestone("utc_only %1", utc_only)
×
530

531
      Timezone.PushVal
×
532

533
      # TRANSLATORS: Button label
534
      other_settings_label = _("Other &Settings...")
×
535

536
      # "On a mainframe it is impossible for the user to change the hardware clock.
537
      # So you can only specify the timezone." (Ihno)
538
      settime = ((!Arch.s390 && !Mode.config) ?
×
539
        PushButton(Id(:settime), other_settings_label) : Empty()
×
540
      )
541

542
      textmode = Language.GetTextMode
×
543

544
      timezone_selector = false
×
545

546
      zonemap = Timezone.get_zonemap
×
547

548
      # map of zones conversions
549
      yast2zonetab = deep_copy(Timezone.yast2zonetab)
×
550

551
      # map of timezone -> translated label to be passed to TimezoneSelector
552
      zones = {}
×
553

554
      # cache the zonemap with the order sorted according to current locale
555
      sorted_zonemap = {}
×
556

557
      Builtins.foreach(zonemap) do |region|
×
558
        Builtins.foreach(Ops.get_map(region, "entries", {})) do |key, name|
×
559
          if !Builtins.haskey(yast2zonetab, key)
×
560
            Ops.set(zones, Ops.get(yast2zonetab, key, key), name)
×
561
          end
562
        end
563
      end
564

565
      @ntp_installed = Stage.initial || Package.Installed("yast2-ntp-client")
×
566

567

568
      # read NTP status
569
      if first_run && NetworkService.isNetworkRunning && !Mode.live_installation &&
×
570
          !GetInstArgs.going_back &&
571
          ProductFeatures.GetBooleanFeature("globals", "default_ntp_setup") == true
572
        # true by default (fate#303520)
573
        @ntp_used = true
×
574
        # configure NTP client
575
        # to prevent misusage of ntp.org we need to distinguish opensuse and SLE usage
576
        require "y2network/ntp_server"
×
577
        @ntp_server = Y2Network::NtpServer.default_servers.map(&:hostname).sample
×
578
        # Dot not select a dhcp ntp server by default but add it to the offered
579
        # list (fate#323454). Add only one server as it is added as a pool (bsc#1188980)
580
        servers = ntp_call("dhcp_ntp_servers", {}).concat([@ntp_server].compact).uniq
×
581
        argmap = {
582
          "server"       => @ntp_server,
×
583
          # FIXME ntp-client_proposal doesn't understand 'servers' yet
584
          "servers"      => servers
585
        }
586

587
        rv = Convert.to_symbol(ntp_call("Write", argmap))
×
588
        if rv == :invalid_hostname
×
589
          Builtins.y2warning("Invalid NTP server hostname %1", @ntp_server)
×
590
          @ntp_used = false
×
591
        else
592
          Timezone.SystemTime2HWClock
×
593
          Builtins.y2milestone("proposing NTP server %1", @ntp_server)
×
594
          ntp_call("SetUseNTP", { "ntp_used" => @ntp_used })
×
595
        end
596
      elsif Stage.initial
×
597
        # from installation summaru
598
        @ntp_used = Timezone.ntp_used
×
599
      elsif @ntp_installed
×
600
        @ntp_used = Convert.to_boolean(ntp_call("GetNTPEnabled", {}))
×
601
        @ntp_used = @ntp_used == true # nil->false, just in case of parse error
×
602
      end
603

604
      time_frame_label =
605
        # frame label
606
        @ntp_used ?
×
607
          _("Date and Time (NTP is configured)") :
×
608
          # frame label
609
          _("Date and Time")
×
610

611
      # Read system date and time.
612
      date = Timezone.GetDateTime(true, false)
×
613

614
      @hwclock_s = hwclock == "-u" ? :hwclock_utc : :hwclock_localtime
×
615
      hwclock_s_old = @hwclock_s
×
616
      @hwclock_s_initial = @hwclock_s
×
617

618
      timezoneterm = HBox()
×
619

620
      hwclock_term = VBox(
×
621
        CheckBox(
622
          Id(:hwclock),
623
          Opt(:notify),
624
          # check box label
625
          _("&Hardware Clock Set to UTC"),
626
          @hwclock_s == :hwclock_utc
627
        ),
628
        textmode ? Label("") : Empty()
×
629
      )
630

631
      if UI.HasSpecialWidget(:TimezoneSelector) == true
×
632
        timezone_selector = true
×
633
        worldmap = Ops.add(Directory.themedir, "/current/worldmap/worldmap.jpg")
×
634

635
        # bsc#946955 Translation doesn't fit in some languages
636
        # Reserved space needs to be allocated proportionally to the text length
637
        other_settings_hweight = other_settings_label.size
×
638
        free_space_hweight = 10
×
639
        entries_hweight = 25
×
640

641
        timezoneterm = VBox(
×
642
          TimezoneSelector(Id(:timezonemap), Opt(:notify), worldmap, zones),
643
          HBox(
644
            HWeight(free_space_hweight, HStretch()),
645
            HWeight(
646
              entries_hweight,
647
              ComboBox(
648
                Id(:region),
649
                Opt(:notify),
650
                # label text
651
                _("&Region"),
652
                Timezone.Region
653
              )
654
            ),
655
            HSpacing(),
656
            HWeight(
657
              entries_hweight,
658
              ComboBox(Id(:timezone), Opt(:notify), _("Time &Zone"))
659
            ),
660
            HSpacing(),
661
            HWeight(other_settings_hweight, HStretch())
662
          ),
663
          HBox(
664
            HWeight(free_space_hweight, HStretch()),
665
            HWeight(entries_hweight, Left(
666
              utc_only ? Label(" ") : hwclock_term
×
667
            )),
668
            HSpacing(),
669
            HWeight(entries_hweight, HBox(
670
              Label(_("Date and Time:")),
671
              Label(Id(:date), date),
672
              HStretch()
673
            )),
674
            HSpacing(),
675
            HWeight(other_settings_hweight, Right(settime))
676
          )
677
        )
678
      else
679
        timezoneterm = VBox(
×
680
          HBox(
681
            SelectionBox(
682
              Id(:region),
683
              Opt(:notify, :immediate),
684
              # label text
685
              _("&Region"),
686
              Timezone.Region
687
            ),
688
            HSpacing(),
689
            SelectionBox(Id(:timezone), Opt(:notify), _("Time &Zone"))
690
          ),
691
          HBox(
692
            HSpacing(),
693
            VBox(
694
              Left(Label(_("Date and Time"))),
695
              Left(Label(Id(:date), date))
696
            ),
697
            HSpacing(),
698
            VBox(
699
              Right(utc_only ? Label(" ") : hwclock_term),
×
700
              Right(settime)
701
            ),
702
            HSpacing()
703
          )
704
        )
705
      end
706

707
      contents = MarginBox(
×
708
        term(:leftMargin, 2),
709
        term(:rightMargin, 2),
710
        term(:topMargin, 0),
711
        term(:bottomMargin, 0.2),
712
        timezoneterm
713
      )
714
      # cache for lists with timezone items
715
      get_timezones_for_region = lambda do |region, zone|
×
716
        if !Builtins.haskey(sorted_zonemap, region)
×
717
          reg_list = Builtins.maplist(
×
718
            Ops.get_map(zonemap, [region, "entries"], {})
719
          ) { |key, name| [name, key] }
×
720

721
          reg_list = Builtins.sort(
×
722
            Convert.convert(reg_list, :from => "list", :to => "list <list>")
723
          ) do |a, b|
724
            # bnc#385172: must use < instead of <=, the following means:
725
            # strcoll(x) <= strcoll(y) && strcoll(x) != strcoll(y)
726
            lsorted = Builtins.lsort(
×
727
              [Ops.get_string(a, 0, ""), Ops.get_string(b, 0, "")]
728
            )
729
            lsorted_r = Builtins.lsort(
×
730
              [Ops.get_string(b, 0, ""), Ops.get_string(a, 0, "")]
731
            )
732
            Ops.get_string(lsorted, 0, "") == Ops.get_string(a, 0, "") &&
×
733
              lsorted == lsorted_r
734
          end
735
          Ops.set(sorted_zonemap, region, reg_list)
×
736
        end
737
        Builtins.maplist(Ops.get_list(sorted_zonemap, region, [])) do |entry|
×
738
          Item(
×
739
            Id(Ops.get_string(entry, 1, "")),
740
            Ops.get_string(entry, 0, ""),
741
            Ops.get_string(entry, 1, "") == zone
742
          )
743
        end
744
      end
745
      # region was seleced: show the correct list of timezones
746
      show_selected_region = lambda do |sel2, zone|
×
747
        if timezone_selector
×
748
          UI.ChangeWidget(Id(:region), :Value, sel2)
×
749
        else
750
          UI.ChangeWidget(Id(:region), :CurrentItem, sel2)
×
751
        end
752

753
        UI.ChangeWidget(
×
754
          Id(:timezone),
755
          :Items,
756
          get_timezones_for_region.call(sel2, zone)
757
        )
758

759
        nil
×
760
      end
761
      # which region is selected?
762
      selected_region = lambda do
×
763
        timezone_selector ?
×
764
          Convert.to_integer(UI.QueryWidget(Id(:region), :Value)) :
×
765
          Convert.to_integer(UI.QueryWidget(Id(:region), :CurrentItem))
×
766
      end
767
      # which timezone is selected?
768
      selected_timezone = lambda do
×
769
        timezone_selector ?
×
770
          Convert.to_string(UI.QueryWidget(Id(:timezone), :Value)) :
×
771
          Convert.to_string(UI.QueryWidget(Id(:timezone), :CurrentItem))
×
772
      end
773

774
      # for given timezone (selected in map), find out to which region it belongs
775
      get_region_for_timezone = lambda do |current, zone|
×
776
        # first check if it is not in current region
777
        if Builtins.haskey(Ops.get_map(zonemap, [current, "entries"], {}), zone)
×
778
          return current
×
779
        end
780
        reg = 0
×
781
        Builtins.foreach(zonemap) do |region|
×
782
          if Builtins.haskey(Ops.get_map(region, "entries", {}), zone)
×
783
            raise Break
×
784
          end
785
          reg = Ops.add(reg, 1)
×
786
        end
787
        reg
×
788
      end
789

790
      # help for timezone screen
791
      help_text = _("\n<p><b><big>Time Zone and Clock Settings</big></b></p>") +
×
792
        # help for timezone screen
793
        _(
794
          "<p>\n" +
795
            "To select the time zone to use in your system, first select the <b>Region</b>.\n" +
796
            "In <b>Time Zone</b>, then select the appropriate time zone, country, or \n" +
797
            "region from those available.\n" +
798
            "</p>\n"
799
        )
800

801
      if !utc_only
×
802
        help_text = help_text + utc_helptext
×
803
      end
804

805

806
      if !Arch.s390 && !Mode.config
×
807
        # general help trailer
808
        help_text = Ops.add(
×
809
          help_text,
810
          _(
811
            "<p>\n" +
812
              "If the current time is not correct, use <b>Change</b> to adjust it.\n" +
813
              "</p>"
814
          )
815
        )
816
      end
817

818
      # Screen title for timezone screen
819
      Wizard.SetContents(
×
820
        _("Clock and Time Zone"),
821
        contents,
822
        help_text,
823
        Ops.get_boolean(args, "enable_back", true),
824
        Ops.get_boolean(args, "enable_next", true)
825
      )
826

827
      if Stage.initial || Stage.firstboot
×
828
        Wizard.SetTitleIcon("yast-timezone")
×
829
      else
830
        Wizard.SetDesktopTitleAndIcon("org.opensuse.yast.Timezone")
×
831
      end
832

833
      show_selected_region.call(sel, timezone)
×
834
      if timezone_selector
×
835
        UI.ChangeWidget(
×
836
          Id(:timezonemap),
837
          :CurrentItem,
838
          Ops.get(yast2zonetab, timezone, timezone)
839
        )
840
      end
841

842
      UI.SetFocus(Id(:region))
×
843

844
      ret = nil
×
845
      begin
×
846
        ret = Convert.to_symbol(Wizard.UserInput)
×
847

848
        Builtins.y2debug("ret %1", ret)
×
849

850
        ret = :next if ret == :ok
×
851

852
        break if !Mode.config && ret == :abort && Popup.ConfirmAbort(:painless)
×
853

854
        if ret == :next
×
855
          # Get current settings.
856
          # UTC vs. localtime, only if needed
857
          #
858
          @hwclock_s = :hwclock_utc
×
859
          if !utc_only
×
860
            @hwclock_s = UI.QueryWidget(Id(:hwclock), :Value) ? :hwclock_utc : :hwclock_localtime
×
861

862
            vmware = SCR.Read(path(".probe.is_vmware"))
×
863
            if !Timezone.windows_partition && !vmware && @hwclock_s == :hwclock_localtime
×
864
              if ! confirm_local_time
×
865
                ret = :not_next
×
866
                next
×
867
              end
868
            end
869
          end
870
        end
871

872
        if ret == :hwclock
×
873
          # Keep internal state in sync (Timezone.hwclock <-> @hwclock_s) in
874
          # case user enters SetTimeDialog() and sets the time (bsc#1087228).
875

876
          @hwclock_s = UI.QueryWidget(Id(:hwclock), :Value) ? :hwclock_utc : :hwclock_localtime
×
877
          SetTimezone(@hwclock_s, timezone, false, false)
×
878

879
          Builtins.y2milestone("hwclock changed to: %1 (%2), diff: %3", @hwclock_s, Timezone.hwclock, Timezone.diff)
×
880

881
          # restart input loop
882
          ret = :again
×
883
          next
×
884
        end
885

886
        if ret == :region
×
887
          num = selected_region.call
×
888
          next if num == sel
×
889
          show_selected_region.call(num, "")
×
890
          tz = selected_timezone.call
×
891
          if tz != timezone
×
892
            timezone = tz
×
893
            changed_time = true if timezone != timezone_old
×
894
            timezone_old = timezone
×
895
            SetTimezone(@hwclock_s, timezone, false, changed_time)
×
896
          end
897
          if timezone_selector
×
898
            UI.ChangeWidget(Id(:timezonemap), :CurrentItem, timezone)
×
899
          end
900
          sel = num
×
901
        elsif ret == :settime
×
902
          # timezone was not adapted in ncurses (bnc#617861)
903
          if textmode
×
904
            tz = selected_timezone.call
×
905
            if tz != timezone
×
906
              timezone = tz
×
907
              changed_time = true if timezone != timezone_old
×
908
              timezone_old = timezone
×
909
              SetTimezone(@hwclock_s, timezone, false, changed_time)
×
910
            end
911
          end
912
          if SetTimeDialog()
×
913
            # Time has just been set in the system. Reset internal state as we're definitely in sync atm.
914
            Timezone.diff = 0
×
915
            @hwclock_s_initial = @hwclock_s
×
916

917
            UI.ChangeWidget(
×
918
              Id(:date),
919
              :Value,
920
              Timezone.GetDateTime(false, false)
921
            )
922
            changed_time = true
×
923
            # adapt frame label, NTP status may be changed
924
            time_frame_label =
925
              # frame label
926
              @ntp_used ?
×
927
                _("Date and Time (NTP is configured)") :
×
928
                # frame label
929
                _("Date and Time")
×
930
            UI.ChangeWidget(Id(:time_fr), :Label, time_frame_label)
×
931
          end
932
        elsif ret == :next || ret == :timezone || ret == :timezonemap
×
933
          if ret == :timezonemap
×
934
            timezone = Convert.to_string(
×
935
              UI.QueryWidget(Id(:timezonemap), :Value)
936
            )
937

938
            reg = get_region_for_timezone.call(sel, timezone)
×
939
            if reg == sel
×
940
              UI.ChangeWidget(Id(:timezone), :Value, timezone)
×
941
            else
942
              sel = reg
×
943
              show_selected_region.call(sel, timezone)
×
944
            end
945
          else
946
            timezone = selected_timezone.call
×
947
          end
948
          if ret == :timezone
×
949
            sel = selected_region.call
×
950
            if timezone_selector
×
951
              UI.ChangeWidget(
×
952
                Id(:timezonemap),
953
                :Value,
954
                Ops.get(yast2zonetab, timezone, timezone)
955
              )
956
            end
957
          end
958

959
          if timezone == nil || Builtins.size(timezone) == 0
×
960
            # popup text
961
            Popup.Error(_("Select a valid time zone."))
×
962
            ret = :again
×
963
            timezone = timezone_old
×
964
          end
965

966
          Builtins.y2milestone("timezone %1 ret %2, hwclock %3 -> %4", timezone, ret, hwclock_s_old, @hwclock_s)
×
967

968
          if timezone != timezone_old || @hwclock_s != hwclock_s_old ||
×
969
              ret == :next
970
            changed_time = true if timezone != timezone_old
×
971
            timezone_old = timezone
×
972
            hwclock_s_old = @hwclock_s
×
973
            SetTimezone(@hwclock_s, timezone, ret == :next && (changed_time || @hwclock_s != @hwclock_s_initial), changed_time)
×
974
          end
975

976
          if ret == :next
×
977
            # User wants to keep his changes.
978
            # Set user_decision flag in timezone module.
979
            #
980
            Timezone.user_decision = true
×
981
            Timezone.user_hwclock = true
×
982
            Timezone.ntp_used = @ntp_used
×
983
            # See bnc#638185c5: refresh_initrd should be called if HWCLOCK is changed (--localtime <-> --utc) and/or
984
            # if --localtime is set and TIMEZONE will be changed.
985
            if @hwclock_s != @hwclock_s_initial ||
×
986
                @hwclock_s == :hwclock_localtime && timezone != timezone_initial
987
              Timezone.call_mkinitrd = true
×
988
            end
989

990
            # save settings (update /etc/adjtime)
991
            Timezone.Save
×
992

993
            if @ntp_used && @ntp_server != ""
×
994
              # save NTP client settings now
995
              ntp_call(
×
996
                "Write",
997
                { "server" => @ntp_server, "write_only" => true }
998
              )
999
            end
1000
          end
1001
        end
1002
      end until ret == :next || ret == :back || ret == :cancel
1003

1004
      Timezone.PopVal if ret != :next
×
1005
      ret
×
1006
    end
1007
  end
1008
end
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc