[PATCH 2/2] Make the date format locale-dependent in our GUI (#1044233)
Vratislav Podzimek
vpodzime at redhat.com
Tue Oct 7 16:32:37 UTC 2014
The y/m/d order varies among locales and so do the delimiters between the date
fields.
Signed-off-by: Vratislav Podzimek <vpodzime at redhat.com>
---
pyanaconda/ui/gui/spokes/datetime_spoke.glade | 159 ++++++++++----------------
pyanaconda/ui/gui/spokes/datetime_spoke.py | 102 +++++++++++------
2 files changed, 129 insertions(+), 132 deletions(-)
diff --git a/pyanaconda/ui/gui/spokes/datetime_spoke.glade b/pyanaconda/ui/gui/spokes/datetime_spoke.glade
index 5a390ae..a9d8933 100644
--- a/pyanaconda/ui/gui/spokes/datetime_spoke.glade
+++ b/pyanaconda/ui/gui/spokes/datetime_spoke.glade
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
-<!-- Generated with glade 3.18.1 -->
+<!-- Generated with glade 3.18.3 -->
<interface>
<requires lib="gtk+" version="3.2"/>
<requires lib="AnacondaWidgets" version="1.0"/>
@@ -33,8 +33,10 @@
</object>
<object class="GtkListStore" id="days">
<columns>
- <!-- column-name number -->
+ <!-- column-name idx -->
<column type="guint"/>
+ <!-- column-name day -->
+ <column type="gchararray"/>
</columns>
</object>
<object class="GtkTreeModelFilter" id="daysFilter">
@@ -57,6 +59,8 @@
</object>
<object class="GtkListStore" id="months">
<columns>
+ <!-- column-name idx -->
+ <column type="guint"/>
<!-- column-name name -->
<column type="gchararray"/>
</columns>
@@ -95,6 +99,46 @@
<property name="can_focus">False</property>
<property name="orientation">vertical</property>
<property name="spacing">6</property>
+ <child internal-child="action_area">
+ <object class="GtkButtonBox" id="dialog-action_area1">
+ <property name="can_focus">False</property>
+ <property name="layout_style">end</property>
+ <child>
+ <object class="GtkButton" id="cancelButton">
+ <property name="label" translatable="yes" context="GUI|Date and Time|NTP">_Cancel</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="use_underline">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButton" id="okButton">
+ <property name="label" translatable="yes" context="GUI|Date and Time|NTP">_OK</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="use_underline">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="pack_type">end</property>
+ <property name="position">4</property>
+ </packing>
+ </child>
<child>
<object class="GtkLabel" id="configHeadingLabel">
<property name="visible">True</property>
@@ -221,46 +265,6 @@
<property name="position">2</property>
</packing>
</child>
- <child internal-child="action_area">
- <object class="GtkButtonBox" id="dialog-action_area1">
- <property name="can_focus">False</property>
- <property name="layout_style">end</property>
- <child>
- <object class="GtkButton" id="cancelButton">
- <property name="label" translatable="yes" context="GUI|Date and Time|NTP">_Cancel</property>
- <property name="visible">True</property>
- <property name="can_focus">True</property>
- <property name="receives_default">True</property>
- <property name="use_underline">True</property>
- </object>
- <packing>
- <property name="expand">False</property>
- <property name="fill">True</property>
- <property name="position">0</property>
- </packing>
- </child>
- <child>
- <object class="GtkButton" id="okButton">
- <property name="label" translatable="yes" context="GUI|Date and Time|NTP">_OK</property>
- <property name="visible">True</property>
- <property name="can_focus">True</property>
- <property name="receives_default">True</property>
- <property name="use_underline">True</property>
- </object>
- <packing>
- <property name="expand">False</property>
- <property name="fill">True</property>
- <property name="position">1</property>
- </packing>
- </child>
- </object>
- <packing>
- <property name="expand">False</property>
- <property name="fill">True</property>
- <property name="pack_type">end</property>
- <property name="position">4</property>
- </packing>
- </child>
</object>
</child>
<action-widgets>
@@ -288,12 +292,6 @@
<property name="can_focus">False</property>
<property name="icon_name">go-up-symbolic</property>
</object>
- <object class="GtkListStore" id="years">
- <columns>
- <!-- column-name number -->
- <column type="guint"/>
- </columns>
- </object>
<object class="AnacondaSpokeWindow" id="datetimeWindow">
<property name="can_focus">False</property>
<property name="window_name" translatable="yes">DATE & TIME</property>
@@ -818,66 +816,19 @@
<property name="yscale">0.20000000298023224</property>
<property name="right_padding">24</property>
<child>
- <object class="GtkBox" id="box5">
+ <object class="GtkBox" id="dateBox">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="halign">end</property>
+ <property name="spacing">3</property>
<child>
- <object class="GtkComboBox" id="monthCombobox">
- <property name="visible">True</property>
- <property name="can_focus">False</property>
- <property name="model">months</property>
- <signal name="changed" handler="on_month_changed" swapped="no"/>
- <child>
- <object class="GtkCellRendererText" id="monthsComboRenderer"/>
- <attributes>
- <attribute name="text">0</attribute>
- </attributes>
- </child>
- </object>
- <packing>
- <property name="expand">False</property>
- <property name="fill">True</property>
- <property name="position">0</property>
- </packing>
+ <placeholder/>
</child>
<child>
- <object class="GtkComboBox" id="dayCombobox">
- <property name="visible">True</property>
- <property name="can_focus">False</property>
- <property name="model">daysFilter</property>
- <signal name="changed" handler="on_day_changed" swapped="no"/>
- <child>
- <object class="GtkCellRendererText" id="daysComboRenderer"/>
- <attributes>
- <attribute name="text">0</attribute>
- </attributes>
- </child>
- </object>
- <packing>
- <property name="expand">False</property>
- <property name="fill">True</property>
- <property name="position">1</property>
- </packing>
+ <placeholder/>
</child>
<child>
- <object class="GtkComboBox" id="yearCombobox">
- <property name="visible">True</property>
- <property name="can_focus">False</property>
- <property name="model">years</property>
- <signal name="changed" handler="on_year_changed" swapped="no"/>
- <child>
- <object class="GtkCellRendererText" id="yearsComboRenderer"/>
- <attributes>
- <attribute name="text">0</attribute>
- </attributes>
- </child>
- </object>
- <packing>
- <property name="expand">False</property>
- <property name="fill">True</property>
- <property name="position">2</property>
- </packing>
+ <placeholder/>
</child>
</object>
</child>
@@ -929,4 +880,12 @@
</object>
</child>
</object>
+ <object class="GtkListStore" id="years">
+ <columns>
+ <!-- column-name idx -->
+ <column type="guint"/>
+ <!-- column-name year -->
+ <column type="gchararray"/>
+ </columns>
+ </object>
</interface>
diff --git a/pyanaconda/ui/gui/spokes/datetime_spoke.py b/pyanaconda/ui/gui/spokes/datetime_spoke.py
index 69000f8..6abc43b 100644
--- a/pyanaconda/ui/gui/spokes/datetime_spoke.py
+++ b/pyanaconda/ui/gui/spokes/datetime_spoke.py
@@ -22,7 +22,7 @@
import logging
log = logging.getLogger("anaconda")
-from gi.repository import GLib, Gdk, TimezoneMap
+from gi.repository import GLib, Gdk, Gtk, TimezoneMap
from pyanaconda.ui.communication import hubQ
from pyanaconda.ui.common import FirstbootSpokeMixIn
@@ -35,7 +35,7 @@ from pyanaconda.ui.helpers import InputCheck
from pyanaconda.i18n import _, CN_
from pyanaconda.timezone import NTP_SERVICE, get_all_regions_and_timezones, is_valid_timezone
-from pyanaconda.localization import get_xlated_timezone
+from pyanaconda.localization import get_xlated_timezone, resolve_date_format
from pyanaconda import iutil
from pyanaconda import isys
from pyanaconda import network
@@ -113,6 +113,27 @@ def _compare_cities(city_xlated1, city_xlated2):
# compare prefixes
return locale_mod.strcoll(prefix1, prefix2)
+def _new_date_field_box(store):
+ """
+ Creates new date field box (a combobox and a label in a horizontal box) for
+ a given store.
+
+ """
+
+ box = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL)
+ suffix_label = Gtk.Label()
+ renderer = Gtk.CellRendererText()
+ combo = Gtk.ComboBox(model=store)
+ combo.pack_start(renderer, False)
+
+ # idx is column 0, string we want to show is 1
+ combo.add_attribute(renderer, "text", 1)
+
+ box.pack_start(combo, False, False, 0)
+ box.pack_start(suffix_label, False, False, 0)
+
+ return (box, combo, suffix_label)
+
class NTPconfigDialog(GUIObject, GUIDialogInputCheckHandler):
builderObjects = ["ntpConfigDialog", "addImage", "serversStore"]
mainWidgetName = "ntpConfigDialog"
@@ -392,6 +413,7 @@ class DatetimeSpoke(FirstbootSpokeMixIn, NormalSpoke):
self._regionsStore = self.builder.get_object("regions")
self._citiesStore = self.builder.get_object("cities")
self._tzmap = self.builder.get_object("tzmap")
+ self._dateBox = self.builder.get_object("dateBox")
# we need to know it the new value is the same as previous or not
self._old_region = None
@@ -399,9 +421,6 @@ class DatetimeSpoke(FirstbootSpokeMixIn, NormalSpoke):
self._regionCombo = self.builder.get_object("regionCombobox")
self._cityCombo = self.builder.get_object("cityCombobox")
- self._monthCombo = self.builder.get_object("monthCombobox")
- self._dayCombo = self.builder.get_object("dayCombobox")
- self._yearCombo = self.builder.get_object("yearCombobox")
self._daysFilter = self.builder.get_object("daysFilter")
self._daysFilter.set_visible_func(self.existing_date, None)
@@ -416,11 +435,31 @@ class DatetimeSpoke(FirstbootSpokeMixIn, NormalSpoke):
self._amPmLabel = self.builder.get_object("amPmLabel")
self._radioButton24h = self.builder.get_object("timeFormatRB")
+ # create widgets for displaying/configuring date
+ day_box, self._dayCombo, day_label = _new_date_field_box(self._daysFilter)
+ month_box, self._monthCombo, month_label = _new_date_field_box(self._monthsStore)
+ year_box, self._yearCombo, year_label = _new_date_field_box(self._yearsStore)
+
+ # get the right order for date widgets and respective formats and put
+ # widgets in place
+ widgets, formats = resolve_date_format(year_box, month_box, day_box)
+ for widget in widgets:
+ self._dateBox.pack_start(widget, False, False, 0)
+
+ self._day_format, suffix = formats[widgets.index(day_box)]
+ day_label.set_text(suffix)
+ self._month_format, suffix = formats[widgets.index(month_box)]
+ month_label.set_text(suffix)
+ self._year_format, suffix = formats[widgets.index(year_box)]
+ year_label.set_text(suffix)
+
self._ntpSwitch = self.builder.get_object("networkTimeSwitch")
self._regions_zones = get_all_regions_and_timezones()
+ self._days_nums = dict()
self._months_nums = dict()
+ self._years_nums = dict()
# Set the initial sensitivity of the AM/PM toggle based on the time-type selected
self._radioButton24h.emit("toggled")
@@ -435,18 +474,18 @@ class DatetimeSpoke(FirstbootSpokeMixIn, NormalSpoke):
target=self._initialize))
def _initialize(self):
- for day in xrange(1, 32):
- self.add_to_store(self._daysStore, day)
+ # a bit hacky way, but should return the translated strings
+ for i in range(1, 32):
+ day = datetime.date(2000, 1, i).strftime(self._day_format)
+ self.add_to_store_idx(self._daysStore, i, day)
- for i in xrange(1, 13):
- #a bit hacky way, but should return the translated string
- #TODO: how to handle language change? Clear and populate again?
- month = datetime.date(2000, i, 1).strftime('%B')
- self.add_to_store(self._monthsStore, month)
- self._months_nums[month] = i
+ for i in range(1, 13):
+ month = datetime.date(2000, i, 1).strftime(self._month_format)
+ self.add_to_store_idx(self._monthsStore, i, month)
- for year in xrange(1990, 2051):
- self.add_to_store(self._yearsStore, year)
+ for i in range(1990, 2051):
+ year = datetime.date(i, 1, 1).strftime(self._year_format)
+ self.add_to_store_idx(self._yearsStore, i, year)
cities = set()
xlated_regions = ((region, get_xlated_timezone(region))
@@ -590,10 +629,14 @@ class DatetimeSpoke(FirstbootSpokeMixIn, NormalSpoke):
def add_to_store(self, store, item):
store.append([item])
- def existing_date(self, model, itr, user_data=None):
- if not itr:
+ @gtk_action_nowait
+ def add_to_store_idx(self, store, idx, item):
+ store.append([idx, item])
+
+ def existing_date(self, days_model, days_iter, user_data=None):
+ if not days_iter:
return False
- day = model[itr][0]
+ day = days_model[days_iter][0]
#days 1-28 are in every month every year
if day < 29:
@@ -603,16 +646,15 @@ class DatetimeSpoke(FirstbootSpokeMixIn, NormalSpoke):
months_iter = self._monthCombo.get_active_iter()
if not months_iter:
return True
- month = months_model[months_iter][0]
years_model = self._yearCombo.get_model()
years_iter = self._yearCombo.get_active_iter()
if not years_iter:
return True
- year = years_model[years_iter][0]
try:
- datetime.date(year, self._months_nums[month], day)
+ datetime.date(years_model[years_iter][0],
+ months_model[months_iter][0], day)
return True
except ValueError:
return False
@@ -682,8 +724,7 @@ class DatetimeSpoke(FirstbootSpokeMixIn, NormalSpoke):
self._minutesLabel.set_text("%0.2d" % now.minute)
self._set_combo_selection(self._dayCombo, now.day)
- self._set_combo_selection(self._monthCombo,
- datetime.date(2000, now.month, 1).strftime('%B'))
+ self._set_combo_selection(self._monthCombo, now.month)
self._set_combo_selection(self._yearCombo, now.year)
#GLib's timer is driven by the return value of the function.
@@ -701,15 +742,13 @@ class DatetimeSpoke(FirstbootSpokeMixIn, NormalSpoke):
if not flags.can_touch_runtime_system("save system time"):
return False
- month = self._get_combo_selection(self._monthCombo)
+ month, month_str = self._get_combo_selection(self._monthCombo)
if not month:
return False
- month = self._months_nums[month]
- year_str = self._get_combo_selection(self._yearCombo)
- if not year_str:
+ year, year_str = self._get_combo_selection(self._yearCombo)
+ if not year:
return False
- year = int(year_str)
hours = int(self._hoursLabel.get_text())
if not self._radioButton24h.get_active():
@@ -717,10 +756,9 @@ class DatetimeSpoke(FirstbootSpokeMixIn, NormalSpoke):
minutes = int(self._minutesLabel.get_text())
- day = self._get_combo_selection(self._dayCombo)
+ day, day_str = self._get_combo_selection(self._dayCombo)
#day may be None if there is no such in the selected year and month
if day:
- day = int(day)
isys.set_system_date_time(year, month, day, hours, minutes)
#start the timer only when the spoke is shown
@@ -789,9 +827,9 @@ class DatetimeSpoke(FirstbootSpokeMixIn, NormalSpoke):
model = combo.get_model()
itr = combo.get_active_iter()
if not itr or not model:
- return None
+ return None, None
- return model[itr][0]
+ return model[itr][0], model[itr][1]
def _restore_old_city_region(self):
"""Restore stored "old" (or last valid) values."""
--
1.9.3
More information about the anaconda-patches
mailing list