Codebase list lightdm-gtk-greeter-settings / 30dcf79
New MultiheadSetupDialog Andrew P. 9 years ago
7 changed file(s) with 755 addition(s) and 590 deletion(s). Raw diff Collapse all Expand all
11 <!-- Generated with glade 3.18.3 -->
22 <interface>
33 <requires lib="gtk+" version="3.8"/>
4 <requires lib="*MultiheadSetupDialog (copy 2).ui" version="0.0"/>
45 <requires lib="gtk_greeter_settings" version="1.0"/>
5 <object class="GtkListStore" id="background_model">
6 <columns>
7 <!-- column-name text -->
8 <column type="gchararray"/>
9 <!-- column-name type -->
10 <column type="gchararray"/>
11 </columns>
12 <data>
13 <row>
14 <col id="0" translatable="yes" context="option|multihead">Select a file</col>
15 <col id="1">path</col>
16 </row>
17 <row>
18 <col id="0" translatable="yes" context="option|multihead">Select color</col>
19 <col id="1">color</col>
20 </row>
21 <row>
22 <col id="0" translatable="yes" context="option|multihead">Use default value</col>
23 <col id="1">default</col>
24 </row>
25 </data>
6 <object class="GtkMenu" id="available_menu">
7 <property name="visible">True</property>
8 <property name="can_focus">False</property>
269 </object>
2710 <object class="GtkFileFilter" id="filefilter1">
2811 <mime-types>
2912 <mime-type>image/*</mime-type>
3013 </mime-types>
14 </object>
15 <object class="GtkImage" id="image1">
16 <property name="visible">True</property>
17 <property name="can_focus">False</property>
18 <property name="icon_name">add</property>
3119 </object>
3220 <object class="GtkImage" id="image2">
3321 <property name="visible">True</property>
4129 <property name="xpad">2</property>
4230 <property name="icon_name">dialog-ok</property>
4331 </object>
44 <object class="GtkListStore" id="monitors_model">
45 <columns>
46 <!-- column-name name -->
47 <column type="gchararray"/>
48 <!-- column-name background -->
49 <column type="gchararray"/>
50 <!-- column-name user-background -->
51 <column type="gboolean"/>
52 <!-- column-name user-background-enabled -->
53 <column type="gboolean"/>
54 <!-- column-name laptop -->
55 <column type="gboolean"/>
56 <!-- column-name laptop-enabled -->
57 <column type="gboolean"/>
58 <!-- column-name background-pixbuf -->
59 <column type="GdkPixbuf"/>
60 <!-- column-name background-is-color -->
61 <column type="gboolean"/>
62 <!-- column-name error-visible -->
63 <column type="gboolean"/>
64 <!-- column-name error-text -->
65 <column type="gchararray"/>
66 </columns>
32 <object class="GtkImage" id="image4">
33 <property name="visible">True</property>
34 <property name="can_focus">False</property>
35 <property name="icon_name">add</property>
6736 </object>
6837 <object class="MultiheadSetupDialog" id="multihead_setup_dialog">
6938 <property name="width_request">500</property>
12796 </packing>
12897 </child>
12998 <child>
130 <object class="GtkBox" id="box7">
99 <object class="GtkNotebook" id="monitors_notebook">
131100 <property name="visible">True</property>
132 <property name="can_focus">False</property>
133 <property name="valign">start</property>
134 <property name="hexpand">True</property>
135 <property name="orientation">vertical</property>
136 <property name="spacing">8</property>
101 <property name="can_focus">True</property>
102 <property name="show_border">False</property>
103 <property name="scrollable">True</property>
104 <property name="group_name">monitors</property>
105 <signal name="switch-page" handler="on_monitors_notebook_switch_page" swapped="no"/>
137106 <child>
138 <object class="GtkBox" id="box1">
107 <object class="GtkBox" id="empty_page">
139108 <property name="visible">True</property>
140109 <property name="can_focus">False</property>
141110 <property name="orientation">vertical</property>
142111 <child>
143 <object class="GtkScrolledWindow" id="scrolledwindow1">
144 <property name="height_request">160</property>
145 <property name="visible">True</property>
146 <property name="can_focus">True</property>
112 <object class="GtkBox" id="empty_add_placeholder">
113 <property name="visible">True</property>
114 <property name="can_focus">False</property>
115 <property name="halign">center</property>
116 <property name="valign">center</property>
117 <property name="margin_left">24</property>
118 <property name="margin_right">24</property>
119 <property name="margin_top">24</property>
120 <property name="margin_bottom">24</property>
147121 <property name="hexpand">True</property>
148122 <property name="vexpand">True</property>
149 <property name="shadow_type">in</property>
150 <child>
151 <object class="GtkTreeView" id="monitors_treeview">
152 <property name="width_request">300</property>
123 <child>
124 <object class="GtkButton" id="empty_add_button">
125 <property name="label" translatable="yes" context="option|multihead">Add configuration</property>
153126 <property name="visible">True</property>
154127 <property name="can_focus">True</property>
155 <property name="model">monitors_model</property>
156 <property name="headers_clickable">False</property>
157 <property name="search_column">0</property>
158 <child internal-child="selection">
159 <object class="GtkTreeSelection" id="monitors_selection">
160 <signal name="changed" handler="on_selection_changed" swapped="no"/>
161 </object>
128 <property name="receives_default">True</property>
129 <property name="image">image4</property>
130 <property name="relief">none</property>
131 <property name="always_show_image">True</property>
132 <signal name="clicked" handler="on_add_button_clicked" swapped="no"/>
133 </object>
134 <packing>
135 <property name="expand">False</property>
136 <property name="fill">True</property>
137 <property name="position">0</property>
138 </packing>
139 </child>
140 <child>
141 <object class="GtkMenuButton" id="empty_add_menu_button">
142 <property name="visible">True</property>
143 <property name="can_focus">True</property>
144 <property name="receives_default">False</property>
145 <property name="relief">none</property>
146 <property name="focus_on_click">False</property>
147 <property name="draw_indicator">True</property>
148 <child>
149 <placeholder/>
162150 </child>
163 <child>
164 <object class="GtkTreeViewColumn" id="name_column">
165 <property name="resizable">True</property>
166 <property name="title" translatable="yes" context="option|multihead">Monitor</property>
167 <child>
168 <object class="GtkCellRendererText" id="name_renderer">
169 <property name="editable">True</property>
170 <signal name="edited" handler="on_name_renderer_edited" swapped="no"/>
171 </object>
172 <attributes>
173 <attribute name="text">0</attribute>
174 </attributes>
175 </child>
176 <child>
177 <object class="GtkCellRendererPixbuf" id="error_renderer">
178 <property name="icon_name">dialog-warning</property>
179 </object>
180 <attributes>
181 <attribute name="visible">8</attribute>
182 </attributes>
183 </child>
184 </object>
185 </child>
186 <child>
187 <object class="GtkTreeViewColumn" id="user_bg_column">
188 <property name="resizable">True</property>
189 <property name="sizing">autosize</property>
190 <property name="title" translatable="yes" context="option|multihead">User's</property>
191 <child>
192 <object class="GtkCellRendererToggle" id="user_bg_renderer">
193 <signal name="toggled" handler="on_user_bg_renderer_toggled" swapped="no"/>
194 </object>
195 <attributes>
196 <attribute name="active">2</attribute>
197 <attribute name="inconsistent">3</attribute>
198 </attributes>
199 </child>
200 </object>
201 </child>
202 <child>
203 <object class="GtkTreeViewColumn" id="laptop_column">
204 <property name="sizing">autosize</property>
205 <property name="title" translatable="yes" context="option|multihead">Laptop</property>
206 <child>
207 <object class="GtkCellRendererToggle" id="laptop_renderer">
208 <signal name="toggled" handler="on_laptop_renderer_toggled" swapped="no"/>
209 </object>
210 <attributes>
211 <attribute name="active">4</attribute>
212 <attribute name="inconsistent">5</attribute>
213 </attributes>
214 </child>
215 </object>
216 </child>
217 <child>
218 <object class="GtkTreeViewColumn" id="background_column">
219 <property name="resizable">True</property>
220 <property name="sizing">autosize</property>
221 <property name="title" translatable="yes" context="option|multihead">Background</property>
222 <property name="expand">True</property>
223 <child>
224 <object class="GtkCellRendererPixbuf" id="color_renderer"/>
225 <attributes>
226 <attribute name="visible">7</attribute>
227 <attribute name="pixbuf">6</attribute>
228 </attributes>
229 </child>
230 <child>
231 <object class="GtkCellRendererCombo" id="bg_renderer">
232 <property name="editable">True</property>
233 <property name="model">background_model</property>
234 <property name="text_column">0</property>
235 <signal name="edited" handler="on_bg_renderer_edited" swapped="no"/>
236 <signal name="editing-started" handler="on_bg_renderer_editing_started" swapped="no"/>
237 </object>
238 <attributes>
239 <attribute name="text">1</attribute>
240 </attributes>
241 </child>
242 </object>
243 </child>
244 </object>
151 </object>
152 <packing>
153 <property name="expand">False</property>
154 <property name="fill">True</property>
155 <property name="position">1</property>
156 </packing>
245157 </child>
246158 </object>
247159 <packing>
250162 <property name="position">0</property>
251163 </packing>
252164 </child>
253 <child>
254 <object class="GtkToolbar" id="monitors_toolbar">
255 <property name="visible">True</property>
256 <property name="can_focus">False</property>
257 <property name="icon_size">2</property>
258 <child>
259 <object class="GtkToolButton" id="add_button">
260 <property name="visible">True</property>
261 <property name="can_focus">False</property>
262 <property name="tooltip_text" translatable="yes" context="option|multihead">Add monior to the list</property>
263 <property name="label" translatable="yes" context="option|multihead">Add</property>
264 <property name="use_underline">True</property>
265 <property name="icon_name">list-add-symbolic</property>
266 <signal name="clicked" handler="on_monitors_add_clicked" swapped="no"/>
267 </object>
268 <packing>
269 <property name="expand">False</property>
270 <property name="homogeneous">True</property>
271 </packing>
272 </child>
273 <child>
274 <object class="GtkToolButton" id="remove_button">
275 <property name="visible">True</property>
276 <property name="can_focus">False</property>
277 <property name="tooltip_text" translatable="yes" context="option|multihead">Remove monitor from the list</property>
278 <property name="label" translatable="yes" context="option|multihead">Remove</property>
279 <property name="use_underline">True</property>
280 <property name="icon_name">list-remove-symbolic</property>
281 <signal name="clicked" handler="on_monitors_remove_clicked" swapped="no"/>
282 </object>
283 <packing>
284 <property name="expand">False</property>
285 <property name="homogeneous">True</property>
286 </packing>
287 </child>
288 <style>
289 <class name="inline-toolbar"/>
290 </style>
291 </object>
292 <packing>
293 <property name="expand">False</property>
294 <property name="fill">True</property>
295 <property name="position">1</property>
296 </packing>
297 </child>
165 </object>
166 </child>
167 <child type="tab">
168 <object class="GtkLabel" id="label3">
169 <property name="visible">True</property>
170 <property name="can_focus">False</property>
171 <property name="label" translatable="yes" context="option|multihead">No configured monitors found</property>
298172 </object>
299173 <packing>
300 <property name="expand">False</property>
301 <property name="fill">True</property>
302 <property name="position">0</property>
174 <property name="tab_fill">False</property>
303175 </packing>
304176 </child>
305177 <child>
306 <object class="GtkLabel" id="monitors_label">
178 <object class="GtkGrid" id="editor_page">
307179 <property name="visible">True</property>
308180 <property name="can_focus">False</property>
309 <property name="xalign">0</property>
310 <property name="label">[available monitors]</property>
311 <property name="use_markup">True</property>
312 <signal name="activate-link" handler="on_monitors_label_activate_link" swapped="no"/>
181 <property name="margin_left">8</property>
182 <property name="margin_right">8</property>
183 <property name="margin_top">8</property>
184 <property name="margin_bottom">8</property>
185 <property name="row_spacing">6</property>
186 <property name="column_spacing">12</property>
187 <child>
188 <object class="GtkRadioButton" id="background_image_choice">
189 <property name="label" translatable="yes" context="option|greeter|background">Image</property>
190 <property name="visible">True</property>
191 <property name="can_focus">True</property>
192 <property name="receives_default">False</property>
193 <property name="halign">start</property>
194 <property name="margin_left">24</property>
195 <property name="xalign">0</property>
196 <property name="draw_indicator">True</property>
197 <property name="group">background_color_choice</property>
198 </object>
199 <packing>
200 <property name="left_attach">0</property>
201 <property name="top_attach">2</property>
202 </packing>
203 </child>
204 <child>
205 <object class="GtkRadioButton" id="background_color_choice">
206 <property name="label" translatable="yes" context="option|greeter|background">Color</property>
207 <property name="visible">True</property>
208 <property name="can_focus">True</property>
209 <property name="receives_default">False</property>
210 <property name="halign">start</property>
211 <property name="margin_left">24</property>
212 <property name="xalign">0</property>
213 <property name="active">True</property>
214 <property name="draw_indicator">True</property>
215 </object>
216 <packing>
217 <property name="left_attach">0</property>
218 <property name="top_attach">3</property>
219 </packing>
220 </child>
221 <child>
222 <object class="GtkFileChooserButton" id="background_image_value">
223 <property name="visible">True</property>
224 <property name="can_focus">False</property>
225 <property name="halign">start</property>
226 <property name="hexpand">True</property>
227 <property name="create_folders">False</property>
228 <property name="local_only">False</property>
229 </object>
230 <packing>
231 <property name="left_attach">1</property>
232 <property name="top_attach">2</property>
233 </packing>
234 </child>
235 <child>
236 <object class="GtkColorButton" id="background_color_value">
237 <property name="visible">True</property>
238 <property name="can_focus">True</property>
239 <property name="receives_default">True</property>
240 <property name="halign">start</property>
241 <property name="hexpand">True</property>
242 </object>
243 <packing>
244 <property name="left_attach">1</property>
245 <property name="top_attach">3</property>
246 </packing>
247 </child>
248 <child>
249 <object class="GtkCheckButton" id="laptop_value">
250 <property name="label" translatable="yes" context="option|greeter|laptop">This monitor is laptop display (detect lid closing)</property>
251 <property name="visible">True</property>
252 <property name="can_focus">True</property>
253 <property name="receives_default">False</property>
254 <property name="margin_left">24</property>
255 <property name="hexpand">True</property>
256 <property name="xalign">0</property>
257 <property name="image_position">right</property>
258 <property name="draw_indicator">True</property>
259 </object>
260 <packing>
261 <property name="left_attach">0</property>
262 <property name="top_attach">7</property>
263 <property name="width">2</property>
264 </packing>
265 </child>
266 <child>
267 <object class="GtkCheckButton" id="user-background_use">
268 <property name="label" translatable="yes" context="option|multihead">Overwrite default "user-background" option</property>
269 <property name="visible">True</property>
270 <property name="can_focus">True</property>
271 <property name="receives_default">False</property>
272 <property name="margin_top">2</property>
273 <property name="xalign">0</property>
274 <property name="draw_indicator">True</property>
275 </object>
276 <packing>
277 <property name="left_attach">0</property>
278 <property name="top_attach">4</property>
279 <property name="width">2</property>
280 </packing>
281 </child>
282 <child>
283 <object class="GtkCheckButton" id="laptop_use">
284 <property name="label" translatable="yes" context="option|multihead">Overwrite default "laptop" option</property>
285 <property name="visible">True</property>
286 <property name="can_focus">True</property>
287 <property name="receives_default">False</property>
288 <property name="margin_top">2</property>
289 <property name="xalign">0</property>
290 <property name="draw_indicator">True</property>
291 </object>
292 <packing>
293 <property name="left_attach">0</property>
294 <property name="top_attach">6</property>
295 <property name="width">2</property>
296 </packing>
297 </child>
298 <child>
299 <object class="GtkBox" id="monitor_name_box">
300 <property name="visible">True</property>
301 <property name="can_focus">False</property>
302 <property name="hexpand">True</property>
303 <child>
304 <object class="GtkLabel" id="label1">
305 <property name="visible">True</property>
306 <property name="can_focus">False</property>
307 <property name="label" translatable="yes" context="option|multihead">Monitor name:</property>
308 </object>
309 <packing>
310 <property name="expand">False</property>
311 <property name="fill">True</property>
312 <property name="position">0</property>
313 </packing>
314 </child>
315 <child>
316 <object class="GtkComboBoxText" id="name_combo">
317 <property name="visible">True</property>
318 <property name="can_focus">False</property>
319 <property name="margin_left">4</property>
320 <property name="margin_right">4</property>
321 <property name="has_entry">True</property>
322 <child internal-child="entry">
323 <object class="GtkEntry" id="name_value">
324 <property name="can_focus">True</property>
325 <property name="width_chars">25</property>
326 <property name="placeholder_text" translatable="yes">Don't leave empty</property>
327 </object>
328 </child>
329 </object>
330 <packing>
331 <property name="expand">False</property>
332 <property name="fill">True</property>
333 <property name="position">1</property>
334 </packing>
335 </child>
336 <child>
337 <object class="GtkImage" id="name_error">
338 <property name="can_focus">False</property>
339 <property name="yalign">0</property>
340 <property name="pixel_size">12</property>
341 <property name="icon_name">dialog-warning</property>
342 <property name="icon_size">1</property>
343 </object>
344 <packing>
345 <property name="expand">False</property>
346 <property name="fill">True</property>
347 <property name="position">2</property>
348 </packing>
349 </child>
350 <child>
351 <object class="GtkMenuButton" id="editor_add_menu_button">
352 <property name="visible">True</property>
353 <property name="can_focus">True</property>
354 <property name="receives_default">False</property>
355 <property name="relief">none</property>
356 <property name="focus_on_click">False</property>
357 <property name="draw_indicator">True</property>
358 <child>
359 <placeholder/>
360 </child>
361 </object>
362 <packing>
363 <property name="expand">False</property>
364 <property name="fill">True</property>
365 <property name="pack_type">end</property>
366 <property name="position">3</property>
367 </packing>
368 </child>
369 <child>
370 <object class="GtkButton" id="editor_add_button">
371 <property name="visible">True</property>
372 <property name="can_focus">True</property>
373 <property name="receives_default">True</property>
374 <property name="tooltip_text" translatable="yes" context="option|multihead">Add new monitor configuration</property>
375 <property name="image">image1</property>
376 <property name="relief">none</property>
377 <property name="always_show_image">True</property>
378 <signal name="clicked" handler="on_add_button_clicked" swapped="no"/>
379 </object>
380 <packing>
381 <property name="expand">False</property>
382 <property name="fill">True</property>
383 <property name="pack_type">end</property>
384 <property name="position">4</property>
385 </packing>
386 </child>
387 </object>
388 <packing>
389 <property name="left_attach">0</property>
390 <property name="top_attach">0</property>
391 <property name="width">2</property>
392 </packing>
393 </child>
394 <child>
395 <object class="GtkBox" id="box1">
396 <property name="visible">True</property>
397 <property name="can_focus">False</property>
398 <child>
399 <object class="GtkCheckButton" id="background_use">
400 <property name="label" translatable="yes" context="option|multihead">Overwrite default "background" option</property>
401 <property name="visible">True</property>
402 <property name="can_focus">True</property>
403 <property name="receives_default">False</property>
404 <property name="xalign">0</property>
405 <property name="draw_indicator">True</property>
406 </object>
407 <packing>
408 <property name="expand">False</property>
409 <property name="fill">True</property>
410 <property name="position">0</property>
411 </packing>
412 </child>
413 <child>
414 <object class="GtkImage" id="background_error">
415 <property name="can_focus">False</property>
416 <property name="yalign">0</property>
417 <property name="pixel_size">12</property>
418 <property name="icon_name">dialog-warning</property>
419 <property name="icon_size">1</property>
420 </object>
421 <packing>
422 <property name="expand">False</property>
423 <property name="fill">True</property>
424 <property name="position">1</property>
425 </packing>
426 </child>
427 </object>
428 <packing>
429 <property name="left_attach">0</property>
430 <property name="top_attach">1</property>
431 <property name="width">2</property>
432 </packing>
433 </child>
434 <child>
435 <object class="GtkCheckButton" id="user-background_value">
436 <property name="label" translatable="yes" context="option|greeter|user-background">Use user wallpaper if available</property>
437 <property name="visible">True</property>
438 <property name="can_focus">True</property>
439 <property name="receives_default">False</property>
440 <property name="margin_left">24</property>
441 <property name="hexpand">True</property>
442 <property name="xalign">0</property>
443 <property name="image_position">right</property>
444 <property name="draw_indicator">True</property>
445 </object>
446 <packing>
447 <property name="left_attach">0</property>
448 <property name="top_attach">5</property>
449 <property name="width">2</property>
450 </packing>
451 </child>
313452 </object>
314453 <packing>
315 <property name="expand">False</property>
316 <property name="fill">True</property>
317454 <property name="position">1</property>
318455 </packing>
319456 </child>
320 <child>
321 <object class="GtkLabel" id="label2">
457 <child type="tab">
458 <object class="GtkLabel" id="label4">
322459 <property name="visible">True</property>
323460 <property name="can_focus">False</property>
324 <property name="xalign">0</property>
325 <property name="label" translatable="yes" context="option|multihead">&lt;i&gt;Note: greeter do not set monitors geometry.
326 You need to configure it by yourself.&lt;/i&gt;</property>
327 <property name="use_markup">True</property>
328 <property name="wrap">True</property>
461 <property name="label">[editor]</property>
329462 </object>
330463 <packing>
331 <property name="expand">False</property>
332 <property name="fill">True</property>
333 <property name="position">2</property>
464 <property name="position">1</property>
465 <property name="tab_fill">False</property>
334466 </packing>
335467 </child>
336468 </object>
337469 <packing>
338 <property name="expand">True</property>
470 <property name="expand">False</property>
471 <property name="fill">True</property>
472 <property name="position">0</property>
473 </packing>
474 </child>
475 <child>
476 <object class="GtkLabel" id="label2">
477 <property name="visible">True</property>
478 <property name="can_focus">False</property>
479 <property name="margin_left">8</property>
480 <property name="xalign">0</property>
481 <property name="label" translatable="yes" context="option|multihead">&lt;i&gt;Note: greeter do not set monitors geometry.
482 You need to configure it by yourself.&lt;/i&gt;</property>
483 <property name="use_markup">True</property>
484 <property name="wrap">True</property>
485 </object>
486 <packing>
487 <property name="expand">False</property>
339488 <property name="fill">True</property>
340489 <property name="position">1</property>
341490 </packing>
103103 self._initial_values = {}
104104 self._changed_entries = None
105105 self._entries = None
106 self._groups = (
107 SimpleGroup('greeter', self.builder, {
108 # Appearance
109 'theme-name': (OptionEntry.StringEntry, ''),
110 'icon-theme-name': (OptionEntry.StringEntry, ''),
111 'font-name': (OptionEntry.FontEntry, 'Sans 10'),
112 'xft-antialias': (OptionEntry.BooleanEntry, 'false'),
113 'xft-dpi': (OptionEntry.StringEntry, None),
114 'xft-rgba': (OptionEntry.ChoiceEntry, None),
115 'xft-hintstyle': (OptionEntry.ChoiceEntry, None),
116 'background': (OptionEntry.BackgroundEntry, '#000000'),
117 'user-background': (OptionEntry.BooleanEntry, 'true'),
118 'hide-user-image': (OptionEntry.InvertedBooleanEntry, 'false'),
119 'default-user-image': (IconEntry.IconEntry, '#avatar-default'),
120 # Panel
121 'clock-format': (OptionEntry.ClockFormatEntry, '%a, %H:%M'),
122 'indicators': (IndicatorsEntry.IndicatorsEntry,
123 '~host;~spacer;~clock;~spacer;~language;~session;~a11y;~power'),
124 # Position
125 'position': (PositionEntry.PositionEntry, '50%,center'),
126 # Misc
127 'screensaver-timeout': (OptionEntry.AdjustmentEntry, '60'),
128 'keyboard': (OptionEntry.StringPathEntry, ''),
129 'reader': (OptionEntry.StringPathEntry, ''),
130 'a11y-states': (OptionEntry.AccessibilityStatesEntry, ''),
131 'allow-debugging': (OptionEntry.BooleanEntry, 'false'), }),
132 MonitorsGroup(self.builder))
106
107 self._group_greeter = SimpleGroup('greeter', self.builder, {
108 # Appearance
109 'theme-name': (OptionEntry.StringEntry, ''),
110 'icon-theme-name': (OptionEntry.StringEntry, ''),
111 'font-name': (OptionEntry.FontEntry, 'Sans 10'),
112 'xft-antialias': (OptionEntry.BooleanEntry, 'false'),
113 'xft-dpi': (OptionEntry.StringEntry, None),
114 'xft-rgba': (OptionEntry.ChoiceEntry, None),
115 'xft-hintstyle': (OptionEntry.ChoiceEntry, None),
116 'background': (OptionEntry.BackgroundEntry, '#000000'),
117 'user-background': (OptionEntry.BooleanEntry, 'true'),
118 'hide-user-image': (OptionEntry.InvertedBooleanEntry, 'false'),
119 'default-user-image': (IconEntry.IconEntry, '#avatar-default'),
120 # Panel
121 'clock-format': (OptionEntry.ClockFormatEntry, '%a, %H:%M'),
122 'indicators': (IndicatorsEntry.IndicatorsEntry,
123 '~host;~spacer;~clock;~spacer;~language;~session;~a11y;~power'),
124 # Position
125 'position': (PositionEntry.PositionEntry, '50%,center'),
126 # Misc
127 'screensaver-timeout': (OptionEntry.AdjustmentEntry, '60'),
128 'keyboard': (OptionEntry.StringPathEntry, ''),
129 'reader': (OptionEntry.StringPathEntry, ''),
130 'a11y-states': (OptionEntry.AccessibilityStatesEntry, ''),
131 'allow-debugging': (OptionEntry.BooleanEntry, 'false'), })
132 self._group_monitors = MonitorsGroup(self.builder, self._get_default_monitors_options)
133
134 self._groups = self._group_greeter, self._group_monitors
133135
134136 for group in self._groups:
135137 group.entry_added.connect(self.on_entry_added)
228230 except OSError as e:
229231 helpers.show_message(e, Gtk.MessageType.ERROR)
230232
233 def _get_default_monitors_options(self):
234 return {key: self._group_greeter.entries[key].value or self._group_greeter.defaults[key]
235 for key in ('background', 'user-background')}
236
231237 def on_entry_added(self, group, entry, key):
232238 if isinstance(group, SimpleGroup) and (group.name, key) in self.entries_setup:
233239 for action in self.entries_setup[(group.name, key)]:
1515 # with this program. If not, see <http://www.gnu.org/licenses/>.
1616
1717
18 from collections import OrderedDict
19
1820 from gi.repository import Gtk
1921
2022 from lightdm_gtk_greeter_settings.helpers import WidgetsWrapper
2931 class MonitorsGroup(BaseGroup):
3032 GROUP_PREFIX = 'monitor:'
3133
32 def __init__(self, widgets):
34 def __init__(self, widgets, defaults_callback=None):
3335 super().__init__(widgets)
34 self._entries = {}
36 self._entries = OrderedDict()
3537 self._widgets = WidgetsWrapper(widgets, 'multihead')
38 self._widgets['label'].connect('activate-link', self._on_label_link_activate)
3639 self._dialog = None
37 self._widgets['label'].connect('activate-link', self._on_label_link_activate)
40 self._get_defaults_callback = defaults_callback
3841
3942 def read(self, config):
4043 self._entries.clear()
5356 for name in config.sections():
5457 if name.startswith(self.GROUP_PREFIX):
5558 config.remove_section(name)
59
5660 for name, entry in self._entries.items():
57 section = '{prefix} {name}'.format(prefix=self.GROUP_PREFIX, name=name)
61 section = '{prefix} {name}'.format(prefix=self.GROUP_PREFIX, name=name.strip())
5862 config.add_section(section)
5963 for key, value in entry:
6064 if value is not None:
6569 self._dialog = MultiheadSetupDialog()
6670 self._dialog.props.transient_for = self._widgets['label'].get_toplevel()
6771
72 if self._get_defaults_callback:
73 self._dialog.set_defaults(self._get_defaults_callback())
74
6875 self._dialog.set_model(self._entries)
6976
7077 if self._dialog.run() == Gtk.ResponseType.OK:
7178 current_names = set(self._entries.keys())
72 for name, values in self._dialog.get_model().items():
79 for name, values in self._dialog.get_model():
7380 if name in self._entries:
7481 self._entries[name].assign(values)
7582 current_names.discard(name)
1515 # with this program. If not, see <http://www.gnu.org/licenses/>.
1616
1717
18 from builtins import max
19 from locale import gettext as _
20
2118 from gi.repository import (
2219 Gdk,
23 GdkPixbuf,
2420 Gtk)
2521
22 import lightdm_gtk_greeter_settings.helpers
23
2624 from lightdm_gtk_greeter_settings.helpers import (
27 C_,
2825 check_path_accessibility,
2926 get_data_path,
30 SimpleEnum,
31 WidgetsEnum)
27 WidgetsEnum,
28 WidgetsWrapper)
29 from lightdm_gtk_greeter_settings import OptionEntry
30
31 from gi.overrides import GLib
3232
3333
3434 __all__ = ['MultiheadSetupDialog']
3535
36
37 class Row(SimpleEnum):
38 Name = ()
39 Background = ()
40 UserBg = ()
41 UserBgDisabled = ()
42 Laptop = ()
43 LaptopDisabled = ()
44 BackgroundPixbuf = ()
45 BackgroundIsColor = ()
46 ErrorVisible = ()
47 ErrorText = ()
48
49
50 class BackgroundRow(SimpleEnum):
51 Text = ()
52 Type = ()
36 C_ = lambda t: lightdm_gtk_greeter_settings.helpers.C_('option|multihead', t)
37
38
39 class PageOptions:
40 name = None
41 background = None
42 background_disabled = None
43 user_background = None
44 user_background_disabled = None
45 laptop = None
46 laptop_disabled = None
47 label = None
5348
5449
5550 class MultiheadSetupDialog(Gtk.Dialog):
5752
5853 def __new__(cls):
5954 builder = Gtk.Builder()
60 builder.add_from_file(get_data_path('%s.ui' % cls.__name__))
55 builder.add_from_file(get_data_path('%s.ui' % cls.__gtype_name__))
6156 window = builder.get_object('multihead_setup_dialog')
6257 window.builder = builder
6358 builder.connect_signals(window)
6560 return window
6661
6762 class Widgets(WidgetsEnum):
68 treeview = 'monitors_treeview'
69 model = 'monitors_model'
70 selection = 'monitors_selection'
71 bg_model = 'background_model'
72 bg_renderer = 'bg_renderer'
73 bg_column = 'background_column'
74 name_column = 'name_column'
75 remove = 'remove_button'
76 available = 'monitors_label'
63 notebook = 'monitors_notebook'
64 available_menu = 'available_menu'
65 name = 'name_value'
66 name_combo = 'name_combo'
67
68 editor = 'editor_page'
69 editor_add_button = 'editor_add_button'
70 editor_add_menu_button = 'editor_add_menu_button'
71 empty = 'empty_page'
72 empty_add_button = 'empty_add_button'
73 empty_add_menu_button = 'empty_add_menu_button'
7774
7875 builder = None
7976
8077 def init_window(self):
8178 self._widgets = self.Widgets(builder=self.builder)
82 self._group = None
83 self._available_monitors = None
84
85 self._file_dialog = None
86 self._color_dialog = None
87 self._invalid_name_dialog = None
88 self._name_exists_dialog = None
89
90 self._widgets.treeview.props.tooltip_column = Row.ErrorText
91 self._widgets.bg_renderer.set_property('placeholder-text',
92 C_('option|multihead', 'Use default value'))
93
94 def _update_monitors_label(self):
95 if not self._available_monitors:
96 self._widgets.available.props.visible = False
79
80 self._widgets.notebook.remove_page(self._widgets.notebook.page_num(self._widgets.editor))
81
82 self._current_page = None
83 self._defaults = {}
84 self._options = {}
85
86 self._option_name = OptionEntry.StringEntry(WidgetsWrapper(self.builder, 'name'))
87 self._option_bg = OptionEntry.BackgroundEntry(WidgetsWrapper(self.builder, 'background'))
88 self._option_user_bg = OptionEntry.BooleanEntry(WidgetsWrapper(self.builder,
89 'user-background'))
90 self._option_laptop = OptionEntry.BooleanEntry(WidgetsWrapper(self.builder, 'laptop'))
91
92 self._option_name.changed.connect(self._on_name_changed)
93 for entry in (self._option_bg, self._option_user_bg, self._option_laptop):
94 entry.changed.connect(self._on_option_changed)
95
96 screen = Gdk.Screen.get_default()
97 self._available_monitors = [(screen.get_monitor_plug_name(i),
98 Gtk.MenuItem(screen.get_monitor_plug_name(i)))
99 for i in range(screen.get_n_monitors())]
100
101 menu_header = Gtk.MenuItem(C_('Detected monitors:'))
102 menu_header.set_sensitive(False)
103 self._widgets.available_menu.append(menu_header)
104 self._widgets.available_menu.append(Gtk.SeparatorMenuItem())
105 self._widgets.available_menu.show_all()
106 for name, item in self._available_monitors:
107 self._widgets.available_menu.append(item)
108 item.connect('activate', self.on_add_button_clicked, name)
109
110 def set_model(self, values):
111 self._widgets.notebook.handler_block_by_func(self.on_monitors_notebook_switch_page)
112 for page in self._widgets.notebook.get_children():
113 self._remove_monitor(page, update=False)
114 self._widgets.notebook.handler_unblock_by_func(self.on_monitors_notebook_switch_page)
115
116 self._options.clear()
117 for name, entry in values.items():
118 options = PageOptions()
119 options.name = name
120 options.background = entry['background']
121 options.user_background = entry['user-background']
122 options.laptop = entry['laptop']
123
124 options.background_disabled = self._get_first_not_none(
125 options.background, self._defaults.get('background'), '')
126 options.user_background_disabled = self._get_first_not_none(
127 options.user_background, self._defaults.get('user-background'), 'true')
128 options.laptop_disabled = self._get_first_not_none(
129 options.laptop, self._defaults.get('laptop'), 'false')
130
131 self._add_monitor(options)
132
133 self._widgets.empty.props.visible = not self._options
134
135 self._update_monitors_list()
136
137 def get_model(self):
138 sections = []
139 for page in self._widgets.notebook.get_children():
140 options = self._options.get(page)
141 if not options or not options.name:
142 continue
143 sections.append((options.name,
144 {'background': options.background,
145 'user-background': options.user_background,
146 'laptop': options.laptop}))
147 return sections
148
149 def set_defaults(self, values):
150 self._defaults = values.copy()
151
152 def _get_first_not_none(self, *values, fallback=None):
153 return next((v for v in values if v is not None), fallback)
154
155 def _add_monitor(self, options):
156 holder = Gtk.Box()
157 holder.show()
158
159 options.label = Gtk.Label(options.name)
160 options.error_image = Gtk.Image.new_from_icon_name('dialog-warning', Gtk.IconSize.INVALID)
161 options.error_image.set_pixel_size(16)
162 options.error_image.set_no_show_all(True)
163
164 close_button = Gtk.Button()
165 close_button.set_focus_on_click(False)
166 close_button.set_relief(Gtk.ReliefStyle.NONE)
167 close_button.connect('clicked', lambda w, p: self._remove_monitor(p), holder)
168 close_image = Gtk.Image.new_from_icon_name('stock_close', Gtk.IconSize.INVALID)
169 close_image.set_pixel_size(16)
170 close_button.add(close_image)
171
172 label_box = Gtk.Box(Gtk.Orientation.HORIZONTAL)
173 label_box.pack_start(options.error_image, False, False, 1)
174 label_box.pack_start(options.label, False, False, 3)
175 label_box.pack_start(close_button, False, False, 0)
176
177 label_eventbox = Gtk.EventBox()
178 label_eventbox.add(label_box)
179 label_eventbox.show_all()
180
181 self._options[holder] = options
182
183 if self._widgets.empty.get_parent():
184 self._widgets.empty.hide()
185
186 current_idx = self._widgets.notebook.get_current_page()
187 current_idx = self._widgets.notebook.insert_page(holder, label_eventbox, current_idx + 1)
188
189 # self._widgets.notebook.set_tab_reorderable(holder, True)
190
191 return current_idx
192
193 def _remove_monitor(self, page, update=True):
194 if page not in self._options:
97195 return
98196
99 used = set(row[Row.Name] for row in self._widgets.model)
100 monitors = []
101 for name in self._available_monitors:
102 if name in used:
103 monitors.append(name)
104 else:
105 monitors.append('<i><a href="{name}">{name}</a></i>'.format(name=name))
106
107 label = C_('option|multihead',
108 'Available monitors: {monitors}').format(monitors=', '.join(monitors))
109 self._widgets.available.props.label = label
110 self._widgets.available.props.visible = True
111
112 def set_model(self, values):
113 self._widgets.model.clear()
114 for name, entry in values.items():
115 row = Row._make(Name=name,
116 Background=entry['background'],
117 UserBg=entry['user-background'],
118 UserBgDisabled=entry['user-background'] is None,
119 Laptop=entry['laptop'],
120 LaptopDisabled=entry['laptop'] is None,
121 BackgroundPixbuf=None,
122 BackgroundIsColor=False,
123 ErrorVisible=False,
124 ErrorText=None)
125 self._update_row_appearance(self._widgets.model.append(row))
126 screen = Gdk.Screen.get_default()
127 self._available_monitors = [screen.get_monitor_plug_name(i)
128 for i in range(screen.get_n_monitors())]
129 self._update_monitors_label()
130
131 def get_model(self):
132 return {
133 row[Row.Name]:
134 {
135 'background': row[Row.Background],
136 'user-background': self._get_toggle_state(row, Row.UserBg, Row.UserBgDisabled),
137 'laptop': self._get_toggle_state(row, Row.Laptop, Row.LaptopDisabled)
138 }
139 for row in self._widgets.model}
140
141 def _update_row_appearance(self, rowiter):
142 row = self._widgets.model[rowiter]
143 bg = row[Row.Background]
144
197 self._options.pop(page)
198
199 if page == self._widgets.editor.props.parent:
200 page.remove(self._widgets.editor)
201
202 if update:
203 self._update_monitors_list()
204 if not self._options:
205 self._widgets.empty.show()
206
207 self._widgets.notebook.remove_page(self._widgets.notebook.page_num(page))
208
209 def _apply_monitor_options(self, options):
210 for entry, value, fallback in \
211 ((self._option_bg, options.background, options.background_disabled),
212 (self._option_user_bg, options.user_background, options.user_background_disabled),
213 (self._option_laptop, options.laptop, options.laptop_disabled)):
214 entry.handler_block_by_func(self._on_option_changed)
215 entry.value = fallback if value is None else value
216 entry.enabled = value is not None
217 entry.handler_unblock_by_func(self._on_option_changed)
218
219 self._option_name.value = options.name or ''
220 self._on_option_changed()
221 self._on_name_changed()
222
223 def _on_option_changed(self, entry=None):
224 options = self._options.get(self._current_page)
225 options.background_disabled = self._option_bg.value
226 options.background = options.background_disabled if self._option_bg.enabled else None
227 options.user_background_disabled = self._option_user_bg.value
228 options.user_background = (options.user_background_disabled
229 if self._option_user_bg.enabled else None)
230 options.laptop_disabled = self._option_laptop.value
231 options.laptop = options.laptop_disabled if self._option_laptop.enabled else None
232
233 if not options.background or Gdk.RGBA().parse(options.background):
234 self._option_bg.error = None
235 else:
236 self._option_bg.error = check_path_accessibility(options.background)
237
238 def _on_name_changed(self, entry=None):
239 options = self._options[self._current_page]
240 options.name = self._option_name.value.strip()
241 self._update_monitors_list()
242
243 markup = None
145244 error = None
146 color = Gdk.RGBA()
147 if color.parse(bg):
148 pixbuf = row[Row.BackgroundPixbuf]
149 if not pixbuf:
150 pixbuf = GdkPixbuf.Pixbuf.new(GdkPixbuf.Colorspace.RGB, False, 8, 16, 16)
151 row[Row.BackgroundPixbuf] = pixbuf
152 value = (int(0xFF * color.red) << 24) + \
153 (int(0xFF * color.green) << 16) + \
154 (int(0xFF * color.blue) << 8)
155 pixbuf.fill(value)
156 row[Row.BackgroundIsColor] = True
245
246 if not options.name:
247 markup = C_('<i>No name</i>')
248 error = C_('The name can\'t be empty. Configuration will not be saved.')
249 elif any(options.name == o.name and p != self._current_page
250 for p, o in self._options.items()):
251 error = (C_('"{name}" is already defined. Only last configuration will be saved.')
252 .format(name=options.name))
253
254 if markup:
255 options.label.set_markup(markup)
157256 else:
158 row[Row.BackgroundIsColor] = False
159 if bg:
160 error = check_path_accessibility(bg)
161
162 row[Row.ErrorVisible] = error is not None
163 row[Row.ErrorText] = error
164
165 ToggleStatesSeq = {None: True, False: None, True: False}
166
167 def _get_toggle_state(self, row, active_column, inconsistent_column):
168 return None if row[inconsistent_column] else row[active_column]
169
170 def _toggle_state(self, row, active_column, inconsistent_column):
171 state = self._get_toggle_state(row, active_column, inconsistent_column)
172 row[active_column] = self.ToggleStatesSeq[state]
173 row[inconsistent_column] = self.ToggleStatesSeq[state] is None
174
175 def on_monitors_add_clicked(self, button):
176 prefix = 'monitor'
177 numbers = (row[Row.Name][len(prefix):]
178 for row in self._widgets.model if row[Row.Name].startswith(prefix))
179 try:
180 max_number = max(int(v) for v in numbers if v.isdigit())
181 except ValueError:
182 max_number = 0
183
184 row = Row._make(Name='%s%d' % (prefix, max_number + 1),
185 UserBg=False,
186 UserBgDisabled=False,
187 Laptop=True,
188 LaptopDisabled=False,
189 Background='',
190 BackgroundPixbuf=None,
191 BackgroundIsColor=False,
192 ErrorVisible=False,
193 ErrorText=None)
194 rowiter = self._widgets.model.append(row)
195 self._widgets.treeview.set_cursor(self._widgets.model.get_path(rowiter),
196 self._widgets.name_column, True)
197
198 def on_monitors_remove_clicked(self, button):
199 model, rowiter = self._widgets.selection.get_selected()
200 model.remove(rowiter)
201 self._update_monitors_label()
202
203 def on_selection_changed(self, selection):
204 self._widgets.remove.props.sensitive = all(selection.get_selected())
205
206 def on_monitors_label_activate_link(self, label, name):
207 row = Row._make(Name=name,
208 UserBg=False,
209 UserBgDisabled=False,
210 Laptop=True,
211 LaptopDisabled=False,
212 Background='',
213 BackgroundPixbuf=None,
214 BackgroundIsColor=True,
215 ErrorVisible=False,
216 ErrorText=None)
217
218 rowiter = self._widgets.model.append(row)
219 self._update_row_appearance(rowiter)
220 self._widgets.selection.select_iter(rowiter)
221 self._update_monitors_label()
222 return True
223
224 def on_bg_renderer_editing_started(self, renderer, combobox, path):
225 combobox.connect('format-entry-text', self.on_bg_combobox_format)
226
227 def on_bg_combobox_format(self, combobox, path):
228 model, rowiter = self._widgets.selection.get_selected()
229 item_type = combobox.props.model[path][BackgroundRow.Type]
230 value = model[rowiter][Row.Background]
231
232 if item_type == 'path':
233 if not self._file_dialog:
234 self._file_dialog = Gtk.FileChooserDialog(
235 parent=self,
236 buttons=(_('_OK'), Gtk.ResponseType.OK,
237 _('_Cancel'), Gtk.ResponseType.CANCEL),
238 title=C_('option|multihead', 'Select background file'))
239 self._file_dialog.props.filter = Gtk.FileFilter()
240 self._file_dialog.props.filter.add_mime_type('image/*')
241 if self._file_dialog.run() == Gtk.ResponseType.OK:
242 value = self._file_dialog.get_filename()
243 self._file_dialog.hide()
244 elif item_type == 'color':
245 if not self._color_dialog:
246 self._color_dialog = Gtk.ColorChooserDialog(parent=self)
247 if self._color_dialog.run() == Gtk.ResponseType.OK:
248 value = self._color_dialog.get_rgba().to_color().to_string()
249 self._color_dialog.hide()
257 options.label.set_label(options.name)
258
259 self._option_name.error = error
260
261 def _focus_name_entry(self):
262 self._widgets.name.grab_focus()
263 self._widgets.name.set_position(0)
264
265 def on_add_button_clicked(self, widget, name=""):
266 options = PageOptions()
267 options.name = name
268
269 options.background_disabled = self._get_first_not_none(
270 self._defaults.get('background'), '')
271 options.user_background_disabled = self._get_first_not_none(
272 self._defaults.get('user-background'), 'true')
273 options.laptop = self._get_first_not_none(self._defaults.get('laptop'), 'false')
274
275 self._widgets.notebook.set_current_page(self._add_monitor(options))
276 if name:
277 self._update_monitors_list()
278
279 def on_monitors_notebook_switch_page(self, notebook, page, page_idx):
280 if page == self._widgets.empty:
281 self._current_page = None
282 buttons = self._widgets.editor_add_menu_button, self._widgets.empty_add_menu_button
250283 else:
251 value = ''
252
253 combobox.set_active(-1)
254 return value
255
256 def on_bg_renderer_edited(self, renderer, path, new_text):
257 self._widgets.model[path][Row.Background] = new_text
258 self._update_row_appearance(self._widgets.model.get_iter(path))
259
260 def on_name_renderer_edited(self, renderer, path, new_name):
261 old_name = self._widgets.model[path][Row.Name]
262 invalid_name = not new_name.strip()
263 name_in_use = new_name != old_name and any(new_name == row[Row.Name]
264 for row in self._widgets.model)
265 if invalid_name or name_in_use:
266 if not self._invalid_name_dialog:
267 self._invalid_name_dialog = Gtk.MessageDialog(parent=self,
268 buttons=Gtk.ButtonsType.OK)
269 self._invalid_name_dialog.set_property('text',
270 C_('option|multihead',
271 'Invalid name: "{name}"')
272 .format(name=new_name))
273 if name_in_use:
274 message = C_('option|multihead', 'This name already in use.')
275 else:
276 message = C_('option|multihead', 'This name is not valid.')
277 self._invalid_name_dialog.set_property('secondary-text', message)
278 self._invalid_name_dialog.run()
279 self._invalid_name_dialog.hide()
280 else:
281 self._widgets.model[path][Row.Name] = new_name
282 self._update_monitors_label()
283
284 def on_user_bg_renderer_toggled(self, renderer, path):
285 self._toggle_state(self._widgets.model[path], Row.UserBg, Row.UserBgDisabled)
286
287 def on_laptop_renderer_toggled(self, renderer, path):
288 self._toggle_state(self._widgets.model[path], Row.Laptop, Row.LaptopDisabled)
284 self._current_page = page
285 buttons = self._widgets.empty_add_menu_button, self._widgets.editor_add_menu_button
286
287 old_parent = self._widgets.editor.get_parent()
288 if old_parent:
289 old_parent.remove(self._widgets.editor)
290 page.add(self._widgets.editor)
291 self._apply_monitor_options(self._options[page])
292
293 GLib.idle_add(self._focus_name_entry)
294
295 buttons[0].props.popup = None
296 buttons[1].props.popup = self._widgets.available_menu
297
298 def _update_monitors_list(self):
299 used_monitors = set(options.name for options in self._options.values())
300 used_count = 0
301 self._widgets.name_combo.get_model().clear()
302 for name, item in self._available_monitors:
303 used = name in used_monitors
304 if used:
305 used_count += 1
306 item.props.visible = not used
307 if not used:
308 self._widgets.name_combo.append_text(name)
309
310 show_button = used_count < len(self._available_monitors)
311 self._widgets.name_combo.props.button_sensitivity = (Gtk.SensitivityType.ON if show_button
312 else Gtk.SensitivityType.OFF)
313 self._widgets.editor_add_menu_button.props.visible = show_button
314 self._widgets.empty_add_menu_button.props.visible = show_button
315315 self._image_value = widgets['image_value']
316316 self._color_value = widgets['color_value']
317317
318 self._widgets_to_disable.append(self._image_choice)
319 self._widgets_to_disable.append(self._color_choice)
320 self._widgets_to_disable.append(self._image_value)
321 self._widgets_to_disable.append(self._color_value)
322
318323 self._on_choice_id = self._color_choice.connect('toggled', self._on_color_choice_toggled)
319324 self._color_value.connect('color-set', self._on_color_set)
320325 self._image_value.connect('file-set', self._on_file_set)
2929 # Broken solution - too complex
3030 class BaseGroup(GObject.GObject):
3131
32 class __DictWrapper:
33
34 def __init__(self, getter):
35 self._getter = getter
36
37 def __getitem__(self, key):
38 return self._getter(key)
39
3240 def __init__(self, widgets):
3341 super().__init__()
42 self.__entries_wrapper = None
3443 self.__defaults_wrapper = None
3544
3645 def read(self, config):
4049 raise NotImplementedError(self.__class__)
4150
4251 @property
52 def entries(self):
53 if not self.__entries_wrapper:
54 self.__entries_wrapper = BaseGroup.__DictWrapper(self._get_entry)
55 return self.__entries_wrapper
56
57 @property
4358 def defaults(self):
4459 if not self.__defaults_wrapper:
45 class DefaultsWrapper:
46
47 def __init__(self, getter):
48 self._getter = getter
49
50 def __getitem__(self, key):
51 return self._getter(key)
52 self.__defaults_wrapper = DefaultsWrapper(self._get_default)
60 self.__defaults_wrapper = BaseGroup.__DictWrapper(self._get_default)
5361 return self.__defaults_wrapper
5462
5563 def _get_default(self, key):
64 raise NotImplementedError(self.__class__)
65
66 def _get_entry(self, key):
5667 raise NotImplementedError(self.__class__)
5768
5869 @GObject.Signal
109120 else:
110121 config.remove_option(self._name, key)
111122
123 def _get_entry(self, key):
124 return self._entries.get(key)
125
112126 def _get_default(self, key):
113127 return self._defaults.get(key)
77 msgstr ""
88 "Project-Id-Version: PACKAGE VERSION\n"
99 "Report-Msgid-Bugs-To: \n"
10 "POT-Creation-Date: 2015-02-09 12:54+0300\n"
10 "POT-Creation-Date: 2015-03-12 11:41+0300\n"
1111 "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
1212 "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
1313 "Language-Team: LANGUAGE <LL@li.org>\n"
113113 msgstr ""
114114
115115 #: ../data/GtkGreeterSettingsWindow.ui.h:19
116 #: ../data/MultiheadSetupDialog.ui.h:7
116117 msgctxt "option|greeter|background"
117118 msgid "Color"
118119 msgstr ""
119120
120121 #: ../data/GtkGreeterSettingsWindow.ui.h:20
122 #: ../data/MultiheadSetupDialog.ui.h:6
121123 msgctxt "option|greeter|background"
122124 msgid "Image"
123125 msgstr ""
148150 msgstr ""
149151
150152 #: ../data/GtkGreeterSettingsWindow.ui.h:26
153 #: ../data/MultiheadSetupDialog.ui.h:15
151154 msgctxt "option|greeter|user-background"
152155 msgid "Use user wallpaper if available"
153156 msgstr ""
373376 msgid "Select icon"
374377 msgstr ""
375378
376 #: ../data/IconChooserDialog.ui.h:2 ../data/MultiheadSetupDialog.ui.h:5
379 #: ../data/IconChooserDialog.ui.h:2 ../data/MultiheadSetupDialog.ui.h:2
377380 msgctxt "button"
378381 msgid "_Cancel"
379382 msgstr ""
380383
381384 #: ../data/IconChooserDialog.ui.h:3 ../data/IndicatorPropertiesDialog.ui.h:4
382 #: ../data/MultiheadSetupDialog.ui.h:6
385 #: ../data/MultiheadSetupDialog.ui.h:3
383386 msgctxt "button"
384387 msgid "_OK"
385388 msgstr ""
409412 msgstr ""
410413
411414 #: ../data/ImageChooserDialog.ui.h:1
412 #: ../lightdm_gtk_greeter_settings/MultiheadSetupDialog.py:238
413415 #: ../lightdm_gtk_greeter_settings/OptionEntry.py:248
414416 msgid "_Cancel"
415417 msgstr ""
416418
417419 #: ../data/ImageChooserDialog.ui.h:2
418 #: ../lightdm_gtk_greeter_settings/MultiheadSetupDialog.py:237
419420 #: ../lightdm_gtk_greeter_settings/OptionEntry.py:247
420421 msgid "_OK"
421422 msgstr ""
482483
483484 #: ../data/MultiheadSetupDialog.ui.h:1
484485 msgctxt "option|multihead"
485 msgid "Select a file"
486 msgstr ""
487
488 #: ../data/MultiheadSetupDialog.ui.h:2
489 msgctxt "option|multihead"
490 msgid "Select color"
491 msgstr ""
492
493 #: ../data/MultiheadSetupDialog.ui.h:3
494 #: ../lightdm_gtk_greeter_settings/MultiheadSetupDialog.py:93
495 msgctxt "option|multihead"
496 msgid "Use default value"
486 msgid "Multihead setup"
497487 msgstr ""
498488
499489 #: ../data/MultiheadSetupDialog.ui.h:4
500 msgctxt "option|multihead"
501 msgid "Multihead setup"
502 msgstr ""
503
504 #: ../data/MultiheadSetupDialog.ui.h:7
505 msgctxt "option|multihead"
506 msgid "Monitor"
507 msgstr ""
508
509 #: ../data/MultiheadSetupDialog.ui.h:8
510 msgctxt "option|multihead"
511 msgid "User's"
512 msgstr ""
513
514 #: ../data/MultiheadSetupDialog.ui.h:9
515 msgctxt "option|multihead"
516 msgid "Laptop"
517 msgstr ""
518
519 #: ../data/MultiheadSetupDialog.ui.h:10
520 msgctxt "option|multihead"
521 msgid "Background"
522 msgstr ""
523
524 #: ../data/MultiheadSetupDialog.ui.h:11
525 msgctxt "option|multihead"
526 msgid "Add monior to the list"
527 msgstr ""
528
529 #: ../data/MultiheadSetupDialog.ui.h:12
530 msgctxt "option|multihead"
531 msgid "Add"
532 msgstr ""
533
534 #: ../data/MultiheadSetupDialog.ui.h:13
535 msgctxt "option|multihead"
536 msgid "Remove monitor from the list"
537 msgstr ""
538
539 #: ../data/MultiheadSetupDialog.ui.h:14
540 msgctxt "option|multihead"
541 msgid "Remove"
542 msgstr ""
543
544 #: ../data/MultiheadSetupDialog.ui.h:15
545490 msgctxt "option|multihead"
546491 msgid ""
547492 "<i>Note: greeter do not set monitors geometry.\n"
548493 "You need to configure it by yourself.</i>"
549494 msgstr ""
550495
551 #: ../lightdm_gtk_greeter_settings/GtkGreeterSettingsWindow.py:143
496 #: ../data/MultiheadSetupDialog.ui.h:8
497 msgctxt "option|greeter|laptop"
498 msgid "This monitor is laptop display (detect lid closing)"
499 msgstr ""
500
501 #: ../data/MultiheadSetupDialog.ui.h:9
502 msgctxt "option|multihead"
503 msgid "Overwrite default \"user-background\" option"
504 msgstr ""
505
506 #: ../data/MultiheadSetupDialog.ui.h:10
507 msgctxt "option|multihead"
508 msgid "Overwrite default \"laptop\" option"
509 msgstr ""
510
511 #: ../data/MultiheadSetupDialog.ui.h:11
512 msgctxt "option|multihead"
513 msgid "Monitor name:"
514 msgstr ""
515
516 #: ../data/MultiheadSetupDialog.ui.h:12
517 msgctxt "option|multihead"
518 msgid "Don't leave empty"
519 msgstr ""
520
521 #: ../data/MultiheadSetupDialog.ui.h:13
522 msgctxt "option|multihead"
523 msgid "Add new monitor configuration"
524 msgstr ""
525
526 #: ../data/MultiheadSetupDialog.ui.h:14
527 msgctxt "option|multihead"
528 msgid "Overwrite default \"background\" option"
529 msgstr ""
530
531 #: ../data/MultiheadSetupDialog.ui.h:16
532 msgctxt "option|multihead"
533 msgid "Add configuration"
534 msgstr ""
535
536 #: ../lightdm_gtk_greeter_settings/GtkGreeterSettingsWindow.py:146
552537 msgid "You don't have permissions to change greeter configuration"
553538 msgstr ""
554539
555 #: ../lightdm_gtk_greeter_settings/GtkGreeterSettingsWindow.py:147
540 #: ../lightdm_gtk_greeter_settings/GtkGreeterSettingsWindow.py:150
556541 msgid "No permissions to save configuration"
557542 msgstr ""
558543
559 #: ../lightdm_gtk_greeter_settings/GtkGreeterSettingsWindow.py:149
544 #: ../lightdm_gtk_greeter_settings/GtkGreeterSettingsWindow.py:152
560545 #, python-brace-format
561546 msgid ""
562547 "It seems that you don't have permissions to write to file:\n"
565550 "Try to run this program using \"sudo\" or \"pkexec\""
566551 msgstr ""
567552
568 #: ../lightdm_gtk_greeter_settings/GtkGreeterSettingsWindow.py:195
553 #: ../lightdm_gtk_greeter_settings/GtkGreeterSettingsWindow.py:202
569554 #, python-brace-format
570555 msgid "Failed to read configuration file: {path}"
571556 msgstr ""
572557
573 #: ../lightdm_gtk_greeter_settings/GtkGreeterSettingsWindow.py:322
558 #: ../lightdm_gtk_greeter_settings/GtkGreeterSettingsWindow.py:346
574559 msgid "<i>disabled</i>"
575560 msgstr ""
576561
577 #: ../lightdm_gtk_greeter_settings/GtkGreeterSettingsWindow.py:324
562 #: ../lightdm_gtk_greeter_settings/GtkGreeterSettingsWindow.py:348
578563 msgid "<i>empty string</i>"
579564 msgstr ""
580565
581 #: ../lightdm_gtk_greeter_settings/GtkGreeterSettingsWindow.py:326
566 #: ../lightdm_gtk_greeter_settings/GtkGreeterSettingsWindow.py:350
582567 msgid "<i>None</i>"
583568 msgstr ""
584569
585 #: ../lightdm_gtk_greeter_settings/GtkGreeterSettingsWindow.py:347
570 #: ../lightdm_gtk_greeter_settings/GtkGreeterSettingsWindow.py:390
586571 #, python-brace-format
587572 msgid "Reset to initial value: <b>{value}</b>"
588573 msgstr ""
589574
590 #: ../lightdm_gtk_greeter_settings/GtkGreeterSettingsWindow.py:358
575 #: ../lightdm_gtk_greeter_settings/GtkGreeterSettingsWindow.py:401
591576 #, python-brace-format
592577 msgid "Reset to default value: <b>{value}</b>"
593578 msgstr ""
594579
595 #: ../lightdm_gtk_greeter_settings/GtkGreeterSettingsWindow.py:377
580 #: ../lightdm_gtk_greeter_settings/GtkGreeterSettingsWindow.py:420
596581 #, python-brace-format
597582 msgctxt "option|greeter|screensaver-timeout"
598583 msgid "{count} min"
599584 msgstr ""
600585
601 #: ../lightdm_gtk_greeter_settings/GtkGreeterSettingsWindow.py:440
586 #: ../lightdm_gtk_greeter_settings/GtkGreeterSettingsWindow.py:483
602587 #, python-brace-format
603588 msgctxt "option|greeter|allow-debugging"
604589 msgid ""
854839 msgid "Predefined templates:"
855840 msgstr ""
856841
857 #: ../lightdm_gtk_greeter_settings/MultiheadSetupDialog.py:109
858 #, python-brace-format
859 msgctxt "option|multihead"
860 msgid "Available monitors: {monitors}"
861 msgstr ""
862
863 #: ../lightdm_gtk_greeter_settings/MultiheadSetupDialog.py:239
864 msgctxt "option|multihead"
865 msgid "Select background file"
866 msgstr ""
867
868 #: ../lightdm_gtk_greeter_settings/MultiheadSetupDialog.py:272
869 #, python-brace-format
870 msgctxt "option|multihead"
871 msgid "Invalid name: \"{name}\""
872 msgstr ""
873
874 #: ../lightdm_gtk_greeter_settings/MultiheadSetupDialog.py:275
875 msgctxt "option|multihead"
876 msgid "This name already in use."
877 msgstr ""
878
879 #: ../lightdm_gtk_greeter_settings/MultiheadSetupDialog.py:277
880 msgctxt "option|multihead"
881 msgid "This name is not valid."
882 msgstr ""
883
884842 #: ../lightdm_gtk_greeter_settings/OptionEntry.py:249
885843 msgctxt "option|StringPathEntry"
886844 msgid "Select path"