New MultiheadSetupDialog
Andrew P.
9 years ago
1 | 1 | <!-- Generated with glade 3.18.3 --> |
2 | 2 | <interface> |
3 | 3 | <requires lib="gtk+" version="3.8"/> |
4 | <requires lib="*MultiheadSetupDialog (copy 2).ui" version="0.0"/> | |
4 | 5 | <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> | |
26 | 9 | </object> |
27 | 10 | <object class="GtkFileFilter" id="filefilter1"> |
28 | 11 | <mime-types> |
29 | 12 | <mime-type>image/*</mime-type> |
30 | 13 | </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> | |
31 | 19 | </object> |
32 | 20 | <object class="GtkImage" id="image2"> |
33 | 21 | <property name="visible">True</property> |
41 | 29 | <property name="xpad">2</property> |
42 | 30 | <property name="icon_name">dialog-ok</property> |
43 | 31 | </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> | |
67 | 36 | </object> |
68 | 37 | <object class="MultiheadSetupDialog" id="multihead_setup_dialog"> |
69 | 38 | <property name="width_request">500</property> |
127 | 96 | </packing> |
128 | 97 | </child> |
129 | 98 | <child> |
130 | <object class="GtkBox" id="box7"> | |
99 | <object class="GtkNotebook" id="monitors_notebook"> | |
131 | 100 | <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"/> | |
137 | 106 | <child> |
138 | <object class="GtkBox" id="box1"> | |
107 | <object class="GtkBox" id="empty_page"> | |
139 | 108 | <property name="visible">True</property> |
140 | 109 | <property name="can_focus">False</property> |
141 | 110 | <property name="orientation">vertical</property> |
142 | 111 | <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> | |
147 | 121 | <property name="hexpand">True</property> |
148 | 122 | <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> | |
153 | 126 | <property name="visible">True</property> |
154 | 127 | <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/> | |
162 | 150 | </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> | |
245 | 157 | </child> |
246 | 158 | </object> |
247 | 159 | <packing> |
250 | 162 | <property name="position">0</property> |
251 | 163 | </packing> |
252 | 164 | </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> | |
298 | 172 | </object> |
299 | 173 | <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> | |
303 | 175 | </packing> |
304 | 176 | </child> |
305 | 177 | <child> |
306 | <object class="GtkLabel" id="monitors_label"> | |
178 | <object class="GtkGrid" id="editor_page"> | |
307 | 179 | <property name="visible">True</property> |
308 | 180 | <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> | |
313 | 452 | </object> |
314 | 453 | <packing> |
315 | <property name="expand">False</property> | |
316 | <property name="fill">True</property> | |
317 | 454 | <property name="position">1</property> |
318 | 455 | </packing> |
319 | 456 | </child> |
320 | <child> | |
321 | <object class="GtkLabel" id="label2"> | |
457 | <child type="tab"> | |
458 | <object class="GtkLabel" id="label4"> | |
322 | 459 | <property name="visible">True</property> |
323 | 460 | <property name="can_focus">False</property> |
324 | <property name="xalign">0</property> | |
325 | <property name="label" translatable="yes" context="option|multihead"><i>Note: greeter do not set monitors geometry. | |
326 | You need to configure it by yourself.</i></property> | |
327 | <property name="use_markup">True</property> | |
328 | <property name="wrap">True</property> | |
461 | <property name="label">[editor]</property> | |
329 | 462 | </object> |
330 | 463 | <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> | |
334 | 466 | </packing> |
335 | 467 | </child> |
336 | 468 | </object> |
337 | 469 | <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"><i>Note: greeter do not set monitors geometry. | |
482 | You need to configure it by yourself.</i></property> | |
483 | <property name="use_markup">True</property> | |
484 | <property name="wrap">True</property> | |
485 | </object> | |
486 | <packing> | |
487 | <property name="expand">False</property> | |
339 | 488 | <property name="fill">True</property> |
340 | 489 | <property name="position">1</property> |
341 | 490 | </packing> |
103 | 103 | self._initial_values = {} |
104 | 104 | self._changed_entries = None |
105 | 105 | 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 | |
133 | 135 | |
134 | 136 | for group in self._groups: |
135 | 137 | group.entry_added.connect(self.on_entry_added) |
228 | 230 | except OSError as e: |
229 | 231 | helpers.show_message(e, Gtk.MessageType.ERROR) |
230 | 232 | |
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 | ||
231 | 237 | def on_entry_added(self, group, entry, key): |
232 | 238 | if isinstance(group, SimpleGroup) and (group.name, key) in self.entries_setup: |
233 | 239 | for action in self.entries_setup[(group.name, key)]: |
15 | 15 | # with this program. If not, see <http://www.gnu.org/licenses/>. |
16 | 16 | |
17 | 17 | |
18 | from collections import OrderedDict | |
19 | ||
18 | 20 | from gi.repository import Gtk |
19 | 21 | |
20 | 22 | from lightdm_gtk_greeter_settings.helpers import WidgetsWrapper |
29 | 31 | class MonitorsGroup(BaseGroup): |
30 | 32 | GROUP_PREFIX = 'monitor:' |
31 | 33 | |
32 | def __init__(self, widgets): | |
34 | def __init__(self, widgets, defaults_callback=None): | |
33 | 35 | super().__init__(widgets) |
34 | self._entries = {} | |
36 | self._entries = OrderedDict() | |
35 | 37 | self._widgets = WidgetsWrapper(widgets, 'multihead') |
38 | self._widgets['label'].connect('activate-link', self._on_label_link_activate) | |
36 | 39 | self._dialog = None |
37 | self._widgets['label'].connect('activate-link', self._on_label_link_activate) | |
40 | self._get_defaults_callback = defaults_callback | |
38 | 41 | |
39 | 42 | def read(self, config): |
40 | 43 | self._entries.clear() |
53 | 56 | for name in config.sections(): |
54 | 57 | if name.startswith(self.GROUP_PREFIX): |
55 | 58 | config.remove_section(name) |
59 | ||
56 | 60 | 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()) | |
58 | 62 | config.add_section(section) |
59 | 63 | for key, value in entry: |
60 | 64 | if value is not None: |
65 | 69 | self._dialog = MultiheadSetupDialog() |
66 | 70 | self._dialog.props.transient_for = self._widgets['label'].get_toplevel() |
67 | 71 | |
72 | if self._get_defaults_callback: | |
73 | self._dialog.set_defaults(self._get_defaults_callback()) | |
74 | ||
68 | 75 | self._dialog.set_model(self._entries) |
69 | 76 | |
70 | 77 | if self._dialog.run() == Gtk.ResponseType.OK: |
71 | 78 | 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(): | |
73 | 80 | if name in self._entries: |
74 | 81 | self._entries[name].assign(values) |
75 | 82 | current_names.discard(name) |
15 | 15 | # with this program. If not, see <http://www.gnu.org/licenses/>. |
16 | 16 | |
17 | 17 | |
18 | from builtins import max | |
19 | from locale import gettext as _ | |
20 | ||
21 | 18 | from gi.repository import ( |
22 | 19 | Gdk, |
23 | GdkPixbuf, | |
24 | 20 | Gtk) |
25 | 21 | |
22 | import lightdm_gtk_greeter_settings.helpers | |
23 | ||
26 | 24 | from lightdm_gtk_greeter_settings.helpers import ( |
27 | C_, | |
28 | 25 | check_path_accessibility, |
29 | 26 | 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 | |
32 | 32 | |
33 | 33 | |
34 | 34 | __all__ = ['MultiheadSetupDialog'] |
35 | 35 | |
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 | |
53 | 48 | |
54 | 49 | |
55 | 50 | class MultiheadSetupDialog(Gtk.Dialog): |
57 | 52 | |
58 | 53 | def __new__(cls): |
59 | 54 | 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__)) | |
61 | 56 | window = builder.get_object('multihead_setup_dialog') |
62 | 57 | window.builder = builder |
63 | 58 | builder.connect_signals(window) |
65 | 60 | return window |
66 | 61 | |
67 | 62 | 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' | |
77 | 74 | |
78 | 75 | builder = None |
79 | 76 | |
80 | 77 | def init_window(self): |
81 | 78 | 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: | |
97 | 195 | return |
98 | 196 | |
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 | |
145 | 244 | 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) | |
157 | 256 | 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 | |
250 | 283 | 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 |
315 | 315 | self._image_value = widgets['image_value'] |
316 | 316 | self._color_value = widgets['color_value'] |
317 | 317 | |
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 | ||
318 | 323 | self._on_choice_id = self._color_choice.connect('toggled', self._on_color_choice_toggled) |
319 | 324 | self._color_value.connect('color-set', self._on_color_set) |
320 | 325 | self._image_value.connect('file-set', self._on_file_set) |
29 | 29 | # Broken solution - too complex |
30 | 30 | class BaseGroup(GObject.GObject): |
31 | 31 | |
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 | ||
32 | 40 | def __init__(self, widgets): |
33 | 41 | super().__init__() |
42 | self.__entries_wrapper = None | |
34 | 43 | self.__defaults_wrapper = None |
35 | 44 | |
36 | 45 | def read(self, config): |
40 | 49 | raise NotImplementedError(self.__class__) |
41 | 50 | |
42 | 51 | @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 | |
43 | 58 | def defaults(self): |
44 | 59 | 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) | |
53 | 61 | return self.__defaults_wrapper |
54 | 62 | |
55 | 63 | def _get_default(self, key): |
64 | raise NotImplementedError(self.__class__) | |
65 | ||
66 | def _get_entry(self, key): | |
56 | 67 | raise NotImplementedError(self.__class__) |
57 | 68 | |
58 | 69 | @GObject.Signal |
109 | 120 | else: |
110 | 121 | config.remove_option(self._name, key) |
111 | 122 | |
123 | def _get_entry(self, key): | |
124 | return self._entries.get(key) | |
125 | ||
112 | 126 | def _get_default(self, key): |
113 | 127 | return self._defaults.get(key) |
7 | 7 | msgstr "" |
8 | 8 | "Project-Id-Version: PACKAGE VERSION\n" |
9 | 9 | "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" | |
11 | 11 | "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" |
12 | 12 | "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" |
13 | 13 | "Language-Team: LANGUAGE <LL@li.org>\n" |
113 | 113 | msgstr "" |
114 | 114 | |
115 | 115 | #: ../data/GtkGreeterSettingsWindow.ui.h:19 |
116 | #: ../data/MultiheadSetupDialog.ui.h:7 | |
116 | 117 | msgctxt "option|greeter|background" |
117 | 118 | msgid "Color" |
118 | 119 | msgstr "" |
119 | 120 | |
120 | 121 | #: ../data/GtkGreeterSettingsWindow.ui.h:20 |
122 | #: ../data/MultiheadSetupDialog.ui.h:6 | |
121 | 123 | msgctxt "option|greeter|background" |
122 | 124 | msgid "Image" |
123 | 125 | msgstr "" |
148 | 150 | msgstr "" |
149 | 151 | |
150 | 152 | #: ../data/GtkGreeterSettingsWindow.ui.h:26 |
153 | #: ../data/MultiheadSetupDialog.ui.h:15 | |
151 | 154 | msgctxt "option|greeter|user-background" |
152 | 155 | msgid "Use user wallpaper if available" |
153 | 156 | msgstr "" |
373 | 376 | msgid "Select icon" |
374 | 377 | msgstr "" |
375 | 378 | |
376 | #: ../data/IconChooserDialog.ui.h:2 ../data/MultiheadSetupDialog.ui.h:5 | |
379 | #: ../data/IconChooserDialog.ui.h:2 ../data/MultiheadSetupDialog.ui.h:2 | |
377 | 380 | msgctxt "button" |
378 | 381 | msgid "_Cancel" |
379 | 382 | msgstr "" |
380 | 383 | |
381 | 384 | #: ../data/IconChooserDialog.ui.h:3 ../data/IndicatorPropertiesDialog.ui.h:4 |
382 | #: ../data/MultiheadSetupDialog.ui.h:6 | |
385 | #: ../data/MultiheadSetupDialog.ui.h:3 | |
383 | 386 | msgctxt "button" |
384 | 387 | msgid "_OK" |
385 | 388 | msgstr "" |
409 | 412 | msgstr "" |
410 | 413 | |
411 | 414 | #: ../data/ImageChooserDialog.ui.h:1 |
412 | #: ../lightdm_gtk_greeter_settings/MultiheadSetupDialog.py:238 | |
413 | 415 | #: ../lightdm_gtk_greeter_settings/OptionEntry.py:248 |
414 | 416 | msgid "_Cancel" |
415 | 417 | msgstr "" |
416 | 418 | |
417 | 419 | #: ../data/ImageChooserDialog.ui.h:2 |
418 | #: ../lightdm_gtk_greeter_settings/MultiheadSetupDialog.py:237 | |
419 | 420 | #: ../lightdm_gtk_greeter_settings/OptionEntry.py:247 |
420 | 421 | msgid "_OK" |
421 | 422 | msgstr "" |
482 | 483 | |
483 | 484 | #: ../data/MultiheadSetupDialog.ui.h:1 |
484 | 485 | 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" | |
497 | 487 | msgstr "" |
498 | 488 | |
499 | 489 | #: ../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 | |
545 | 490 | msgctxt "option|multihead" |
546 | 491 | msgid "" |
547 | 492 | "<i>Note: greeter do not set monitors geometry.\n" |
548 | 493 | "You need to configure it by yourself.</i>" |
549 | 494 | msgstr "" |
550 | 495 | |
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 | |
552 | 537 | msgid "You don't have permissions to change greeter configuration" |
553 | 538 | msgstr "" |
554 | 539 | |
555 | #: ../lightdm_gtk_greeter_settings/GtkGreeterSettingsWindow.py:147 | |
540 | #: ../lightdm_gtk_greeter_settings/GtkGreeterSettingsWindow.py:150 | |
556 | 541 | msgid "No permissions to save configuration" |
557 | 542 | msgstr "" |
558 | 543 | |
559 | #: ../lightdm_gtk_greeter_settings/GtkGreeterSettingsWindow.py:149 | |
544 | #: ../lightdm_gtk_greeter_settings/GtkGreeterSettingsWindow.py:152 | |
560 | 545 | #, python-brace-format |
561 | 546 | msgid "" |
562 | 547 | "It seems that you don't have permissions to write to file:\n" |
565 | 550 | "Try to run this program using \"sudo\" or \"pkexec\"" |
566 | 551 | msgstr "" |
567 | 552 | |
568 | #: ../lightdm_gtk_greeter_settings/GtkGreeterSettingsWindow.py:195 | |
553 | #: ../lightdm_gtk_greeter_settings/GtkGreeterSettingsWindow.py:202 | |
569 | 554 | #, python-brace-format |
570 | 555 | msgid "Failed to read configuration file: {path}" |
571 | 556 | msgstr "" |
572 | 557 | |
573 | #: ../lightdm_gtk_greeter_settings/GtkGreeterSettingsWindow.py:322 | |
558 | #: ../lightdm_gtk_greeter_settings/GtkGreeterSettingsWindow.py:346 | |
574 | 559 | msgid "<i>disabled</i>" |
575 | 560 | msgstr "" |
576 | 561 | |
577 | #: ../lightdm_gtk_greeter_settings/GtkGreeterSettingsWindow.py:324 | |
562 | #: ../lightdm_gtk_greeter_settings/GtkGreeterSettingsWindow.py:348 | |
578 | 563 | msgid "<i>empty string</i>" |
579 | 564 | msgstr "" |
580 | 565 | |
581 | #: ../lightdm_gtk_greeter_settings/GtkGreeterSettingsWindow.py:326 | |
566 | #: ../lightdm_gtk_greeter_settings/GtkGreeterSettingsWindow.py:350 | |
582 | 567 | msgid "<i>None</i>" |
583 | 568 | msgstr "" |
584 | 569 | |
585 | #: ../lightdm_gtk_greeter_settings/GtkGreeterSettingsWindow.py:347 | |
570 | #: ../lightdm_gtk_greeter_settings/GtkGreeterSettingsWindow.py:390 | |
586 | 571 | #, python-brace-format |
587 | 572 | msgid "Reset to initial value: <b>{value}</b>" |
588 | 573 | msgstr "" |
589 | 574 | |
590 | #: ../lightdm_gtk_greeter_settings/GtkGreeterSettingsWindow.py:358 | |
575 | #: ../lightdm_gtk_greeter_settings/GtkGreeterSettingsWindow.py:401 | |
591 | 576 | #, python-brace-format |
592 | 577 | msgid "Reset to default value: <b>{value}</b>" |
593 | 578 | msgstr "" |
594 | 579 | |
595 | #: ../lightdm_gtk_greeter_settings/GtkGreeterSettingsWindow.py:377 | |
580 | #: ../lightdm_gtk_greeter_settings/GtkGreeterSettingsWindow.py:420 | |
596 | 581 | #, python-brace-format |
597 | 582 | msgctxt "option|greeter|screensaver-timeout" |
598 | 583 | msgid "{count} min" |
599 | 584 | msgstr "" |
600 | 585 | |
601 | #: ../lightdm_gtk_greeter_settings/GtkGreeterSettingsWindow.py:440 | |
586 | #: ../lightdm_gtk_greeter_settings/GtkGreeterSettingsWindow.py:483 | |
602 | 587 | #, python-brace-format |
603 | 588 | msgctxt "option|greeter|allow-debugging" |
604 | 589 | msgid "" |
854 | 839 | msgid "Predefined templates:" |
855 | 840 | msgstr "" |
856 | 841 | |
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 | ||
884 | 842 | #: ../lightdm_gtk_greeter_settings/OptionEntry.py:249 |
885 | 843 | msgctxt "option|StringPathEntry" |
886 | 844 | msgid "Select path" |