Check for "reader" and "reader" options
Andrew P.
9 years ago
1377 | 1377 | <property name="column_spacing">8</property> |
1378 | 1378 | <child> |
1379 | 1379 | <object class="GtkCheckButton" id="greeter_keyboard_use"> |
1380 | <property name="label" translatable="yes" context="greeter|option|keyboard">Keyboard</property> | |
1381 | 1380 | <property name="visible">True</property> |
1382 | 1381 | <property name="can_focus">True</property> |
1383 | 1382 | <property name="receives_default">False</property> |
1384 | 1383 | <property name="xalign">0</property> |
1385 | 1384 | <property name="draw_indicator">True</property> |
1385 | <child> | |
1386 | <object class="GtkBox" id="box14"> | |
1387 | <property name="visible">True</property> | |
1388 | <property name="can_focus">False</property> | |
1389 | <child> | |
1390 | <object class="GtkLabel" id="label6"> | |
1391 | <property name="visible">True</property> | |
1392 | <property name="can_focus">False</property> | |
1393 | <property name="label" translatable="yes" context="greeter|option|keyboard">Keyboard</property> | |
1394 | </object> | |
1395 | <packing> | |
1396 | <property name="expand">False</property> | |
1397 | <property name="fill">True</property> | |
1398 | <property name="position">0</property> | |
1399 | </packing> | |
1400 | </child> | |
1401 | <child> | |
1402 | <object class="GtkImage" id="greeter_keyboard_error"> | |
1403 | <property name="can_focus">False</property> | |
1404 | <property name="yalign">0</property> | |
1405 | <property name="pixel_size">12</property> | |
1406 | <property name="icon_name">dialog-warning</property> | |
1407 | <property name="icon_size">1</property> | |
1408 | </object> | |
1409 | <packing> | |
1410 | <property name="expand">False</property> | |
1411 | <property name="fill">True</property> | |
1412 | <property name="position">1</property> | |
1413 | </packing> | |
1414 | </child> | |
1415 | </object> | |
1416 | </child> | |
1386 | 1417 | </object> |
1387 | 1418 | <packing> |
1388 | 1419 | <property name="left_attach">0</property> |
1391 | 1422 | </child> |
1392 | 1423 | <child> |
1393 | 1424 | <object class="GtkCheckButton" id="greeter_reader_use"> |
1394 | <property name="label" translatable="yes" context="greeter|option|reader">Reader</property> | |
1395 | 1425 | <property name="visible">True</property> |
1396 | 1426 | <property name="can_focus">True</property> |
1397 | 1427 | <property name="receives_default">False</property> |
1398 | 1428 | <property name="xalign">0</property> |
1399 | 1429 | <property name="draw_indicator">True</property> |
1430 | <child> | |
1431 | <object class="GtkBox" id="box15"> | |
1432 | <property name="visible">True</property> | |
1433 | <property name="can_focus">False</property> | |
1434 | <child> | |
1435 | <object class="GtkLabel" id="label11"> | |
1436 | <property name="visible">True</property> | |
1437 | <property name="can_focus">False</property> | |
1438 | <property name="label" translatable="yes" context="greeter|option|reader">Reader</property> | |
1439 | </object> | |
1440 | <packing> | |
1441 | <property name="expand">False</property> | |
1442 | <property name="fill">True</property> | |
1443 | <property name="position">0</property> | |
1444 | </packing> | |
1445 | </child> | |
1446 | <child> | |
1447 | <object class="GtkImage" id="greeter_reader_error"> | |
1448 | <property name="can_focus">False</property> | |
1449 | <property name="yalign">0</property> | |
1450 | <property name="pixel_size">12</property> | |
1451 | <property name="icon_name">dialog-warning</property> | |
1452 | <property name="icon_size">1</property> | |
1453 | </object> | |
1454 | <packing> | |
1455 | <property name="expand">False</property> | |
1456 | <property name="fill">True</property> | |
1457 | <property name="position">1</property> | |
1458 | </packing> | |
1459 | </child> | |
1460 | </object> | |
1461 | </child> | |
1400 | 1462 | </object> |
1401 | 1463 | <packing> |
1402 | 1464 | <property name="left_attach">0</property> |
18 | 18 | import collections |
19 | 19 | import configparser |
20 | 20 | import os |
21 | import shlex | |
21 | 22 | import sys |
22 | 23 | from glob import iglob |
23 | 24 | from itertools import chain |
71 | 72 | ('greeter', 'default-user-image'): ('changed',), |
72 | 73 | ('greeter', 'screensaver-timeout'): ('setup', 'get', 'set'), |
73 | 74 | ('greeter', 'theme-name'): ('setup', 'changed'), |
74 | ('greeter', 'icon-theme-name'): ('setup', 'changed')} | |
75 | ('greeter', 'icon-theme-name'): ('setup', 'changed'), | |
76 | ('greeter', 'keyboard'): ('changed',), | |
77 | ('greeter', 'reader'): ('changed',)} | |
75 | 78 | |
76 | 79 | def init_window(self): |
77 | 80 | self._widgets = self.Widgets(builder=self.builder) |
83 | 86 | self._groups = ( |
84 | 87 | SimpleGroup('greeter', self.builder, { |
85 | 88 | # Appearance |
86 | 'theme-name': (OptionEntry.StringEntry, None), | |
87 | 'icon-theme-name': (OptionEntry.StringEntry, None), | |
89 | 'theme-name': (OptionEntry.StringEntry, ''), | |
90 | 'icon-theme-name': (OptionEntry.StringEntry, ''), | |
88 | 91 | 'font-name': (OptionEntry.FontEntry, 'Sans 10'), |
89 | 92 | 'xft-antialias': (OptionEntry.BooleanEntry, 'false'), |
90 | 93 | 'xft-dpi': (OptionEntry.StringEntry, None), |
104 | 107 | 'screensaver-timeout': (OptionEntry.AdjustmentEntry, 60), |
105 | 108 | 'keyboard': (OptionEntry.StringPathEntry, None), |
106 | 109 | 'reader': (OptionEntry.StringPathEntry, None), |
107 | 'a11y-states': (OptionEntry.AccessibilityStatesEntry, None), | |
110 | 'a11y-states': (OptionEntry.AccessibilityStatesEntry, ''), | |
108 | 111 | 'allow-debugging': (OptionEntry.BooleanEntry, 'false'), }), |
109 | 112 | MonitorsGroup(WidgetsWrapper(self.builder))) |
110 | 113 | |
223 | 226 | adjustment) |
224 | 227 | |
225 | 228 | def on_entry_get_greeter_screensaver_timeout(self, entry=None, value=None): |
226 | value = int(float(value)) | |
229 | try: | |
230 | value = int(float(value)) | |
231 | except ValueError: | |
232 | value = 60 | |
233 | ||
227 | 234 | if value > 60: |
228 | 235 | return (value - 59) * 60 |
229 | 236 | return value |
230 | 237 | |
231 | 238 | def on_entry_set_greeter_screensaver_timeout(self, entry=None, value=None): |
232 | value = int(float(value)) | |
239 | try: | |
240 | value = int(float(value)) | |
241 | except ValueError: | |
242 | value = 60 | |
243 | ||
233 | 244 | if value > 60: |
234 | 245 | return value // 60 + 59 |
235 | 246 | return value |
291 | 302 | else: |
292 | 303 | entry.error = helpers.check_path_accessibility(value) |
293 | 304 | |
305 | # [greeter] keyboard | |
306 | def on_entry_changed_greeter_keyboard(self, entry): | |
307 | error = None | |
308 | if entry.enabled: | |
309 | value = entry.value | |
310 | if os.path.isabs(value): | |
311 | argv = shlex.split(value) | |
312 | error = helpers.check_path_accessibility(argv[0], executable=True) | |
313 | elif not value: | |
314 | error = _('Do not leave this field empty') | |
315 | entry.error = error | |
316 | ||
317 | # [greeter] reader | |
318 | on_entry_changed_greeter_reader = on_entry_changed_greeter_keyboard | |
319 | ||
294 | 320 | def on_destroy(self, *unused): |
295 | 321 | Gtk.main_quit() |
296 | 322 |
230 | 230 | # text, image, layout=image-text -> text, image |
231 | 231 | if options.get(Option.Layout) == {LayoutSet.Text, LayoutSet.Image}: |
232 | 232 | del options[Option.Layout] |
233 | # defaults.pop(Option.Image, None) | |
234 | # defaults.pop(Option.Text, None) | |
235 | 233 | |
236 | 234 | for k in defaults.keys() & options.keys(): |
237 | 235 | if defaults[k] == options[k]: |
480 | 480 | |
481 | 481 | class AccessibilityStatesEntry(BaseEntry): |
482 | 482 | |
483 | Options = {'keyboard', 'reader', 'contrast', 'font'} | |
483 | Options = ('keyboard', 'reader', 'contrast', 'font') | |
484 | 484 | |
485 | 485 | def __init__(self, widgets): |
486 | 486 | super().__init__(widgets) |
128 | 128 | return pixbuf |
129 | 129 | |
130 | 130 | |
131 | def check_path_accessibility(path): | |
131 | def check_path_accessibility(path, file=True, executable=False): | |
132 | 132 | """Return None if file is readable by greeter and error message otherwise""" |
133 | 133 | |
134 | 134 | if not os.path.exists(path): |
170 | 170 | _('LighDM do not have permissions to read path: {path}'.format(path=p)) |
171 | 171 | |
172 | 172 | errors = (check(p) for p in accumulate(parts, os.path.join)) |
173 | return next((error for error in errors if error), None) | |
173 | error = next((error for error in errors if error), None) | |
174 | ||
175 | if not error and file and not os.path.isfile(path): | |
176 | return _('Path is not a regular file: {path}'.format(path=path)) | |
177 | ||
178 | if not error and executable: | |
179 | st = os.stat(path) | |
180 | if st.st_uid == uid: | |
181 | if not st.st_mode & stat.S_IXUSR: | |
182 | return _('LighDM do not have permissions to execute file: {path}'.format(path=path)) | |
183 | elif st.st_gid in gids: | |
184 | if not st.st_mode & stat.S_IXGRP: | |
185 | return _('LighDM do not have permissions to execute file: {path}'.format(path=path)) | |
186 | elif not st.st_mode & stat.S_IXOTH: | |
187 | return _('LighDM do not have permissions to execute file: {path}'.format(path=path)) | |
188 | ||
189 | return error | |
174 | 190 | |
175 | 191 | |
176 | 192 | def get_markup_error(markup): |