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 ################################################################################
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 an icon representing encrypted storage
26 ################################################################################
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
42 # To ease future internationalisation
45 UI_FILE
= 'greeter.ui'
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
)
55 self
.set_icon_name(APPLICATION_ICON_NAME
)
57 self
.set_position(Gtk
.WindowPosition
.CENTER
)
58 self
._last
_selected
_setting
_row
= []
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
.listbox_add_setting
= self
._builder
.get_object('listbox_add_setting')
128 box_text_popover
= self
._builder
.get_object('box_text_popover')
129 searchentry_text
= self
._builder
.get_object('searchentry_text')
130 liststore_text
= self
._builder
.get_object('liststore_text')
131 treeview_text
= self
._builder
.get_object('treeview_text')
132 box_keyboard_popover
= self
._builder
.get_object('box_keyboard_popover')
133 searchentry_keyboard
= self
._builder
.get_object('searchentry_keyboard')
134 liststore_keyboard
= self
._builder
.get_object('liststore_keyboard')
135 treeview_keyboard
= self
._builder
.get_object('treeview_keyboard')
136 box_formats_popover
= self
._builder
.get_object('box_formats_popover')
137 searchentry_formats
= self
._builder
.get_object('searchentry_formats')
138 liststore_formats
= self
._builder
.get_object('liststore_formats')
139 treeview_formats
= self
._builder
.get_object('treeview_formats')
140 box_tz_popover
= self
._builder
.get_object('box_tz_popover')
141 searchentry_tz
= self
._builder
.get_object('searchentry_tz')
142 liststore_tz
= self
._builder
.get_object('liststore_tz')
143 treeview_tz
= self
._builder
.get_object('treeview_tz')
145 self
.box_admin_popover
= self
._builder
.get_object('box_admin_popover')
146 self
.entry_admin_password
= \
147 self
._builder
.get_object('entry_admin_password')
148 self
.entry_admin_verify
= self
._builder
.get_object('entry_admin_verify')
149 self
.box_macspoof_popover
= self
._builder
.get_object('box_macspoof_popover')
150 switch_macspoof
= self
._builder
.get_object('switch_macspoof')
151 self
.box_network_popover
= self
._builder
.get_object('box_network_popover')
152 self
.listbox_network_controls
= \
153 self
._builder
.get_object('listbox_network_controls')
154 self
.listboxrow_network_clear
= \
155 self
._builder
.get_object('listboxrow_network_clear')
156 self
.image_network_clear
= \
157 self
._builder
.get_object('image_network_clear')
158 self
.listboxrow_network_specific
= \
159 self
._builder
.get_object('listboxrow_network_specific')
160 self
.image_network_specific
= \
161 self
._builder
.get_object('image_network_specific')
162 self
.listboxrow_network_off
= \
163 self
._builder
.get_object('listboxrow_network_off')
164 self
.image_network_off
= \
165 self
._builder
.get_object('image_network_off')
166 self
.box_camouflage_popover
= \
167 self
._builder
.get_object('box_camouflage_popover')
168 switch_camouflage
= self
._builder
.get_object('switch_camouflage')
171 self
.set_default_size(600, -1)
173 # Add our icon dir to icon theme
174 icon_theme
= Gtk
.IconTheme
.get_default()
175 icon_theme
.prepend_search_path(ICON_DIR
)
177 # Add placeholder to settings ListBox
178 self
.listbox_settings
.set_placeholder(label_settings_default
)
181 headerbar
= Gtk
.HeaderBar()
182 headerbar_sizegroup
= Gtk
.SizeGroup(Gtk
.SizeGroupMode
.HORIZONTAL
)
184 button_restart
= Gtk
.Button()
185 button_restart
.set_label(_("Restart"))
186 button_restart
.connect('clicked', self
.cb_button_restart_clicked
)
187 headerbar_sizegroup
.add_widget(button_restart
)
188 headerbar
.pack_start(button_restart
)
190 button_start
= Gtk
.Button()
191 button_start
.set_label(_("Start Tails"))
192 Gtk
.StyleContext
.add_class(button_start
.get_style_context(),
194 button_start
.connect('clicked', self
.cb_button_start_clicked
)
195 headerbar_sizegroup
.add_widget(button_start
)
196 headerbar
.pack_end(button_start
)
198 button_tour
= Gtk
.Button()
199 button_tour
.set_label(_("Take a Tour"))
200 button_tour
.connect('clicked', self
.cb_button_tour_clicked
)
201 headerbar_sizegroup
.add_widget(button_tour
)
202 headerbar
.pack_end(button_tour
)
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
)
213 self
.popover_text
= self
.__add
_popover
(
214 self
.listboxrow_text
,
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
,
224 closed_cb
=self
.cb_popover_formats_closed
)
225 self
.popover_tz
= self
.__add
_popover
(
228 closed_cb
=self
.cb_popover_tz_closed
)
230 # Add children to ApplicationWindow
232 self
.set_titlebar(headerbar
)
234 # Create "Add Privacy Setting" dialog
235 self
.dialog_add_setting
= Gtk
.Dialog(use_header_bar
=True)
236 self
.dialog_add_setting
.set_transient_for(self
)
237 self
.dialog_add_setting
.set_title(_("Add Privacy Setting"))
238 self
.dialog_add_setting
.set_default_size(-1, 400)
240 dialog_add_setting_sizegroup
= Gtk
.SizeGroup(Gtk
.SizeGroupMode
.HORIZONTAL
)
242 self
.button_add_setting_cancel
= self
.dialog_add_setting
.add_button(
243 _("Cancel"), Gtk
.ResponseType
.CANCEL
)
244 dialog_add_setting_sizegroup
.add_widget(self
.button_add_setting_cancel
)
246 self
.button_add_setting_add
= self
.dialog_add_setting
.add_button(
247 _("Add"), Gtk
.ResponseType
.YES
)
248 Gtk
.StyleContext
.add_class(self
.button_add_setting_add
.get_style_context(),
250 dialog_add_setting_sizegroup
.add_widget(self
.button_add_setting_add
)
252 self
.button_add_setting_add
.set_visible(False)
253 self
.button_add_setting_back
= Gtk
.Button
.new_with_label(_("Back"))
254 self
.button_add_setting_back
.set_visible(False)
255 self
.button_add_setting_back
.connect(
256 'clicked', self
.cb_button_add_setting_back_clicked
, None)
257 dialog_add_setting_sizegroup
.add_widget(self
.button_add_setting_back
)
258 self
.dialog_add_setting
.get_header_bar().pack_end(self
.button_add_setting_back
)
260 self
.stack_add_setting
= Gtk
.Stack()
261 self
.stack_add_setting
.add_named(self
.listbox_add_setting
, "setting-type")
262 self
.listbox_add_setting
.set_valign(Gtk
.Align
.FILL
)
263 self
.listbox_add_setting
.set_vexpand(True)
264 self
.stack_add_setting
.set_visible(True)
265 self
.stack_add_setting
.set_transition_type(
266 Gtk
.StackTransitionType
.SLIDE_LEFT_RIGHT
)
267 self
.dialog_add_setting
.get_content_area().add(self
.stack_add_setting
)
269 # Fill language treeviews
270 for language
in greeterdata
.languages
:
271 liststore_text
.append(language
)
272 self
.__fill
_tv
("Text Language", treeview_text
)
273 self
.liststore_text_filtered
= liststore_text
.filter_new()
274 self
.liststore_text_filtered
.set_visible_func(
275 self
.cb_liststore_filtered_visible_func
, data
=searchentry_text
)
276 treeview_text
.set_model(self
.liststore_text_filtered
)
278 for layout
in greeterdata
.layouts
:
279 liststore_keyboard
.append(layout
)
280 self
.__fill
_tv
("Keyboard Layout", treeview_keyboard
)
281 self
.liststore_keyboard_filtered
= liststore_keyboard
.filter_new()
282 self
.liststore_keyboard_filtered
.set_visible_func(
283 self
.cb_liststore_filtered_visible_func
, data
=searchentry_keyboard
)
284 treeview_keyboard
.set_model(self
.liststore_keyboard_filtered
)
286 for locale
in greeterdata
.locales
:
287 liststore_formats
.append(locale
)
288 self
.__fill
_tv
("Format", treeview_formats
)
289 self
.liststore_formats_filtered
= liststore_formats
.filter_new()
290 self
.liststore_formats_filtered
.set_visible_func(
291 self
.cb_liststore_filtered_visible_func
, data
=searchentry_formats
)
292 treeview_formats
.set_model(self
.liststore_formats_filtered
)
294 for timezone
in greeterdata
.timezones
:
295 liststore_tz
.append(timezone
)
296 self
.__fill
_tv
("Time Zone", treeview_tz
)
297 self
.liststore_tz_filtered
= liststore_tz
.filter_new()
298 self
.liststore_tz_filtered
.set_visible_func(
299 self
.cb_liststore_filtered_visible_func
, data
=searchentry_tz
)
300 treeview_tz
.set_model(self
.liststore_tz_filtered
)
302 # Storage configuration/unlocking
303 if os
.getenv('TAILS_HAS_PERSISTENCE'):
304 self
.button_storage_configure
.set_visible(False)
305 self
.checkbutton_storage_show_passphrase
.set_visible(True)
306 self
.box_storage_unlock
.set_visible(True)
307 self
.button_storage_state
.set_visible(True)
308 self
.entry_storage_passphrase
.set_visible(True)
309 self
.button_storage_unlock
.set_visible(True)
312 switch_macspoof
.connect('notify::active', self
.cb_switch_macspoof_active
)
313 switch_camouflage
.connect('notify::active', self
.cb_switch_camouflage_active
)
315 def setting_admin_check(self
):
316 password
= self
.entry_admin_password
.get_text()
317 verify
= self
.entry_admin_verify
.get_text()
318 if verify
and verify
== password
:
319 icon
= 'emblem-ok-symbolic'
320 elif verify
and not (verify
== password
):
321 icon
= 'dialog-warning-symbolic'
324 self
.entry_admin_verify
.set_icon_from_icon_name(
325 Gtk
.EntryIconPosition
.SECONDARY
, icon
)
326 return (verify
== password
)
328 def setting_admin_apply(self
):
329 if self
.setting_admin_check():
330 self
.label_settings_admin_value
.set_text(
331 self
.__get
_on
_off
_string
(self
.entry_admin_password
.get_text()))
332 if hasattr(self
, 'popover_admin'):
333 self
.popover_admin
.set_visible(False)
341 def __add_popover(widget
, content
, closed_cb
=None):
342 popover
= Gtk
.Popover
.new(widget
)
343 popover
.set_position(Gtk
.PositionType
.BOTTOM
)
346 popover
.connect('closed', closed_cb
)
350 def __fill_tv (name
, treeview
):
351 assert isinstance(name
, str)
352 assert isinstance(treeview
, Gtk
.TreeView
)
353 renderer
= Gtk
.CellRendererText()
354 column
= Gtk
.TreeViewColumn(name
, renderer
, text
=1)
355 treeview
.append_column(column
)
358 def __popover_toggle(popover
):
359 if popover
.get_visible():
360 popover
.set_visible(False)
362 popover
.set_visible(True)
365 def __get_on_off_string(value
):
373 def cb_button_add_setting_back_clicked(self
, widget
, user_data
=None):
374 self
.stack_add_setting
.set_visible_child_name('setting-type')
375 self
.stack_add_setting
.remove(
376 self
.stack_add_setting
.get_child_by_name('setting-details'))
379 def cb_button_help_clicked(self
, widget
, user_data
=None):
380 dialog
= Gtk
.MessageDialog(
382 Gtk
.DialogFlags
.DESTROY_WITH_PARENT
,
383 Gtk
.MessageType
.INFO
,
384 Gtk
.ButtonsType
.CLOSE
,
385 _("You would see the help page for this element."))
390 def cb_button_restart_clicked(self
, widget
, user_data
=None):
394 def cb_button_start_clicked(self
, widget
, user_data
=None):
398 def cb_button_storage_configure_clicked(self
, user_data
=None):
399 dialog
= Gtk
.MessageDialog(
401 Gtk
.DialogFlags
.DESTROY_WITH_PARENT
,
402 Gtk
.MessageType
.INFO
,
403 Gtk
.ButtonsType
.CLOSE
,
404 _("You would be able to set up an encrypted storage."))
409 def cb_button_tour_clicked(self
, user_data
=None):
410 dialog
= Gtk
.MessageDialog(
412 Gtk
.DialogFlags
.DESTROY_WITH_PARENT
,
413 Gtk
.MessageType
.INFO
,
414 Gtk
.ButtonsType
.CLOSE
,
415 _("You would be guided through options by a wizard."))
420 def cb_button_storage_lock_clicked(self
, widget
, user_data
=None):
421 self
.button_storage_lock
.set_visible(False)
422 self
.checkbutton_storage_show_passphrase
.set_visible(True)
423 self
.box_storage_unlock
.set_visible(True)
424 self
.button_storage_state
.set_visible(True)
425 self
.image_storage_state
.set_from_icon_name('tails-locked',
427 self
.entry_storage_passphrase
.set_visible(True)
428 self
.entry_storage_passphrase
.set_sensitive(True)
429 self
.button_storage_unlock
.set_visible(True)
430 self
.button_storage_unlock
.set_sensitive(True)
431 self
.button_storage_unlock
.set_label(_("Unlock"))
434 def cb_button_storage_unlock_clicked(self
, widget
, user_data
=None):
435 self
.checkbutton_storage_show_passphrase
.set_visible(False)
436 self
.entry_storage_passphrase
.set_sensitive(False)
437 self
.button_storage_unlock
.set_sensitive(False)
438 self
.button_storage_unlock
.set_label(_("Unlocking"))
439 self
.button_storage_state
.set_visible(False)
440 self
.button_storage_spinner
.set_visible(True)
441 GLib
.timeout_add_seconds(2, self
.cb_timeout_storage_unlocked
, user_data
=None)
444 def cb_checkbutton_storage_show_passphrase_toggled(self
, widget
, user_data
=None):
445 self
.entry_storage_passphrase
.set_visibility(widget
.get_active())
447 def cb_entry_admin_changed(self
, editable
, user_data
=None):
448 self
.setting_admin_check()
451 def cb_entry_admin_focus_out_event(self
, widget
, event
, user_data
=None):
452 self
.setting_admin_apply()
455 def cb_entry_admin_password_activate(self
, widget
, user_data
=None):
456 self
.entry_admin_verify
.grab_focus()
459 def cb_entry_admin_verify_activate(self
, widget
, user_data
=None):
460 self
.setting_admin_apply()
463 def cb_listbox_add_setting_focus(self
, widget
, direction
, user_data
=None):
464 # Workaround autoselection of 1st item on focus
465 self
.listbox_add_setting
.unselect_all()
468 def cb_listbox_add_setting_row_activated(self
, listbox
, row
, user_data
=None):
469 if row
== self
.listboxrow_settings_admin
:
470 box
= self
.box_admin_popover
471 elif row
== self
.listboxrow_settings_macspoof
:
472 box
= self
.box_macspoof_popover
473 elif row
== self
.listboxrow_settings_network
:
474 box
= self
.box_network_popover
475 elif row
== self
.listboxrow_settings_camouflage
:
476 box
= self
.box_camouflage_popover
477 else: # this happens when the row gets unselected
479 self
.stack_add_setting
.add_named(box
, 'setting-details')
480 self
.stack_add_setting
.set_visible_child_name('setting-details')
481 self
.button_add_setting_back
.set_visible(True)
482 self
.button_add_setting_add
.set_visible(True)
485 def cb_listbox_language_row_activated(self
, listbox
, row
, user_data
=None):
486 if row
== self
.listboxrow_text
:
487 self
.__popover
_toggle
(self
.popover_text
)
488 elif row
== self
.listboxrow_keyboard
:
489 self
.__popover
_toggle
(self
.popover_keyboard
)
490 elif row
== self
.listboxrow_formats
:
491 self
.__popover
_toggle
(self
.popover_formats
)
492 elif row
== self
.listboxrow_tz
:
493 self
.__popover
_toggle
(self
.popover_tz
)
496 def cb_listbox_network_row_activated(self
, listbox
, row
, user_data
=None):
497 if row
== self
.listboxrow_network_clear
:
498 self
.image_network_clear
.set_visible(True)
499 self
.image_network_specific
.set_visible(False)
500 self
.image_network_off
.set_visible(False)
501 self
.label_settings_network_value
.set_text(_("Direct"))
502 elif row
== self
.listboxrow_network_specific
:
503 self
.image_network_specific
.set_visible(True)
504 self
.image_network_clear
.set_visible(False)
505 self
.image_network_off
.set_visible(False)
506 self
.label_settings_network_value
.set_text(_("Censored"))
507 elif row
== self
.listboxrow_network_off
:
508 self
.image_network_off
.set_visible(True)
509 self
.image_network_specific
.set_visible(False)
510 self
.image_network_clear
.set_visible(False)
511 self
.label_settings_network_value
.set_text(_("Off"))
512 if hasattr(self
, 'popover_network'):
513 self
.popover_network
.set_visible(False)
516 def cb_listbox_settings_add(self
, listbox
, row
, user_data
=None):
517 self
._last
_selected
_setting
_row
.append(row
)
518 if len(listbox
.get_children()) > 0:
519 self
.toolbutton_settings_remove
.set_sensitive(True)
522 def cb_listbox_settings_remove(self
, container
, object, user_data
=None):
523 if len(container
.get_children()) == 0:
524 self
.toolbutton_settings_remove
.set_sensitive(False)
527 def cb_listbox_settings_row_selected(self
, listbox
, row
, user_data
=None):
529 self
._last
_selected
_setting
_row
.append(row
)
531 def cb_listbox_settings_row_activated(self
, listbox
, row
, user_data
=None):
532 if row
== self
.listboxrow_settings_admin
:
533 self
.__popover
_toggle
(self
.popover_admin
)
534 elif row
== self
.listboxrow_settings_macspoof
:
535 self
.__popover
_toggle
(self
.popover_macspoof
)
536 elif row
== self
.listboxrow_settings_network
:
537 self
.__popover
_toggle
(self
.popover_network
)
538 elif row
== self
.listboxrow_settings_camouflage
:
539 self
.__popover
_toggle
(self
.popover_camouflage
)
542 def cb_liststore_filtered_visible_func(self
, model
, treeiter
, searchentry
):
543 search_query
= searchentry
.get_text().lower()
544 value
= model
.get_value(treeiter
, 1).lower()
547 elif search_query
in value
:
552 def cb_popover_text_closed(self
, popover
, user_data
=None):
553 self
.listbox_language
.unselect_all()
556 def cb_popover_keyboard_closed(self
, popover
, user_data
=None):
557 self
.listbox_language
.unselect_all()
560 def cb_popover_formats_closed(self
, popover
, user_data
=None):
561 self
.listbox_language
.unselect_all()
564 def cb_popover_tz_closed(self
, popover
, user_data
=None):
565 self
.listbox_language
.unselect_all()
568 def cb_popover_admin_closed(self
, popover
, user_data
=None):
569 self
.listbox_settings
.unselect_all()
572 def cb_popover_macspoof_closed(self
, popover
, user_data
=None):
573 self
.listbox_settings
.unselect_all()
576 def cb_popover_network_closed(self
, popover
, user_data
=None):
577 self
.listbox_settings
.unselect_all()
580 def cb_popover_camouflage_closed(self
, popover
, user_data
=None):
581 self
.listbox_settings
.unselect_all()
584 def cb_searchentry_formats_search_changed(self
, widget
, user_data
=None):
585 self
.liststore_formats_filtered
.refilter()
588 def cb_searchentry_keyboard_search_changed(self
, widget
, user_data
=None):
589 self
.liststore_keyboard_filtered
.refilter()
592 def cb_searchentry_text_search_changed(self
, widget
, user_data
=None):
593 self
.liststore_text_filtered
.refilter()
596 def cb_searchentry_tz_search_changed(self
, widget
, user_data
=None):
597 self
.liststore_tz_filtered
.refilter()
600 def cb_switch_camouflage_active(self
, switch
, pspec
, user_data
=None):
601 self
.label_settings_camouflage_value
.set_text(
602 self
.__get
_on
_off
_string
(switch
.get_state()))
603 if hasattr(self
, 'popover_camouflage'):
604 self
.popover_camouflage
.set_visible(False)
606 def cb_switch_macspoof_active(self
, switch
, pspec
, user_data
=None):
607 self
.label_settings_macspoof_value
.set_text(
608 self
.__get
_on
_off
_string
(switch
.get_state()))
609 if hasattr(self
, 'popover_macspoof'):
610 self
.popover_macspoof
.set_visible(False)
612 def cb_timeout_storage_unlocked(self
, user_data
=None):
613 self
.button_storage_spinner
.set_visible(False)
614 self
.entry_storage_passphrase
.set_visible(False)
615 self
.button_storage_unlock
.set_visible(False)
616 self
.image_storage_state
.set_from_icon_name('tails-unlocked',
618 self
.button_storage_state
.set_visible(True)
619 self
.button_storage_lock
.set_visible(True)
622 def cb_toolbutton_settings_add_clicked(self
, user_data
=None):
623 self
.stack_add_setting
.set_visible_child_name('setting-type')
624 self
.button_add_setting_back
.set_visible(False)
625 self
.button_add_setting_add
.set_visible(False)
626 response
= self
.dialog_add_setting
.run()
627 if response
== Gtk
.ResponseType
.YES
:
628 row
= self
.listbox_add_setting
.get_selected_row()
629 self
.listbox_add_setting
.remove(row
)
630 self
.listbox_settings
.add(row
)
631 self
.dialog_add_setting
.set_visible(False)
632 if row
== self
.listboxrow_settings_admin
:
633 self
.stack_add_setting
.remove(self
.box_admin_popover
)
634 self
.popover_admin
= self
.__add
_popover
(
635 self
.listboxrow_settings_admin
,
636 self
.box_admin_popover
,
637 closed_cb
=self
.cb_popover_admin_closed
)
638 elif row
== self
.listboxrow_settings_macspoof
:
639 self
.stack_add_setting
.remove(self
.box_macspoof_popover
)
640 self
.popover_macspoof
= self
.__add
_popover
(
641 self
.listboxrow_settings_macspoof
,
642 self
.box_macspoof_popover
,
643 closed_cb
=self
.cb_popover_macspoof_closed
)
644 elif row
== self
.listboxrow_settings_network
:
645 self
.stack_add_setting
.remove(self
.box_network_popover
)
646 self
.popover_network
= self
.__add
_popover
(
647 self
.listboxrow_settings_network
,
648 self
.box_network_popover
,
649 closed_cb
=self
.cb_popover_network_closed
)
650 elif row
== self
.listboxrow_settings_camouflage
:
651 self
.stack_add_setting
.remove(self
.box_camouflage_popover
)
652 self
.popover_camouflage
= self
.__add
_popover
(
653 self
.listboxrow_settings_camouflage
,
654 self
.box_camouflage_popover
,
655 closed_cb
=self
.cb_popover_camouflage_closed
)
656 self
.listbox_settings
.unselect_all()
657 if len(self
.listbox_add_setting
.get_children()) == 0:
658 self
.toolbutton_settings_add
.set_sensitive(False)
659 self
.dialog_add_setting
.set_visible(False)
660 self
.dialog_add_setting
.set_visible(False)
663 def cb_toolbutton_settings_remove_clicked(self
, user_data
=None):
665 row
= self
._last
_selected
_setting
_row
.pop()
668 self
.listbox_settings
.remove(row
)
669 self
.listbox_add_setting
.add(row
)
672 def cb_treeview_formats_row_activated(self
, treeview
, path
, column
, user_data
=None):
673 treemodel
= treeview
.get_model()
674 value
= treemodel
.get_value(treemodel
.get_iter(path
), 1)
675 self
.label_formats_value
.set_text(value
)
676 self
.label_language_header_status
.set_text(_("Custom settings"))
677 self
.popover_formats
.set_visible(False)
679 def cb_treeview_keyboard_row_activated(self
, treeview
, path
, column
, user_data
=None):
680 treemodel
= treeview
.get_model()
681 value
= treemodel
.get_value(treemodel
.get_iter(path
), 1)
682 self
.label_keyboard_value
.set_text(value
)
683 self
.label_language_header_status
.set_text(_("Custom settings"))
684 self
.popover_keyboard
.set_visible(False)
686 def cb_treeview_text_row_activated(self
, treeview
, path
, column
, user_data
=None):
687 treemodel
= treeview
.get_model()
688 value
= treemodel
.get_value(treemodel
.get_iter(path
), 1)
689 self
.label_text_value
.set_text(value
)
690 self
.label_language_header_status
.set_text(_("Custom settings"))
691 self
.popover_text
.set_visible(False)
693 def cb_treeview_tz_row_activated(self
, treeview
, path
, column
, user_data
=None):
694 treemodel
= treeview
.get_model()
695 value
= treemodel
.get_value(treemodel
.get_iter(path
), 1)
696 self
.label_tz_value
.set_text(value
)
697 self
.label_language_header_status
.set_text(_("Custom settings"))
698 self
.popover_tz
.set_visible(False)
700 class GreeterBackgroundWindow(Gtk
.ApplicationWindow
):
702 def __init__(self
, app
):
703 Gtk
.Window
.__init
__(self
, title
=APPLICATION_TITLE
, application
=app
)
704 self
.set_icon_name(APPLICATION_ICON_NAME
)
705 self
.override_background_color(
706 Gtk
.StateFlags
.NORMAL
, Gdk
.RGBA(0, 0, 0, 1))
708 class GreeterApplication(Gtk
.Application
):
711 Gtk
.Application
.__init
__(self
)
712 self
.set_application_id
= 'org.boum.tails.greeter'
714 def do_activate(self
):
715 backgroundwindow
= GreeterBackgroundWindow(self
)
716 backgroundwindow
.maximize()
717 appwindow
= GreeterMainWindow(self
)
718 appwindow
.set_transient_for(backgroundwindow
)
720 if not os
.getenv('DEBUG'):
721 backgroundwindow
.show()
724 def do_startup(self
):
725 Gtk
.Application
.do_startup(self
)
727 app
= GreeterApplication()
728 exit_status
= app
.run(sys
.argv
)
729 sys
.exit(exit_status
)