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 a select mode for adding/removing privacy settings
26 # * add an icon representing encrypted storage
27 ################################################################################
34 gi
.require_version('GLib', '2.0')
35 from gi
.repository
import GLib
36 gi
.require_version('Gdk', '3.0')
37 from gi
.repository
import Gdk
38 gi
.require_version('Gtk', '3.0')
39 from gi
.repository
import Gtk
43 # To ease future internationalisation
46 UI_FILE
= 'greeter.ui'
48 APPLICATION_ICON_NAME
= 'gdm-setup'
49 APPLICATION_TITLE
= 'Welcome to Tails!'
51 class GreeterMainWindow(Gtk
.ApplicationWindow
):
53 def __init__(self
, app
):
54 Gtk
.Window
.__init
__(self
, title
=APPLICATION_TITLE
, application
=app
)
56 self
.set_icon_name(APPLICATION_ICON_NAME
)
58 self
.set_position(Gtk
.WindowPosition
.CENTER
)
59 self
._last
_selected
_setting
_row
= []
62 # Load UI interface definition
63 self
._builder
= Gtk
.Builder()
64 self
._builder
.add_from_file(UI_FILE
)
65 self
._builder
.connect_signals(self
)
67 # Map interface objects
68 box_main
= self
._builder
.get_object('box_main')
70 self
.label_language_header_status
= \
71 self
._builder
.get_object('label_language_header_status')
72 checkbutton_language_save
= \
73 self
._builder
.get_object('checkbutton_language_save')
74 self
.listbox_language
= self
._builder
.get_object('listbox_language')
75 self
.listboxrow_text
= self
._builder
.get_object('listboxrow_text')
76 self
.label_text_value
= self
._builder
.get_object('label_text_value')
77 self
.listboxrow_keyboard
= self
._builder
.get_object('listboxrow_keyboard')
78 self
.label_keyboard_value
= self
._builder
.get_object('label_keyboard_value')
79 self
.listboxrow_formats
= self
._builder
.get_object('listboxrow_formats')
80 self
.label_formats_value
= self
._builder
.get_object('label_formats_value')
81 self
.listboxrow_tz
= self
._builder
.get_object('listboxrow_tz')
82 self
.label_tz_value
= self
._builder
.get_object('label_tz_value')
84 self
.checkbutton_storage_show_passphrase
= \
85 self
._builder
.get_object('checkbutton_storage_show_passphrase')
86 self
.button_storage_configure
= \
87 self
._builder
.get_object('button_storage_configure')
88 self
.button_storage_state
= self
._builder
.get_object('button_storage_state')
89 self
.image_storage_state
= self
._builder
.get_object('image_storage_state')
90 self
.button_storage_spinner
= \
91 self
._builder
.get_object('button_storage_spinner')
92 self
.spinner_storage_unlock
= \
93 self
._builder
.get_object('spinner_storage_unlock')
94 self
.entry_storage_passphrase
= \
95 self
._builder
.get_object('entry_storage_passphrase')
96 self
.button_storage_lock
= self
._builder
.get_object('button_storage_lock')
97 self
.button_storage_unlock
=self
._builder
.get_object('button_storage_unlock')
98 self
.box_storage_unlock
= self
._builder
.get_object('box_storage_unlock')
100 checkbutton_settings_save
= \
101 self
._builder
.get_object('checkbutton_settings_save')
102 self
.listbox_settings
= self
._builder
.get_object('listbox_settings')
103 self
.listboxrow_settings_admin
= \
104 self
._builder
.get_object('listboxrow_settings_admin')
105 self
.label_settings_admin_value
= \
106 self
._builder
.get_object('label_settings_admin_value')
107 self
.listboxrow_settings_macspoof
= \
108 self
._builder
.get_object('listboxrow_settings_macspoof')
109 self
.label_settings_macspoof_value
= \
110 self
._builder
.get_object('label_settings_macspoof_value')
111 self
.listboxrow_settings_network
= \
112 self
._builder
.get_object('listboxrow_settings_network')
113 self
.label_settings_network_value
= \
114 self
._builder
.get_object('label_settings_network_value')
115 self
.listboxrow_settings_camouflage
= \
116 self
._builder
.get_object('listboxrow_settings_camouflage')
117 self
.label_settings_camouflage_value
= \
118 self
._builder
.get_object('label_settings_camouflage_value')
120 label_settings_default
= \
121 self
._builder
.get_object('label_settings_default')
122 self
.toolbutton_settings_remove
= \
123 self
._builder
.get_object('toolbutton_settings_remove')
124 self
.toolbutton_settings_add
= \
125 self
._builder
.get_object('toolbutton_settings_add')
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 self
.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 self
.box_macspoof_popover
= self
._builder
.get_object('box_macspoof_popover')
151 switch_macspoof
= self
._builder
.get_object('switch_macspoof')
152 self
.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 self
.box_camouflage_popover
= \
168 self
._builder
.get_object('box_camouflage_popover')
169 switch_camouflage
= self
._builder
.get_object('switch_camouflage')
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
)
182 headerbar
= Gtk
.HeaderBar()
183 headerbar_sizegroup
= Gtk
.SizeGroup(Gtk
.SizeGroupMode
.HORIZONTAL
)
185 button_restart
= Gtk
.Button()
186 button_restart
.set_label(_("Restart"))
187 button_restart
.connect('clicked', self
.cb_button_restart_clicked
)
188 headerbar_sizegroup
.add_widget(button_restart
)
189 headerbar
.pack_start(button_restart
)
191 button_start
= Gtk
.Button()
192 button_start
.set_label(_("Start Tails"))
193 Gtk
.StyleContext
.add_class(button_start
.get_style_context(),
195 button_start
.connect('clicked', self
.cb_button_start_clicked
)
196 headerbar_sizegroup
.add_widget(button_start
)
197 headerbar
.pack_end(button_start
)
199 button_tour
= Gtk
.Button()
200 button_tour
.set_label(_("Take a Tour"))
201 button_tour
.connect('clicked', self
.cb_button_tour_clicked
)
202 headerbar_sizegroup
.add_widget(button_tour
)
203 headerbar
.pack_end(button_tour
)
207 # Align CheckBoxes to the left
208 for cb
in [checkbutton_language_save
,
209 self
.checkbutton_storage_show_passphrase
,
210 checkbutton_settings_save
]:
211 cb
.set_direction(Gtk
.TextDirection
.RTL
)
214 self
.popover_text
= self
.__add
_popover
(
215 self
.listboxrow_text
,
217 closed_cb
=self
.cb_popover_text_closed
)
218 self
.popover_keyboard
= self
.__add
_popover
(
219 self
.listboxrow_keyboard
,
220 box_keyboard_popover
,
221 closed_cb
=self
.cb_popover_keyboard_closed
)
222 self
.popover_formats
= self
.__add
_popover
(
223 self
.listboxrow_formats
,
225 closed_cb
=self
.cb_popover_formats_closed
)
226 self
.popover_tz
= self
.__add
_popover
(
229 closed_cb
=self
.cb_popover_tz_closed
)
231 # Add children to ApplicationWindow
233 self
.set_titlebar(headerbar
)
235 # Create "Add Privacy Setting" dialog
236 self
.dialog_add_setting
= Gtk
.Dialog(use_header_bar
=True)
237 self
.dialog_add_setting
.set_transient_for(self
)
238 self
.dialog_add_setting
.set_title(_("Add Privacy Setting"))
239 self
.dialog_add_setting
.set_default_size(-1, 400)
241 dialog_add_setting_sizegroup
= Gtk
.SizeGroup(Gtk
.SizeGroupMode
.HORIZONTAL
)
243 self
.button_add_setting_cancel
= self
.dialog_add_setting
.add_button(
244 _("Cancel"), Gtk
.ResponseType
.CANCEL
)
245 dialog_add_setting_sizegroup
.add_widget(self
.button_add_setting_cancel
)
247 self
.button_add_setting_add
= self
.dialog_add_setting
.add_button(
248 _("Add"), Gtk
.ResponseType
.YES
)
249 Gtk
.StyleContext
.add_class(self
.button_add_setting_add
.get_style_context(),
251 dialog_add_setting_sizegroup
.add_widget(self
.button_add_setting_add
)
253 self
.button_add_setting_add
.set_visible(False)
254 self
.button_add_setting_back
= Gtk
.Button
.new_with_label(_("Back"))
255 self
.button_add_setting_back
.set_visible(False)
256 self
.button_add_setting_back
.connect(
257 'clicked', self
.cb_button_add_setting_back_clicked
, None)
258 dialog_add_setting_sizegroup
.add_widget(self
.button_add_setting_back
)
259 self
.dialog_add_setting
.get_header_bar().pack_end(self
.button_add_setting_back
)
261 self
.stack_add_setting
= Gtk
.Stack()
262 self
.stack_add_setting
.add_named(self
.listbox_add_setting
, "setting-type")
263 self
.listbox_add_setting
.set_valign(Gtk
.Align
.FILL
)
264 self
.listbox_add_setting
.set_vexpand(True)
265 self
.stack_add_setting
.set_visible(True)
266 self
.stack_add_setting
.set_transition_type(
267 Gtk
.StackTransitionType
.SLIDE_LEFT_RIGHT
)
268 self
.dialog_add_setting
.get_content_area().add(self
.stack_add_setting
)
270 # Fill language treeviews
271 for language
in greeterdata
.languages
:
272 liststore_text
.append(language
)
273 self
.__fill
_tv
("Text Language", treeview_text
)
274 self
.liststore_text_filtered
= liststore_text
.filter_new()
275 self
.liststore_text_filtered
.set_visible_func(
276 self
.cb_liststore_filtered_visible_func
, data
=searchentry_text
)
277 treeview_text
.set_model(self
.liststore_text_filtered
)
279 for layout
in greeterdata
.layouts
:
280 liststore_keyboard
.append(layout
)
281 self
.__fill
_tv
("Keyboard Layout", treeview_keyboard
)
282 self
.liststore_keyboard_filtered
= liststore_keyboard
.filter_new()
283 self
.liststore_keyboard_filtered
.set_visible_func(
284 self
.cb_liststore_filtered_visible_func
, data
=searchentry_keyboard
)
285 treeview_keyboard
.set_model(self
.liststore_keyboard_filtered
)
287 for locale
in greeterdata
.locales
:
288 liststore_formats
.append(locale
)
289 self
.__fill
_tv
("Format", treeview_formats
)
290 self
.liststore_formats_filtered
= liststore_formats
.filter_new()
291 self
.liststore_formats_filtered
.set_visible_func(
292 self
.cb_liststore_filtered_visible_func
, data
=searchentry_formats
)
293 treeview_formats
.set_model(self
.liststore_formats_filtered
)
295 for timezone
in greeterdata
.timezones
:
296 liststore_tz
.append(timezone
)
297 self
.__fill
_tv
("Time Zone", treeview_tz
)
298 self
.liststore_tz_filtered
= liststore_tz
.filter_new()
299 self
.liststore_tz_filtered
.set_visible_func(
300 self
.cb_liststore_filtered_visible_func
, data
=searchentry_tz
)
301 treeview_tz
.set_model(self
.liststore_tz_filtered
)
303 # Storage configuration/unlocking
304 if os
.getenv('TAILS_HAS_PERSISTENCE'):
305 self
.button_storage_configure
.set_visible(False)
306 self
.checkbutton_storage_show_passphrase
.set_visible(True)
307 self
.box_storage_unlock
.set_visible(True)
308 self
.button_storage_state
.set_visible(True)
309 self
.entry_storage_passphrase
.set_visible(True)
310 self
.button_storage_unlock
.set_visible(True)
313 switch_macspoof
.connect('notify::active', self
.cb_switch_macspoof_active
)
314 switch_camouflage
.connect('notify::active', self
.cb_switch_camouflage_active
)
316 def setting_admin_check(self
):
317 password
= self
.entry_admin_password
.get_text()
318 verify
= self
.entry_admin_verify
.get_text()
319 if verify
and verify
== password
:
320 icon
= 'emblem-ok-symbolic'
321 elif verify
and not (verify
== password
):
322 icon
= 'dialog-warning-symbolic'
325 self
.entry_admin_verify
.set_icon_from_icon_name(
326 Gtk
.EntryIconPosition
.SECONDARY
, icon
)
327 return (verify
== password
)
329 def setting_admin_apply(self
):
330 if self
.setting_admin_check():
331 self
.label_settings_admin_value
.set_text(
332 self
.__get
_on
_off
_string
(self
.entry_admin_password
.get_text()))
333 if hasattr(self
, 'popover_admin'):
334 self
.popover_admin
.set_visible(False)
342 def __add_popover(widget
, content
, closed_cb
=None):
343 popover
= Gtk
.Popover
.new(widget
)
344 popover
.set_position(Gtk
.PositionType
.BOTTOM
)
347 popover
.connect('closed', closed_cb
)
351 def __fill_tv (name
, treeview
):
352 assert isinstance(name
, str)
353 assert isinstance(treeview
, Gtk
.TreeView
)
354 renderer
= Gtk
.CellRendererText()
355 column
= Gtk
.TreeViewColumn(name
, renderer
, text
=1)
356 treeview
.append_column(column
)
359 def __popover_toggle(popover
):
360 if popover
.get_visible():
361 popover
.set_visible(False)
363 popover
.set_visible(True)
366 def __get_on_off_string(value
):
374 def cb_button_add_setting_back_clicked(self
, widget
, user_data
=None):
375 self
.stack_add_setting
.set_visible_child_name('setting-type')
376 self
.stack_add_setting
.remove(
377 self
.stack_add_setting
.get_child_by_name('setting-details'))
380 def cb_button_help_clicked(self
, widget
, user_data
=None):
381 dialog
= Gtk
.MessageDialog(
383 Gtk
.DialogFlags
.DESTROY_WITH_PARENT
,
384 Gtk
.MessageType
.INFO
,
385 Gtk
.ButtonsType
.CLOSE
,
386 _("You would see the help page for this element."))
391 def cb_button_restart_clicked(self
, widget
, user_data
=None):
395 def cb_button_start_clicked(self
, widget
, user_data
=None):
399 def cb_button_storage_configure_clicked(self
, user_data
=None):
400 dialog
= Gtk
.MessageDialog(
402 Gtk
.DialogFlags
.DESTROY_WITH_PARENT
,
403 Gtk
.MessageType
.INFO
,
404 Gtk
.ButtonsType
.CLOSE
,
405 _("You would be able to set up an encrypted storage."))
410 def cb_button_tour_clicked(self
, user_data
=None):
411 dialog
= Gtk
.MessageDialog(
413 Gtk
.DialogFlags
.DESTROY_WITH_PARENT
,
414 Gtk
.MessageType
.INFO
,
415 Gtk
.ButtonsType
.CLOSE
,
416 _("You would be guided through options by a wizard."))
421 def cb_button_storage_lock_clicked(self
, widget
, user_data
=None):
422 self
.button_storage_lock
.set_visible(False)
423 self
.checkbutton_storage_show_passphrase
.set_visible(True)
424 self
.box_storage_unlock
.set_visible(True)
425 self
.button_storage_state
.set_visible(True)
426 self
.image_storage_state
.set_from_icon_name('tails-locked',
428 self
.entry_storage_passphrase
.set_visible(True)
429 self
.entry_storage_passphrase
.set_sensitive(True)
430 self
.button_storage_unlock
.set_visible(True)
431 self
.button_storage_unlock
.set_sensitive(True)
432 self
.button_storage_unlock
.set_label(_("Unlock"))
435 def cb_button_storage_unlock_clicked(self
, widget
, user_data
=None):
436 self
.checkbutton_storage_show_passphrase
.set_visible(False)
437 self
.entry_storage_passphrase
.set_sensitive(False)
438 self
.button_storage_unlock
.set_sensitive(False)
439 self
.button_storage_unlock
.set_label(_("Unlocking"))
440 self
.button_storage_state
.set_visible(False)
441 self
.button_storage_spinner
.set_visible(True)
442 GLib
.timeout_add_seconds(2, self
.cb_timeout_storage_unlocked
, user_data
=None)
445 def cb_checkbutton_storage_show_passphrase_toggled(self
, widget
, user_data
=None):
446 self
.entry_storage_passphrase
.set_visibility(widget
.get_active())
448 def cb_entry_admin_changed(self
, editable
, user_data
=None):
449 self
.setting_admin_check()
452 def cb_entry_admin_focus_out_event(self
, widget
, event
, user_data
=None):
453 self
.setting_admin_apply()
456 def cb_entry_admin_password_activate(self
, widget
, user_data
=None):
457 self
.entry_admin_verify
.grab_focus()
460 def cb_entry_admin_verify_activate(self
, widget
, user_data
=None):
461 self
.setting_admin_apply()
464 def cb_listbox_add_setting_focus(self
, widget
, direction
, user_data
=None):
465 # Workaround autoselection of 1st item on focus
466 self
.listbox_add_setting
.unselect_all()
469 def cb_listbox_add_setting_row_activated(self
, listbox
, row
, user_data
=None):
470 if row
== self
.listboxrow_settings_admin
:
471 box
= self
.box_admin_popover
472 elif row
== self
.listboxrow_settings_macspoof
:
473 box
= self
.box_macspoof_popover
474 elif row
== self
.listboxrow_settings_network
:
475 box
= self
.box_network_popover
476 elif row
== self
.listboxrow_settings_camouflage
:
477 box
= self
.box_camouflage_popover
478 else: # this happens when the row gets unselected
480 self
.stack_add_setting
.add_named(box
, 'setting-details')
481 self
.stack_add_setting
.set_visible_child_name('setting-details')
482 self
.button_add_setting_back
.set_visible(True)
483 self
.button_add_setting_add
.set_visible(True)
486 def cb_listbox_language_row_activated(self
, listbox
, row
, user_data
=None):
487 if row
== self
.listboxrow_text
:
488 self
.__popover
_toggle
(self
.popover_text
)
489 elif row
== self
.listboxrow_keyboard
:
490 self
.__popover
_toggle
(self
.popover_keyboard
)
491 elif row
== self
.listboxrow_formats
:
492 self
.__popover
_toggle
(self
.popover_formats
)
493 elif row
== self
.listboxrow_tz
:
494 self
.__popover
_toggle
(self
.popover_tz
)
497 def cb_listbox_network_row_activated(self
, listbox
, row
, user_data
=None):
498 if row
== self
.listboxrow_network_clear
:
499 self
.image_network_clear
.set_visible(True)
500 self
.image_network_specific
.set_visible(False)
501 self
.image_network_off
.set_visible(False)
502 self
.label_settings_network_value
.set_text(_("Direct"))
503 elif row
== self
.listboxrow_network_specific
:
504 self
.image_network_specific
.set_visible(True)
505 self
.image_network_clear
.set_visible(False)
506 self
.image_network_off
.set_visible(False)
507 self
.label_settings_network_value
.set_text(_("Censored"))
508 elif row
== self
.listboxrow_network_off
:
509 self
.image_network_off
.set_visible(True)
510 self
.image_network_specific
.set_visible(False)
511 self
.image_network_clear
.set_visible(False)
512 self
.label_settings_network_value
.set_text(_("Off"))
513 if hasattr(self
, 'popover_network'):
514 self
.popover_network
.set_visible(False)
517 def cb_listbox_settings_add(self
, listbox
, row
, user_data
=None):
518 self
._last
_selected
_setting
_row
.append(row
)
519 if len(listbox
.get_children()) > 0:
520 self
.toolbutton_settings_remove
.set_sensitive(True)
523 def cb_listbox_settings_remove(self
, container
, object, user_data
=None):
524 if len(container
.get_children()) == 0:
525 self
.toolbutton_settings_remove
.set_sensitive(False)
528 def cb_listbox_settings_row_selected(self
, listbox
, row
, user_data
=None):
530 self
._last
_selected
_setting
_row
.append(row
)
532 def cb_listbox_settings_row_activated(self
, listbox
, row
, user_data
=None):
533 if row
== self
.listboxrow_settings_admin
:
534 self
.__popover
_toggle
(self
.popover_admin
)
535 elif row
== self
.listboxrow_settings_macspoof
:
536 self
.__popover
_toggle
(self
.popover_macspoof
)
537 elif row
== self
.listboxrow_settings_network
:
538 self
.__popover
_toggle
(self
.popover_network
)
539 elif row
== self
.listboxrow_settings_camouflage
:
540 self
.__popover
_toggle
(self
.popover_camouflage
)
543 def cb_liststore_filtered_visible_func(self
, model
, treeiter
, searchentry
):
544 search_query
= searchentry
.get_text().lower()
545 value
= model
.get_value(treeiter
, 1).lower()
548 elif search_query
in value
:
553 def cb_popover_text_closed(self
, popover
, user_data
=None):
554 self
.listbox_language
.unselect_all()
557 def cb_popover_keyboard_closed(self
, popover
, user_data
=None):
558 self
.listbox_language
.unselect_all()
561 def cb_popover_formats_closed(self
, popover
, user_data
=None):
562 self
.listbox_language
.unselect_all()
565 def cb_popover_tz_closed(self
, popover
, user_data
=None):
566 self
.listbox_language
.unselect_all()
569 def cb_popover_admin_closed(self
, popover
, user_data
=None):
570 self
.listbox_settings
.unselect_all()
573 def cb_popover_macspoof_closed(self
, popover
, user_data
=None):
574 self
.listbox_settings
.unselect_all()
577 def cb_popover_network_closed(self
, popover
, user_data
=None):
578 self
.listbox_settings
.unselect_all()
581 def cb_popover_camouflage_closed(self
, popover
, user_data
=None):
582 self
.listbox_settings
.unselect_all()
585 def cb_searchentry_formats_search_changed(self
, widget
, user_data
=None):
586 self
.liststore_formats_filtered
.refilter()
589 def cb_searchentry_keyboard_search_changed(self
, widget
, user_data
=None):
590 self
.liststore_keyboard_filtered
.refilter()
593 def cb_searchentry_text_search_changed(self
, widget
, user_data
=None):
594 self
.liststore_text_filtered
.refilter()
597 def cb_searchentry_tz_search_changed(self
, widget
, user_data
=None):
598 self
.liststore_tz_filtered
.refilter()
601 def cb_switch_camouflage_active(self
, switch
, pspec
, user_data
=None):
602 self
.label_settings_camouflage_value
.set_text(
603 self
.__get
_on
_off
_string
(switch
.get_state()))
604 if hasattr(self
, 'popover_camouflage'):
605 self
.popover_camouflage
.set_visible(False)
607 def cb_switch_macspoof_active(self
, switch
, pspec
, user_data
=None):
608 self
.label_settings_macspoof_value
.set_text(
609 self
.__get
_on
_off
_string
(switch
.get_state()))
610 if hasattr(self
, 'popover_macspoof'):
611 self
.popover_macspoof
.set_visible(False)
613 def cb_timeout_storage_unlocked(self
, user_data
=None):
614 self
.button_storage_spinner
.set_visible(False)
615 self
.entry_storage_passphrase
.set_visible(False)
616 self
.button_storage_unlock
.set_visible(False)
617 self
.image_storage_state
.set_from_icon_name('tails-unlocked',
619 self
.button_storage_state
.set_visible(True)
620 self
.button_storage_lock
.set_visible(True)
623 def cb_toolbutton_settings_add_clicked(self
, user_data
=None):
624 self
.stack_add_setting
.set_visible_child_name('setting-type')
625 self
.button_add_setting_back
.set_visible(False)
626 self
.button_add_setting_add
.set_visible(False)
627 response
= self
.dialog_add_setting
.run()
628 if response
== Gtk
.ResponseType
.YES
:
629 row
= self
.listbox_add_setting
.get_selected_row()
630 self
.listbox_add_setting
.remove(row
)
631 self
.listbox_settings
.add(row
)
632 self
.dialog_add_setting
.set_visible(False)
633 if row
== self
.listboxrow_settings_admin
:
634 self
.stack_add_setting
.remove(self
.box_admin_popover
)
635 self
.popover_admin
= self
.__add
_popover
(
636 self
.listboxrow_settings_admin
,
637 self
.box_admin_popover
,
638 closed_cb
=self
.cb_popover_admin_closed
)
639 elif row
== self
.listboxrow_settings_macspoof
:
640 self
.stack_add_setting
.remove(self
.box_macspoof_popover
)
641 self
.popover_macspoof
= self
.__add
_popover
(
642 self
.listboxrow_settings_macspoof
,
643 self
.box_macspoof_popover
,
644 closed_cb
=self
.cb_popover_macspoof_closed
)
645 elif row
== self
.listboxrow_settings_network
:
646 self
.stack_add_setting
.remove(self
.box_network_popover
)
647 self
.popover_network
= self
.__add
_popover
(
648 self
.listboxrow_settings_network
,
649 self
.box_network_popover
,
650 closed_cb
=self
.cb_popover_network_closed
)
651 elif row
== self
.listboxrow_settings_camouflage
:
652 self
.stack_add_setting
.remove(self
.box_camouflage_popover
)
653 self
.popover_camouflage
= self
.__add
_popover
(
654 self
.listboxrow_settings_camouflage
,
655 self
.box_camouflage_popover
,
656 closed_cb
=self
.cb_popover_camouflage_closed
)
657 self
.listbox_settings
.unselect_all()
658 if len(self
.listbox_add_setting
.get_children()) == 0:
659 self
.toolbutton_settings_add
.set_sensitive(False)
660 self
.dialog_add_setting
.set_visible(False)
661 self
.dialog_add_setting
.set_visible(False)
664 def cb_toolbutton_settings_remove_clicked(self
, user_data
=None):
666 row
= self
._last
_selected
_setting
_row
.pop()
669 self
.listbox_settings
.remove(row
)
670 self
.listbox_add_setting
.add(row
)
673 def cb_treeview_formats_row_activated(self
, treeview
, path
, column
, user_data
=None):
674 treemodel
= treeview
.get_model()
675 value
= treemodel
.get_value(treemodel
.get_iter(path
), 1)
676 self
.label_formats_value
.set_text(value
)
677 self
.label_language_header_status
.set_text(_("Custom settings"))
678 self
.popover_formats
.set_visible(False)
680 def cb_treeview_keyboard_row_activated(self
, treeview
, path
, column
, user_data
=None):
681 treemodel
= treeview
.get_model()
682 value
= treemodel
.get_value(treemodel
.get_iter(path
), 1)
683 self
.label_keyboard_value
.set_text(value
)
684 self
.label_language_header_status
.set_text(_("Custom settings"))
685 self
.popover_keyboard
.set_visible(False)
687 def cb_treeview_text_row_activated(self
, treeview
, path
, column
, user_data
=None):
688 treemodel
= treeview
.get_model()
689 value
= treemodel
.get_value(treemodel
.get_iter(path
), 1)
690 self
.label_text_value
.set_text(value
)
691 self
.label_language_header_status
.set_text(_("Custom settings"))
692 self
.popover_text
.set_visible(False)
694 def cb_treeview_tz_row_activated(self
, treeview
, path
, column
, user_data
=None):
695 treemodel
= treeview
.get_model()
696 value
= treemodel
.get_value(treemodel
.get_iter(path
), 1)
697 self
.label_tz_value
.set_text(value
)
698 self
.label_language_header_status
.set_text(_("Custom settings"))
699 self
.popover_tz
.set_visible(False)
701 class GreeterBackgroundWindow(Gtk
.ApplicationWindow
):
703 def __init__(self
, app
):
704 Gtk
.Window
.__init
__(self
, title
=APPLICATION_TITLE
, application
=app
)
705 self
.set_icon_name(APPLICATION_ICON_NAME
)
706 self
.override_background_color(
707 Gtk
.StateFlags
.NORMAL
, Gdk
.RGBA(0, 0, 0, 1))
709 class GreeterApplication(Gtk
.Application
):
712 Gtk
.Application
.__init
__(self
)
713 self
.set_application_id
= 'org.boum.tails.greeter'
715 def do_activate(self
):
716 backgroundwindow
= GreeterBackgroundWindow(self
)
717 backgroundwindow
.maximize()
718 appwindow
= GreeterMainWindow(self
)
719 appwindow
.set_transient_for(backgroundwindow
)
721 if not os
.getenv('DEBUG'):
722 backgroundwindow
.show()
725 def do_startup(self
):
726 Gtk
.Application
.do_startup(self
)
728 app
= GreeterApplication()
729 exit_status
= app
.run(sys
.argv
)
730 sys
.exit(exit_status
)