Rephrase settings names
[tails-greeter-prototype.git] / greeter.py
blobbdc392adb9dff0dd4f3860a9723e5bab469b3ab9
1 #!/usr/bin/env python3
3 # Copyright 2015 Tails developers <tails@boum.org>
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU General Public License as published by
7 # the Free Software Foundation, either version 3 of the License, or
8 # (at your option) any later version.
10 # This program is distributed in the hope that it will be useful,
11 # but WITHOUT ANY WARRANTY; without even the implied warranty of
12 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 # GNU General Public License for more details.
15 # You should have received a copy of the GNU General Public License
16 # along with this program. If not, see <http://www.gnu.org/licenses/>
18 ################################################################################
19 # TODO
21 # * help button should not look like buttons
22 # * settings change position when added, then removed
23 # * fill formats with formats (cf gnome-control-center)
24 # * show time when timezone is selected (we'll need to have it editable at some poit)
25 # * add a way cancel setting adding
26 ################################################################################
28 import os
29 import sys
31 import gi
33 gi.require_version('GLib', '2.0')
34 from gi.repository import GLib
35 gi.require_version('Gdk', '3.0')
36 from gi.repository import Gdk
37 gi.require_version('Gtk', '3.0')
38 from gi.repository import Gtk
40 import greeterdata
42 # To ease future internationalisation
43 _ = lambda x: x
45 UI_FILE = 'greeter.ui'
46 ICON_DIR = 'icons/'
47 APPLICATION_ICON_NAME = 'gdm-setup'
48 APPLICATION_TITLE = 'Welcome to Tails!'
50 class GreeterMainWindow(Gtk.ApplicationWindow):
52 def __init__(self, app):
53 Gtk.Window.__init__(self, title=APPLICATION_TITLE, application=app)
54 self._app = app
55 self.set_icon_name(APPLICATION_ICON_NAME)
56 self._build_ui()
57 self.set_position(Gtk.WindowPosition.CENTER)
58 self._last_selected_setting_row = []
60 def _build_ui(self):
61 # Load UI interface definition
62 self._builder = Gtk.Builder()
63 self._builder.add_from_file(UI_FILE)
64 self._builder.connect_signals(self)
66 # Map interface objects
67 box_main = self._builder.get_object('box_main')
69 self.label_language_header_status = \
70 self._builder.get_object('label_language_header_status')
71 checkbutton_language_save = \
72 self._builder.get_object('checkbutton_language_save')
73 self.listbox_language = self._builder.get_object('listbox_language')
74 self.listboxrow_text = self._builder.get_object('listboxrow_text')
75 self.label_text_value = self._builder.get_object('label_text_value')
76 self.listboxrow_keyboard = self._builder.get_object('listboxrow_keyboard')
77 self.label_keyboard_value = self._builder.get_object('label_keyboard_value')
78 self.listboxrow_formats = self._builder.get_object('listboxrow_formats')
79 self.label_formats_value = self._builder.get_object('label_formats_value')
80 self.listboxrow_tz = self._builder.get_object('listboxrow_tz')
81 self.label_tz_value = self._builder.get_object('label_tz_value')
83 self.checkbutton_storage_show_passphrase = \
84 self._builder.get_object('checkbutton_storage_show_passphrase')
85 self.button_storage_configure = \
86 self._builder.get_object('button_storage_configure')
87 self.button_storage_state = self._builder.get_object('button_storage_state')
88 self.image_storage_state = self._builder.get_object('image_storage_state')
89 self.button_storage_spinner = \
90 self._builder.get_object('button_storage_spinner')
91 self.spinner_storage_unlock = \
92 self._builder.get_object('spinner_storage_unlock')
93 self.entry_storage_passphrase = \
94 self._builder.get_object('entry_storage_passphrase')
95 self.button_storage_lock = self._builder.get_object('button_storage_lock')
96 self.button_storage_unlock =self._builder.get_object('button_storage_unlock')
97 self.box_storage_unlock = self._builder.get_object('box_storage_unlock')
99 checkbutton_settings_save = \
100 self._builder.get_object('checkbutton_settings_save')
101 self.listbox_settings = self._builder.get_object('listbox_settings')
102 self.listboxrow_settings_admin = \
103 self._builder.get_object('listboxrow_settings_admin')
104 self.label_settings_admin_value = \
105 self._builder.get_object('label_settings_admin_value')
106 self.listboxrow_settings_macspoof = \
107 self._builder.get_object('listboxrow_settings_macspoof')
108 self.label_settings_macspoof_value = \
109 self._builder.get_object('label_settings_macspoof_value')
110 self.listboxrow_settings_network = \
111 self._builder.get_object('listboxrow_settings_network')
112 self.label_settings_network_value = \
113 self._builder.get_object('label_settings_network_value')
114 self.listboxrow_settings_camouflage = \
115 self._builder.get_object('listboxrow_settings_camouflage')
116 self.label_settings_camouflage_value = \
117 self._builder.get_object('label_settings_camouflage_value')
119 label_settings_default = \
120 self._builder.get_object('label_settings_default')
121 self.toolbutton_settings_remove = \
122 self._builder.get_object('toolbutton_settings_remove')
123 self.toolbutton_settings_add = \
124 self._builder.get_object('toolbutton_settings_add')
126 self.window_add_setting = self._builder.get_object('window_add_setting')
127 self.listbox_add_setting = self._builder.get_object('listbox_add_setting')
129 box_text_popover = self._builder.get_object('box_text_popover')
130 searchentry_text = self._builder.get_object('searchentry_text')
131 liststore_text = self._builder.get_object('liststore_text')
132 treeview_text = self._builder.get_object('treeview_text')
133 box_keyboard_popover = self._builder.get_object('box_keyboard_popover')
134 searchentry_keyboard = self._builder.get_object('searchentry_keyboard')
135 liststore_keyboard = self._builder.get_object('liststore_keyboard')
136 treeview_keyboard = self._builder.get_object('treeview_keyboard')
137 box_formats_popover = self._builder.get_object('box_formats_popover')
138 searchentry_formats = self._builder.get_object('searchentry_formats')
139 liststore_formats = self._builder.get_object('liststore_formats')
140 treeview_formats = self._builder.get_object('treeview_formats')
141 box_tz_popover = self._builder.get_object('box_tz_popover')
142 searchentry_tz = self._builder.get_object('searchentry_tz')
143 liststore_tz = self._builder.get_object('liststore_tz')
144 treeview_tz = self._builder.get_object('treeview_tz')
146 box_admin_popover = self._builder.get_object('box_admin_popover')
147 self.entry_admin_password = \
148 self._builder.get_object('entry_admin_password')
149 self.entry_admin_verify = self._builder.get_object('entry_admin_verify')
150 box_macspoof_popover = self._builder.get_object('box_macspoof_popover')
151 switch_macspoof = self._builder.get_object('switch_macspoof')
152 box_network_popover = self._builder.get_object('box_network_popover')
153 self.listbox_network_controls = \
154 self._builder.get_object('listbox_network_controls')
155 self.listboxrow_network_clear = \
156 self._builder.get_object('listboxrow_network_clear')
157 self.image_network_clear = \
158 self._builder.get_object('image_network_clear')
159 self.listboxrow_network_specific = \
160 self._builder.get_object('listboxrow_network_specific')
161 self.image_network_specific = \
162 self._builder.get_object('image_network_specific')
163 self.listboxrow_network_off = \
164 self._builder.get_object('listboxrow_network_off')
165 self.image_network_off = \
166 self._builder.get_object('image_network_off')
167 box_camouflage_popover = \
168 self._builder.get_object('box_camouflage_popover')
169 switch_camouflage = self._builder.get_object('switch_camouflage')
171 # Set preferred size
172 self.set_default_size(600, -1)
174 # Add our icon dir to icon theme
175 icon_theme = Gtk.IconTheme.get_default()
176 icon_theme.prepend_search_path(ICON_DIR)
178 # Add placeholder to settings ListBox
179 self.listbox_settings.set_placeholder(label_settings_default)
181 # Create HeaderBar
182 headerbar = Gtk.HeaderBar()
184 button_restart = Gtk.Button()
185 button_restart.set_label(_("Restart"))
186 button_restart.set_size_request(100, -1)
187 button_restart.connect('clicked', self.cb_button_restart_clicked)
188 headerbar.pack_start(button_restart)
190 button_start = Gtk.Button()
191 button_start.set_label(_("Start Tails"))
192 button_start.set_size_request(100, -1)
193 Gtk.StyleContext.add_class(button_start.get_style_context(),
194 'suggested-action')
195 button_start.connect('clicked', self.cb_button_start_clicked)
196 headerbar.pack_end(button_start)
198 button_tour = Gtk.Button()
199 button_tour.set_label(_("Take a Tour"))
200 button_tour.set_size_request(100, -1)
201 button_tour.connect('clicked', self.cb_button_tour_clicked)
202 headerbar.pack_end(button_tour)
204 headerbar.show_all()
206 # Align CheckBoxes to the left
207 for cb in [checkbutton_language_save,
208 self.checkbutton_storage_show_passphrase,
209 checkbutton_settings_save]:
210 cb.set_direction(Gtk.TextDirection.RTL)
212 # Add popovers
213 self.popover_text = self.__add_popover(
214 self.listboxrow_text,
215 box_text_popover,
216 closed_cb=self.cb_popover_text_closed)
217 self.popover_keyboard = self.__add_popover(
218 self.listboxrow_keyboard,
219 box_keyboard_popover,
220 closed_cb=self.cb_popover_keyboard_closed)
221 self.popover_formats = self.__add_popover(
222 self.listboxrow_formats,
223 box_formats_popover,
224 closed_cb=self.cb_popover_formats_closed)
225 self.popover_tz = self.__add_popover(
226 self.listboxrow_tz,
227 box_tz_popover,
228 closed_cb=self.cb_popover_tz_closed)
230 self.popover_admin = self.__add_popover(
231 self.listboxrow_settings_admin,
232 box_admin_popover,
233 closed_cb=self.cb_popover_admin_closed)
234 self.popover_macspoof = self.__add_popover(
235 self.listboxrow_settings_macspoof,
236 box_macspoof_popover,
237 closed_cb=self.cb_popover_macspoof_closed)
238 self.popover_network = self.__add_popover(
239 self.listboxrow_settings_network,
240 box_network_popover,
241 closed_cb=self.cb_popover_network_closed)
242 self.popover_camouflage = self.__add_popover(
243 self.listboxrow_settings_camouflage,
244 box_camouflage_popover,
245 closed_cb=self.cb_popover_camouflage_closed)
247 # Add children to ApplicationWindow
248 self.add(box_main)
249 self.set_titlebar(headerbar)
251 # Create "Add Privacy Setting" dialog
252 self.window_add_setting.set_transient_for(self)
254 # Fill language treeviews
255 for language in greeterdata.languages:
256 liststore_text.append(language)
257 self.__fill_tv("Text Language", treeview_text)
258 self.liststore_text_filtered = liststore_text.filter_new()
259 self.liststore_text_filtered.set_visible_func(
260 self.cb_liststore_filtered_visible_func, data=searchentry_text)
261 treeview_text.set_model(self.liststore_text_filtered)
263 for layout in greeterdata.layouts:
264 liststore_keyboard.append(layout)
265 self.__fill_tv("Keyboard Layout", treeview_keyboard)
266 self.liststore_keyboard_filtered = liststore_keyboard.filter_new()
267 self.liststore_keyboard_filtered.set_visible_func(
268 self.cb_liststore_filtered_visible_func, data=searchentry_keyboard)
269 treeview_keyboard.set_model(self.liststore_keyboard_filtered)
271 for locale in greeterdata.locales:
272 liststore_formats.append(locale)
273 self.__fill_tv("Format", treeview_formats)
274 self.liststore_formats_filtered = liststore_formats.filter_new()
275 self.liststore_formats_filtered.set_visible_func(
276 self.cb_liststore_filtered_visible_func, data=searchentry_formats)
277 treeview_formats.set_model(self.liststore_formats_filtered)
279 for timezone in greeterdata.timezones:
280 liststore_tz.append(timezone)
281 self.__fill_tv("Time Zone", treeview_tz)
282 self.liststore_tz_filtered = liststore_tz.filter_new()
283 self.liststore_tz_filtered.set_visible_func(
284 self.cb_liststore_filtered_visible_func, data=searchentry_tz)
285 treeview_tz.set_model(self.liststore_tz_filtered)
287 # Storage configuration/unlocking
288 if os.getenv('TAILS_HAS_PERSISTENCE'):
289 self.button_storage_configure.set_visible(False)
290 self.checkbutton_storage_show_passphrase.set_visible(True)
291 self.box_storage_unlock.set_visible(True)
292 self.button_storage_state.set_visible(True)
293 self.entry_storage_passphrase.set_visible(True)
294 self.button_storage_unlock.set_visible(True)
296 # Settings popovers
297 switch_macspoof.connect('notify::active', self.cb_switch_macspoof_active)
298 switch_camouflage.connect('notify::active', self.cb_switch_camouflage_active)
300 def setting_admin_check(self):
301 password = self.entry_admin_password.get_text()
302 verify = self.entry_admin_verify.get_text()
303 if verify and verify == password:
304 icon = 'emblem-ok-symbolic'
305 elif verify and not (verify == password):
306 icon = 'dialog-warning-symbolic'
307 else:
308 icon = None
309 self.entry_admin_verify.set_icon_from_icon_name(
310 Gtk.EntryIconPosition.SECONDARY, icon)
311 return (verify == password)
313 def setting_admin_apply(self):
314 if self.setting_admin_check():
315 self.label_settings_admin_value.set_text(
316 self.__get_on_off_string(self.entry_admin_password.get_text()))
317 self.popover_admin.set_visible(False)
318 return True
319 else:
320 return False
322 # Utility methods
324 @staticmethod
325 def __add_popover(widget, content, closed_cb=None):
326 popover = Gtk.Popover.new(widget)
327 popover.set_position(Gtk.PositionType.BOTTOM)
328 popover.add(content)
329 if closed_cb:
330 popover.connect('closed', closed_cb)
331 return popover
333 @staticmethod
334 def __fill_tv (name, treeview):
335 assert isinstance(name, str)
336 assert isinstance(treeview, Gtk.TreeView)
337 renderer = Gtk.CellRendererText()
338 column = Gtk.TreeViewColumn(name, renderer, text=1)
339 treeview.append_column(column)
341 @staticmethod
342 def __popover_toggle(popover):
343 if popover.get_visible():
344 popover.set_visible(False)
345 else:
346 popover.set_visible(True)
348 @staticmethod
349 def __get_on_off_string(value):
350 if value:
351 return _("On")
352 else:
353 return _("Off")
355 # Callbacks
357 def cb_button_help_clicked(self, widget, user_data=None):
358 dialog = Gtk.MessageDialog(
359 self,
360 Gtk.DialogFlags.DESTROY_WITH_PARENT,
361 Gtk.MessageType.INFO,
362 Gtk.ButtonsType.CLOSE,
363 _("You would see the help page for this element."))
364 dialog.run()
365 dialog.destroy()
366 return False
368 def cb_button_restart_clicked(self, widget, user_data=None):
369 self._app.quit()
370 return False
372 def cb_button_start_clicked(self, widget, user_data=None):
373 self._app.quit()
374 return False
376 def cb_button_storage_configure_clicked(self, user_data=None):
377 dialog = Gtk.MessageDialog(
378 self,
379 Gtk.DialogFlags.DESTROY_WITH_PARENT,
380 Gtk.MessageType.INFO,
381 Gtk.ButtonsType.CLOSE,
382 _("You would be able to set up an encrypted storage."))
383 dialog.run()
384 dialog.destroy()
385 return False
387 def cb_button_tour_clicked(self, user_data=None):
388 dialog = Gtk.MessageDialog(
389 self,
390 Gtk.DialogFlags.DESTROY_WITH_PARENT,
391 Gtk.MessageType.INFO,
392 Gtk.ButtonsType.CLOSE,
393 _("You would be guided through options by a wizard."))
394 dialog.run()
395 dialog.destroy()
396 return False
399 def cb_button_storage_lock_clicked(self, widget, user_data=None):
400 self.button_storage_lock.set_visible(False)
401 self.checkbutton_storage_show_passphrase.set_visible(True)
402 self.box_storage_unlock.set_visible(True)
403 self.button_storage_state.set_visible(True)
404 self.image_storage_state.set_from_icon_name('tails-locked',
405 Gtk.IconSize.BUTTON)
406 self.entry_storage_passphrase.set_visible(True)
407 self.entry_storage_passphrase.set_sensitive(True)
408 self.button_storage_unlock.set_visible(True)
409 self.button_storage_unlock.set_sensitive(True)
410 self.button_storage_unlock.set_label(_("Unlock"))
411 return False
413 def cb_button_storage_unlock_clicked(self, widget, user_data=None):
414 self.checkbutton_storage_show_passphrase.set_visible(False)
415 self.entry_storage_passphrase.set_sensitive(False)
416 self.button_storage_unlock.set_sensitive(False)
417 self.button_storage_unlock.set_label(_("Unlocking"))
418 self.button_storage_state.set_visible(False)
419 self.button_storage_spinner.set_visible(True)
420 GLib.timeout_add_seconds(2, self.cb_timeout_storage_unlocked, user_data=None)
421 return False
423 def cb_checkbutton_storage_show_passphrase_toggled(self, widget, user_data=None):
424 self.entry_storage_passphrase.set_visibility(widget.get_active())
426 def cb_entry_admin_changed(self, editable, user_data=None):
427 self.setting_admin_check()
428 return False
430 def cb_entry_admin_focus_out_event(self, widget, event, user_data=None):
431 self.setting_admin_apply()
432 return False
434 def cb_entry_admin_password_activate(self, widget, user_data=None):
435 self.entry_admin_verify.grab_focus()
436 return False
438 def cb_entry_admin_verify_activate(self, widget, user_data=None):
439 self.setting_admin_apply()
440 return False
442 def cb_listbox_add_setting_focus(self, widget, direction, user_data=None):
443 # Workaround autoselection of 1st item on focus
444 self.listbox_add_setting.unselect_all()
445 return False
447 def cb_listbox_add_setting_row_activated(self, listbox, row, user_data=None):
448 if not row: # this happens when the row gets unselected
449 return False
450 listbox.remove(row)
451 self.listbox_settings.add(row)
452 self.window_add_setting.set_visible(False)
453 if row == self.listboxrow_settings_admin:
454 self.__popover_toggle(self.popover_admin)
455 elif row == self.listboxrow_settings_macspoof:
456 self.__popover_toggle(self.popover_macspoof)
457 elif row == self.listboxrow_settings_network:
458 self.__popover_toggle(self.popover_network)
459 elif row == self.listboxrow_settings_camouflage:
460 self.__popover_toggle(self.popover_camouflage)
461 if len(listbox.get_children()) == 0:
462 self.toolbutton_settings_add.set_sensitive(False)
463 return False
465 def cb_listbox_language_row_activated(self, listbox, row, user_data=None):
466 if row == self.listboxrow_text:
467 self.__popover_toggle(self.popover_text)
468 elif row == self.listboxrow_keyboard:
469 self.__popover_toggle(self.popover_keyboard)
470 elif row == self.listboxrow_formats:
471 self.__popover_toggle(self.popover_formats)
472 elif row == self.listboxrow_tz:
473 self.__popover_toggle(self.popover_tz)
474 return False
476 def cb_listbox_network_row_activated(self, listbox, row, user_data=None):
477 if row == self.listboxrow_network_clear:
478 self.image_network_clear.set_visible(True)
479 self.image_network_specific.set_visible(False)
480 self.image_network_off.set_visible(False)
481 self.label_settings_network_value.set_text(_("Direct"))
482 elif row == self.listboxrow_network_specific:
483 self.image_network_specific.set_visible(True)
484 self.image_network_clear.set_visible(False)
485 self.image_network_off.set_visible(False)
486 self.label_settings_network_value.set_text(_("Censored"))
487 elif row == self.listboxrow_network_off:
488 self.image_network_off.set_visible(True)
489 self.image_network_specific.set_visible(False)
490 self.image_network_clear.set_visible(False)
491 self.label_settings_network_value.set_text(_("Off"))
492 self.popover_network.set_visible(False)
493 return False
495 def cb_listbox_settings_add(self, listbox, row, user_data=None):
496 self._last_selected_setting_row.append(row)
497 if len(listbox.get_children()) > 0:
498 self.toolbutton_settings_remove.set_sensitive(True)
499 return False
501 def cb_listbox_settings_remove(self, container, object, user_data=None):
502 if len(container.get_children()) == 0:
503 self.toolbutton_settings_remove.set_sensitive(False)
504 return False
506 def cb_listbox_settings_row_selected(self, listbox, row, user_data=None):
507 if row:
508 self._last_selected_setting_row.append(row)
510 def cb_listbox_settings_row_activated(self, listbox, row, user_data=None):
511 if row == self.listboxrow_settings_admin:
512 self.__popover_toggle(self.popover_admin)
513 elif row == self.listboxrow_settings_macspoof:
514 self.__popover_toggle(self.popover_macspoof)
515 elif row == self.listboxrow_settings_network:
516 self.__popover_toggle(self.popover_network)
517 elif row == self.listboxrow_settings_camouflage:
518 self.__popover_toggle(self.popover_camouflage)
519 return False
521 def cb_liststore_filtered_visible_func(self, model, treeiter, searchentry):
522 search_query = searchentry.get_text().lower()
523 value = model.get_value(treeiter, 1).lower()
524 if not search_query:
525 return True
526 elif search_query in value:
527 return True
528 else:
529 return False
531 def cb_popover_text_closed(self, popover, user_data=None):
532 self.listbox_language.unselect_all()
533 return False
535 def cb_popover_keyboard_closed(self, popover, user_data=None):
536 self.listbox_language.unselect_all()
537 return False
539 def cb_popover_formats_closed(self, popover, user_data=None):
540 self.listbox_language.unselect_all()
541 return False
543 def cb_popover_tz_closed(self, popover, user_data=None):
544 self.listbox_language.unselect_all()
545 return False
547 def cb_popover_admin_closed(self, popover, user_data=None):
548 self.listbox_settings.unselect_all()
549 return False
551 def cb_popover_macspoof_closed(self, popover, user_data=None):
552 self.listbox_settings.unselect_all()
553 return False
555 def cb_popover_network_closed(self, popover, user_data=None):
556 self.listbox_settings.unselect_all()
557 return False
559 def cb_popover_camouflage_closed(self, popover, user_data=None):
560 self.listbox_settings.unselect_all()
561 return False
563 def cb_searchentry_formats_search_changed(self, widget, user_data=None):
564 self.liststore_formats_filtered.refilter()
565 return False
567 def cb_searchentry_keyboard_search_changed(self, widget, user_data=None):
568 self.liststore_keyboard_filtered.refilter()
569 return False
571 def cb_searchentry_text_search_changed(self, widget, user_data=None):
572 self.liststore_text_filtered.refilter()
573 return False
575 def cb_searchentry_tz_search_changed(self, widget, user_data=None):
576 self.liststore_tz_filtered.refilter()
577 return False
579 def cb_switch_camouflage_active(self, switch, pspec, user_data=None):
580 self.label_settings_camouflage_value.set_text(
581 self.__get_on_off_string(switch.get_state()))
582 self.popover_camouflage.set_visible(False)
584 def cb_switch_macspoof_active(self, switch, pspec, user_data=None):
585 self.label_settings_macspoof_value.set_text(
586 self.__get_on_off_string(switch.get_state()))
587 self.popover_macspoof.set_visible(False)
589 def cb_timeout_storage_unlocked(self, user_data=None):
590 self.button_storage_spinner.set_visible(False)
591 self.entry_storage_passphrase.set_visible(False)
592 self.button_storage_unlock.set_visible(False)
593 self.image_storage_state.set_from_icon_name('tails-unlocked',
594 Gtk.IconSize.BUTTON)
595 self.button_storage_state.set_visible(True)
596 self.button_storage_lock.set_visible(True)
597 return False
599 def cb_toolbutton_settings_add_clicked(self, user_data=None):
600 self.window_add_setting.show_all()
601 return False
603 def cb_toolbutton_settings_remove_clicked(self, user_data=None):
604 try:
605 row = self._last_selected_setting_row.pop()
606 except IndexError:
607 return False
608 self.listbox_settings.remove(row)
609 self.listbox_add_setting.add(row)
610 return False
612 def cb_treeview_formats_row_activated(self, treeview, path, column, user_data=None):
613 treemodel = treeview.get_model()
614 value = treemodel.get_value(treemodel.get_iter(path), 1)
615 self.label_formats_value.set_text(value)
616 self.label_language_header_status.set_text(_("Custom settings"))
617 self.popover_formats.set_visible(False)
619 def cb_treeview_keyboard_row_activated(self, treeview, path, column, user_data=None):
620 treemodel = treeview.get_model()
621 value = treemodel.get_value(treemodel.get_iter(path), 1)
622 self.label_keyboard_value.set_text(value)
623 self.label_language_header_status.set_text(_("Custom settings"))
624 self.popover_keyboard.set_visible(False)
626 def cb_treeview_text_row_activated(self, treeview, path, column, user_data=None):
627 treemodel = treeview.get_model()
628 value = treemodel.get_value(treemodel.get_iter(path), 1)
629 self.label_text_value.set_text(value)
630 self.label_language_header_status.set_text(_("Custom settings"))
631 self.popover_text.set_visible(False)
633 def cb_treeview_tz_row_activated(self, treeview, path, column, user_data=None):
634 treemodel = treeview.get_model()
635 value = treemodel.get_value(treemodel.get_iter(path), 1)
636 self.label_tz_value.set_text(value)
637 self.label_language_header_status.set_text(_("Custom settings"))
638 self.popover_tz.set_visible(False)
640 class GreeterBackgroundWindow(Gtk.ApplicationWindow):
642 def __init__(self, app):
643 Gtk.Window.__init__(self, title=APPLICATION_TITLE, application=app)
644 self.set_icon_name(APPLICATION_ICON_NAME)
645 self.override_background_color(
646 Gtk.StateFlags.NORMAL, Gdk.RGBA(0, 0, 0, 1))
648 class GreeterApplication(Gtk.Application):
650 def __init__(self):
651 Gtk.Application.__init__(self)
652 self.set_application_id = 'org.boum.tails.greeter'
654 def do_activate(self):
655 backgroundwindow = GreeterBackgroundWindow(self)
656 backgroundwindow.maximize()
657 appwindow = GreeterMainWindow(self)
658 appwindow.set_transient_for(backgroundwindow)
660 if not os.getenv('DEBUG'):
661 backgroundwindow.show()
662 appwindow.show()
664 def do_startup(self):
665 Gtk.Application.do_startup(self)
667 app = GreeterApplication()
668 exit_status = app.run(sys.argv)
669 sys.exit(exit_status)