Merge lp:~hmollercl/software-properties/software-properties into lp:software-properties
- software-properties
- Merge into main
Status: | Merged |
---|---|
Merged at revision: | 1066 |
Proposed branch: | lp:~hmollercl/software-properties/software-properties |
Merge into: | lp:software-properties |
Diff against target: |
927 lines (+712/-32) 3 files modified
data/designer/main.ui (+225/-23) software-properties-qt (+6/-1) softwareproperties/qt/SoftwarePropertiesQt.py (+481/-8) |
To merge this branch: | bzr merge lp:~hmollercl/software-properties/software-properties |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
ԜаӀtеr Ⅼарсһуnѕkі | Pending | ||
Simon Quigley | Pending | ||
Review via email: mp+361331@code.launchpad.net |
Commit message
Added "additional driver" tab for the Qt version
Description of the change
Added "additional driver" tab for the qt version
To maintain same numbers as gtk version it will be tab 4.
Also added --open-tab commandline option so you can open directly in one tab (same as gtk)
Added lxqt-sudo mention (along with pkexec) when not run with root privileges.
Migrate some GridLayout to BoxLayout in Qt version so windows resizing still makes things look good.
- 1059. By Sebastien Bacher
-
[ Carlo Vanini ]
Fix removal of signing keys in the Authentication tab always failing.
(lp: #1656100) - 1060. By Sebastien Bacher
-
releasing package software-properties version 0.96.30
- 1061. By Sebastien Bacher
-
Remove the migration script, it was online needed until bionic
- 1062. By Andrea Azzarone
-
[ Andrea Azzarone ]
* data/gtkbuilder/dialog- auth.ui: Update design of the authentication
dialog.
* softwareproperties/gtk/ DialogAuth. py: Implement new design of the
authentication dialog. - 1063. By Sebastien Bacher
-
releasing package software-properties version 0.96.31
- 1064. By Sebastien Bacher
-
* softwarepropert
ies/gtk/ DialogAuth. py:
- Log call_ensure_credentials_ finish errors, fixes the build failing
due to pyflakes warning about an unused variable - 1065. By Sebastien Bacher
-
releasing package software-properties version 0.96.32
- 1066. By Simon Quigley
-
Merge lp:~hmollercl/software-properties/software-properties into lp:software-properties and add changelog entry.
Hans P. Möller (hmollercl) wrote : | # |
Preview Diff
1 | === modified file 'data/designer/main.ui' | |||
2 | --- data/designer/main.ui 2018-07-14 10:32:29 +0000 | |||
3 | +++ data/designer/main.ui 2018-12-29 13:41:58 +0000 | |||
4 | @@ -6,21 +6,15 @@ | |||
5 | 6 | <rect> | 6 | <rect> |
6 | 7 | <x>0</x> | 7 | <x>0</x> |
7 | 8 | <y>0</y> | 8 | <y>0</y> |
9 | 9 | <width>605</width> | 9 | <width>706</width> |
10 | 10 | <height>408</height> | 10 | <height>408</height> |
11 | 11 | </rect> | 11 | </rect> |
12 | 12 | </property> | 12 | </property> |
13 | 13 | <property name="windowTitle"> | 13 | <property name="windowTitle"> |
14 | 14 | <string>Software Sources</string> | 14 | <string>Software Sources</string> |
15 | 15 | </property> | 15 | </property> |
24 | 16 | <layout class="QGridLayout"> | 16 | <layout class="QVBoxLayout" name="verticalLayout"> |
25 | 17 | <property name="margin"> | 17 | <item> |
18 | 18 | <number>9</number> | ||
19 | 19 | </property> | ||
20 | 20 | <property name="spacing"> | ||
21 | 21 | <number>6</number> | ||
22 | 22 | </property> | ||
23 | 23 | <item row="0" column="0"> | ||
26 | 24 | <widget class="QTabWidget" name="tabWidget"> | 18 | <widget class="QTabWidget" name="tabWidget"> |
27 | 25 | <property name="currentIndex"> | 19 | <property name="currentIndex"> |
28 | 26 | <number>0</number> | 20 | <number>0</number> |
29 | @@ -30,7 +24,16 @@ | |||
30 | 30 | <string>Software & Updates</string> | 24 | <string>Software & Updates</string> |
31 | 31 | </attribute> | 25 | </attribute> |
32 | 32 | <layout class="QGridLayout"> | 26 | <layout class="QGridLayout"> |
34 | 33 | <property name="margin"> | 27 | <property name="leftMargin"> |
35 | 28 | <number>9</number> | ||
36 | 29 | </property> | ||
37 | 30 | <property name="topMargin"> | ||
38 | 31 | <number>9</number> | ||
39 | 32 | </property> | ||
40 | 33 | <property name="rightMargin"> | ||
41 | 34 | <number>9</number> | ||
42 | 35 | </property> | ||
43 | 36 | <property name="bottomMargin"> | ||
44 | 34 | <number>9</number> | 37 | <number>9</number> |
45 | 35 | </property> | 38 | </property> |
46 | 36 | <property name="spacing"> | 39 | <property name="spacing"> |
47 | @@ -42,7 +45,16 @@ | |||
48 | 42 | <string><b>Downloadable from the Internet</b></string> | 45 | <string><b>Downloadable from the Internet</b></string> |
49 | 43 | </property> | 46 | </property> |
50 | 44 | <layout class="QGridLayout"> | 47 | <layout class="QGridLayout"> |
52 | 45 | <property name="margin"> | 48 | <property name="leftMargin"> |
53 | 49 | <number>9</number> | ||
54 | 50 | </property> | ||
55 | 51 | <property name="topMargin"> | ||
56 | 52 | <number>9</number> | ||
57 | 53 | </property> | ||
58 | 54 | <property name="rightMargin"> | ||
59 | 55 | <number>9</number> | ||
60 | 56 | </property> | ||
61 | 57 | <property name="bottomMargin"> | ||
62 | 46 | <number>9</number> | 58 | <number>9</number> |
63 | 47 | </property> | 59 | </property> |
64 | 48 | <property name="spacing"> | 60 | <property name="spacing"> |
65 | @@ -57,7 +69,16 @@ | |||
66 | 57 | <enum>QFrame::Raised</enum> | 69 | <enum>QFrame::Raised</enum> |
67 | 58 | </property> | 70 | </property> |
68 | 59 | <layout class="QGridLayout"> | 71 | <layout class="QGridLayout"> |
70 | 60 | <property name="margin"> | 72 | <property name="leftMargin"> |
71 | 73 | <number>0</number> | ||
72 | 74 | </property> | ||
73 | 75 | <property name="topMargin"> | ||
74 | 76 | <number>0</number> | ||
75 | 77 | </property> | ||
76 | 78 | <property name="rightMargin"> | ||
77 | 79 | <number>0</number> | ||
78 | 80 | </property> | ||
79 | 81 | <property name="bottomMargin"> | ||
80 | 61 | <number>0</number> | 82 | <number>0</number> |
81 | 62 | </property> | 83 | </property> |
82 | 63 | <property name="spacing"> | 84 | <property name="spacing"> |
83 | @@ -68,7 +89,16 @@ | |||
84 | 68 | <property name="spacing"> | 89 | <property name="spacing"> |
85 | 69 | <number>6</number> | 90 | <number>6</number> |
86 | 70 | </property> | 91 | </property> |
88 | 71 | <property name="margin"> | 92 | <property name="leftMargin"> |
89 | 93 | <number>0</number> | ||
90 | 94 | </property> | ||
91 | 95 | <property name="topMargin"> | ||
92 | 96 | <number>0</number> | ||
93 | 97 | </property> | ||
94 | 98 | <property name="rightMargin"> | ||
95 | 99 | <number>0</number> | ||
96 | 100 | </property> | ||
97 | 101 | <property name="bottomMargin"> | ||
98 | 72 | <number>0</number> | 102 | <number>0</number> |
99 | 73 | </property> | 103 | </property> |
100 | 74 | </layout> | 104 | </layout> |
101 | @@ -105,7 +135,16 @@ | |||
102 | 105 | <string>Installable from CD-ROM/DVD</string> | 135 | <string>Installable from CD-ROM/DVD</string> |
103 | 106 | </property> | 136 | </property> |
104 | 107 | <layout class="QGridLayout"> | 137 | <layout class="QGridLayout"> |
106 | 108 | <property name="margin"> | 138 | <property name="leftMargin"> |
107 | 139 | <number>9</number> | ||
108 | 140 | </property> | ||
109 | 141 | <property name="topMargin"> | ||
110 | 142 | <number>9</number> | ||
111 | 143 | </property> | ||
112 | 144 | <property name="rightMargin"> | ||
113 | 145 | <number>9</number> | ||
114 | 146 | </property> | ||
115 | 147 | <property name="bottomMargin"> | ||
116 | 109 | <number>9</number> | 148 | <number>9</number> |
117 | 110 | </property> | 149 | </property> |
118 | 111 | <property name="spacing"> | 150 | <property name="spacing"> |
119 | @@ -168,7 +207,16 @@ | |||
120 | 168 | <string>Other Software</string> | 207 | <string>Other Software</string> |
121 | 169 | </attribute> | 208 | </attribute> |
122 | 170 | <layout class="QGridLayout"> | 209 | <layout class="QGridLayout"> |
124 | 171 | <property name="margin"> | 210 | <property name="leftMargin"> |
125 | 211 | <number>9</number> | ||
126 | 212 | </property> | ||
127 | 213 | <property name="topMargin"> | ||
128 | 214 | <number>9</number> | ||
129 | 215 | </property> | ||
130 | 216 | <property name="rightMargin"> | ||
131 | 217 | <number>9</number> | ||
132 | 218 | </property> | ||
133 | 219 | <property name="bottomMargin"> | ||
134 | 172 | <number>9</number> | 220 | <number>9</number> |
135 | 173 | </property> | 221 | </property> |
136 | 174 | <property name="spacing"> | 222 | <property name="spacing"> |
137 | @@ -233,7 +281,16 @@ | |||
138 | 233 | <string>Updates</string> | 281 | <string>Updates</string> |
139 | 234 | </attribute> | 282 | </attribute> |
140 | 235 | <layout class="QGridLayout"> | 283 | <layout class="QGridLayout"> |
142 | 236 | <property name="margin"> | 284 | <property name="leftMargin"> |
143 | 285 | <number>9</number> | ||
144 | 286 | </property> | ||
145 | 287 | <property name="topMargin"> | ||
146 | 288 | <number>9</number> | ||
147 | 289 | </property> | ||
148 | 290 | <property name="rightMargin"> | ||
149 | 291 | <number>9</number> | ||
150 | 292 | </property> | ||
151 | 293 | <property name="bottomMargin"> | ||
152 | 237 | <number>9</number> | 294 | <number>9</number> |
153 | 238 | </property> | 295 | </property> |
154 | 239 | <property name="spacing"> | 296 | <property name="spacing"> |
155 | @@ -245,7 +302,16 @@ | |||
156 | 245 | <string><b>Ubuntu updates</b></string> | 302 | <string><b>Ubuntu updates</b></string> |
157 | 246 | </property> | 303 | </property> |
158 | 247 | <layout class="QGridLayout" name="gridLayout_2"> | 304 | <layout class="QGridLayout" name="gridLayout_2"> |
160 | 248 | <property name="margin"> | 305 | <property name="leftMargin"> |
161 | 306 | <number>9</number> | ||
162 | 307 | </property> | ||
163 | 308 | <property name="topMargin"> | ||
164 | 309 | <number>9</number> | ||
165 | 310 | </property> | ||
166 | 311 | <property name="rightMargin"> | ||
167 | 312 | <number>9</number> | ||
168 | 313 | </property> | ||
169 | 314 | <property name="bottomMargin"> | ||
170 | 249 | <number>9</number> | 315 | <number>9</number> |
171 | 250 | </property> | 316 | </property> |
172 | 251 | <property name="spacing"> | 317 | <property name="spacing"> |
173 | @@ -256,7 +322,16 @@ | |||
174 | 256 | <property name="spacing"> | 322 | <property name="spacing"> |
175 | 257 | <number>6</number> | 323 | <number>6</number> |
176 | 258 | </property> | 324 | </property> |
178 | 259 | <property name="margin"> | 325 | <property name="leftMargin"> |
179 | 326 | <number>0</number> | ||
180 | 327 | </property> | ||
181 | 328 | <property name="topMargin"> | ||
182 | 329 | <number>0</number> | ||
183 | 330 | </property> | ||
184 | 331 | <property name="rightMargin"> | ||
185 | 332 | <number>0</number> | ||
186 | 333 | </property> | ||
187 | 334 | <property name="bottomMargin"> | ||
188 | 260 | <number>0</number> | 335 | <number>0</number> |
189 | 261 | </property> | 336 | </property> |
190 | 262 | <item> | 337 | <item> |
191 | @@ -268,7 +343,16 @@ | |||
192 | 268 | <enum>QFrame::Raised</enum> | 343 | <enum>QFrame::Raised</enum> |
193 | 269 | </property> | 344 | </property> |
194 | 270 | <layout class="QGridLayout"> | 345 | <layout class="QGridLayout"> |
196 | 271 | <property name="margin"> | 346 | <property name="leftMargin"> |
197 | 347 | <number>0</number> | ||
198 | 348 | </property> | ||
199 | 349 | <property name="topMargin"> | ||
200 | 350 | <number>0</number> | ||
201 | 351 | </property> | ||
202 | 352 | <property name="rightMargin"> | ||
203 | 353 | <number>0</number> | ||
204 | 354 | </property> | ||
205 | 355 | <property name="bottomMargin"> | ||
206 | 272 | <number>0</number> | 356 | <number>0</number> |
207 | 273 | </property> | 357 | </property> |
208 | 274 | <property name="spacing"> | 358 | <property name="spacing"> |
209 | @@ -288,7 +372,16 @@ | |||
210 | 288 | <string><b>Automatic updates</b></string> | 372 | <string><b>Automatic updates</b></string> |
211 | 289 | </property> | 373 | </property> |
212 | 290 | <layout class="QGridLayout" name="gridLayout"> | 374 | <layout class="QGridLayout" name="gridLayout"> |
214 | 291 | <property name="margin"> | 375 | <property name="leftMargin"> |
215 | 376 | <number>9</number> | ||
216 | 377 | </property> | ||
217 | 378 | <property name="topMargin"> | ||
218 | 379 | <number>9</number> | ||
219 | 380 | </property> | ||
220 | 381 | <property name="rightMargin"> | ||
221 | 382 | <number>9</number> | ||
222 | 383 | </property> | ||
223 | 384 | <property name="bottomMargin"> | ||
224 | 292 | <number>9</number> | 385 | <number>9</number> |
225 | 293 | </property> | 386 | </property> |
226 | 294 | <property name="spacing"> | 387 | <property name="spacing"> |
227 | @@ -370,7 +463,16 @@ | |||
228 | 370 | <string>Authentication</string> | 463 | <string>Authentication</string> |
229 | 371 | </attribute> | 464 | </attribute> |
230 | 372 | <layout class="QGridLayout"> | 465 | <layout class="QGridLayout"> |
232 | 373 | <property name="margin"> | 466 | <property name="leftMargin"> |
233 | 467 | <number>9</number> | ||
234 | 468 | </property> | ||
235 | 469 | <property name="topMargin"> | ||
236 | 470 | <number>9</number> | ||
237 | 471 | </property> | ||
238 | 472 | <property name="rightMargin"> | ||
239 | 473 | <number>9</number> | ||
240 | 474 | </property> | ||
241 | 475 | <property name="bottomMargin"> | ||
242 | 374 | <number>9</number> | 476 | <number>9</number> |
243 | 375 | </property> | 477 | </property> |
244 | 376 | <property name="spacing"> | 478 | <property name="spacing"> |
245 | @@ -437,12 +539,112 @@ | |||
246 | 437 | </item> | 539 | </item> |
247 | 438 | </layout> | 540 | </layout> |
248 | 439 | </widget> | 541 | </widget> |
249 | 542 | <widget class="QWidget" name="vbox_drivers"> | ||
250 | 543 | <attribute name="title"> | ||
251 | 544 | <string>Additional Drivers</string> | ||
252 | 545 | </attribute> | ||
253 | 546 | <layout class="QVBoxLayout" name="verticalLayout_2"> | ||
254 | 547 | <property name="spacing"> | ||
255 | 548 | <number>0</number> | ||
256 | 549 | </property> | ||
257 | 550 | <item> | ||
258 | 551 | <widget class="QScrollArea" name="scrollArea"> | ||
259 | 552 | <property name="widgetResizable"> | ||
260 | 553 | <bool>true</bool> | ||
261 | 554 | </property> | ||
262 | 555 | <widget class="QWidget" name="scrollAreaWidgetContents"> | ||
263 | 556 | <property name="geometry"> | ||
264 | 557 | <rect> | ||
265 | 558 | <x>0</x> | ||
266 | 559 | <y>0</y> | ||
267 | 560 | <width>670</width> | ||
268 | 561 | <height>244</height> | ||
269 | 562 | </rect> | ||
270 | 563 | </property> | ||
271 | 564 | <layout class="QVBoxLayout" name="verticalLayout_3"> | ||
272 | 565 | <property name="spacing"> | ||
273 | 566 | <number>0</number> | ||
274 | 567 | </property> | ||
275 | 568 | <property name="leftMargin"> | ||
276 | 569 | <number>0</number> | ||
277 | 570 | </property> | ||
278 | 571 | <property name="topMargin"> | ||
279 | 572 | <number>0</number> | ||
280 | 573 | </property> | ||
281 | 574 | <property name="rightMargin"> | ||
282 | 575 | <number>0</number> | ||
283 | 576 | </property> | ||
284 | 577 | <property name="bottomMargin"> | ||
285 | 578 | <number>0</number> | ||
286 | 579 | </property> | ||
287 | 580 | <item> | ||
288 | 581 | <layout class="QVBoxLayout" name="box_driver_detail"/> | ||
289 | 582 | </item> | ||
290 | 583 | </layout> | ||
291 | 584 | </widget> | ||
292 | 585 | </widget> | ||
293 | 586 | </item> | ||
294 | 587 | <item> | ||
295 | 588 | <widget class="QGroupBox" name="groupBox_driver_action"> | ||
296 | 589 | <property name="sizePolicy"> | ||
297 | 590 | <sizepolicy hsizetype="Preferred" vsizetype="Preferred"> | ||
298 | 591 | <horstretch>0</horstretch> | ||
299 | 592 | <verstretch>0</verstretch> | ||
300 | 593 | </sizepolicy> | ||
301 | 594 | </property> | ||
302 | 595 | <layout class="QHBoxLayout" name="box_driver_action"> | ||
303 | 596 | <property name="spacing"> | ||
304 | 597 | <number>0</number> | ||
305 | 598 | </property> | ||
306 | 599 | <property name="leftMargin"> | ||
307 | 600 | <number>0</number> | ||
308 | 601 | </property> | ||
309 | 602 | <property name="topMargin"> | ||
310 | 603 | <number>0</number> | ||
311 | 604 | </property> | ||
312 | 605 | <property name="rightMargin"> | ||
313 | 606 | <number>0</number> | ||
314 | 607 | </property> | ||
315 | 608 | <property name="bottomMargin"> | ||
316 | 609 | <number>0</number> | ||
317 | 610 | </property> | ||
318 | 611 | <item> | ||
319 | 612 | <widget class="QLabel" name="label_driver_action"> | ||
320 | 613 | <property name="text"> | ||
321 | 614 | <string>No propietary drivers are in use.</string> | ||
322 | 615 | </property> | ||
323 | 616 | </widget> | ||
324 | 617 | </item> | ||
325 | 618 | </layout> | ||
326 | 619 | </widget> | ||
327 | 620 | </item> | ||
328 | 621 | <item> | ||
329 | 622 | <widget class="QLabel" name="label_disc"> | ||
330 | 623 | <property name="text"> | ||
331 | 624 | <string><small>A proprietary driver has private code that Ubuntu developers can't review or improve. Security and other updates are dependent on the driver vendor.</small></string> | ||
332 | 625 | </property> | ||
333 | 626 | <property name="wordWrap"> | ||
334 | 627 | <bool>true</bool> | ||
335 | 628 | </property> | ||
336 | 629 | </widget> | ||
337 | 630 | </item> | ||
338 | 631 | </layout> | ||
339 | 632 | </widget> | ||
340 | 440 | <widget class="QWidget" name="tab_5"> | 633 | <widget class="QWidget" name="tab_5"> |
341 | 441 | <attribute name="title"> | 634 | <attribute name="title"> |
342 | 442 | <string>Statistics</string> | 635 | <string>Statistics</string> |
343 | 443 | </attribute> | 636 | </attribute> |
344 | 444 | <layout class="QGridLayout"> | 637 | <layout class="QGridLayout"> |
346 | 445 | <property name="margin"> | 638 | <property name="leftMargin"> |
347 | 639 | <number>9</number> | ||
348 | 640 | </property> | ||
349 | 641 | <property name="topMargin"> | ||
350 | 642 | <number>9</number> | ||
351 | 643 | </property> | ||
352 | 644 | <property name="rightMargin"> | ||
353 | 645 | <number>9</number> | ||
354 | 646 | </property> | ||
355 | 647 | <property name="bottomMargin"> | ||
356 | 446 | <number>9</number> | 648 | <number>9</number> |
357 | 447 | </property> | 649 | </property> |
358 | 448 | <property name="spacing"> | 650 | <property name="spacing"> |
359 | @@ -482,7 +684,7 @@ | |||
360 | 482 | </widget> | 684 | </widget> |
361 | 483 | </widget> | 685 | </widget> |
362 | 484 | </item> | 686 | </item> |
364 | 485 | <item row="1" column="0"> | 687 | <item> |
365 | 486 | <widget class="QDialogButtonBox" name="buttonBox"> | 688 | <widget class="QDialogButtonBox" name="buttonBox"> |
366 | 487 | <property name="orientation"> | 689 | <property name="orientation"> |
367 | 488 | <enum>Qt::Horizontal</enum> | 690 | <enum>Qt::Horizontal</enum> |
368 | 489 | 691 | ||
369 | === modified file 'software-properties-qt' | |||
370 | --- software-properties-qt 2018-07-14 10:11:32 +0000 | |||
371 | +++ software-properties-qt 2018-12-29 13:41:58 +0000 | |||
372 | @@ -82,6 +82,10 @@ | |||
373 | 82 | _("Enable the specified component of the distro's repositories"), | 82 | _("Enable the specified component of the distro's repositories"), |
374 | 83 | "name"); | 83 | "name"); |
375 | 84 | parser.addOption(componentOption); | 84 | parser.addOption(componentOption); |
376 | 85 | openTabOption = QCommandLineOption("open-tab", | ||
377 | 86 | _("Open specific tab number on startup"), | ||
378 | 87 | "open_tab"); | ||
379 | 88 | parser.addOption(openTabOption); | ||
380 | 85 | ppaOption = QCommandLineOption("enable-ppa", | 89 | ppaOption = QCommandLineOption("enable-ppa", |
381 | 86 | _("Enable PPA with the given name"), | 90 | _("Enable PPA with the given name"), |
382 | 87 | "name"); | 91 | "name"); |
383 | @@ -100,7 +104,7 @@ | |||
384 | 100 | 104 | ||
385 | 101 | # Check for root permissions | 105 | # Check for root permissions |
386 | 102 | if os.geteuid() != 0: | 106 | if os.geteuid() != 0: |
388 | 103 | text = "Please run this software with administrative rights. To do so, run this program with pkexec." | 107 | text = "Please run this software with administrative rights. To do so, run this program with lxqt-sudo or pkexec." |
389 | 104 | title = "Need administrative powers" | 108 | title = "Need administrative powers" |
390 | 105 | msgbox = QMessageBox.critical(None, title, text) | 109 | msgbox = QMessageBox.critical(None, title, text) |
391 | 106 | sys.exit(1) | 110 | sys.exit(1) |
392 | @@ -119,6 +123,7 @@ | |||
393 | 119 | options.debug = parser.isSet(debugOption) | 123 | options.debug = parser.isSet(debugOption) |
394 | 120 | options.debug = parser.isSet(massiveDebugOption) | 124 | options.debug = parser.isSet(massiveDebugOption) |
395 | 121 | options.no_update = parser.isSet(noUpdateOption) | 125 | options.no_update = parser.isSet(noUpdateOption) |
396 | 126 | options.open_tab = parser.value(openTabOption) | ||
397 | 122 | 127 | ||
398 | 123 | attachWinID = None | 128 | attachWinID = None |
399 | 124 | if parser.isSet(winidOption): | 129 | if parser.isSet(winidOption): |
400 | 125 | 130 | ||
401 | === modified file 'softwareproperties/qt/SoftwarePropertiesQt.py' | |||
402 | --- softwareproperties/qt/SoftwarePropertiesQt.py 2018-07-14 10:45:16 +0000 | |||
403 | +++ softwareproperties/qt/SoftwarePropertiesQt.py 2018-12-29 13:41:58 +0000 | |||
404 | @@ -49,6 +49,28 @@ | |||
405 | 49 | from .DialogMirror import DialogMirror | 49 | from .DialogMirror import DialogMirror |
406 | 50 | from .CdromProgress import CdromProgress | 50 | from .CdromProgress import CdromProgress |
407 | 51 | 51 | ||
408 | 52 | from UbuntuDrivers import detect | ||
409 | 53 | import sys | ||
410 | 54 | import apt | ||
411 | 55 | from functools import partial | ||
412 | 56 | from aptdaemon import client | ||
413 | 57 | from aptdaemon.errors import NotAuthorizedError, TransactionFailed | ||
414 | 58 | import aptsources.distro | ||
415 | 59 | import logging | ||
416 | 60 | |||
417 | 61 | class DetectDriverThread(QThread): | ||
418 | 62 | #WARNING class to run detect_drivers() in separate thread | ||
419 | 63 | #so GUI won't freeze. | ||
420 | 64 | def __init__(self, swprop): | ||
421 | 65 | QThread.__init__(self) | ||
422 | 66 | self.swprop = swprop | ||
423 | 67 | |||
424 | 68 | def __del__(self): | ||
425 | 69 | self.wait() | ||
426 | 70 | |||
427 | 71 | def run(self): | ||
428 | 72 | self.swprop.detect_drivers() | ||
429 | 73 | |||
430 | 52 | class SoftwarePropertiesQtUI(QWidget): | 74 | class SoftwarePropertiesQtUI(QWidget): |
431 | 53 | def __init__(self, datadir): | 75 | def __init__(self, datadir): |
432 | 54 | QWidget.__init__(self) | 76 | QWidget.__init__(self) |
433 | @@ -101,6 +123,12 @@ | |||
434 | 101 | self.init_isv_sources() | 123 | self.init_isv_sources() |
435 | 102 | self.show_isv_sources() | 124 | self.show_isv_sources() |
436 | 103 | self.show_cdrom_sources() | 125 | self.show_cdrom_sources() |
437 | 126 | # Setup and show the Additonal Drivers tab | ||
438 | 127 | self.init_drivers() | ||
439 | 128 | |||
440 | 129 | # Connect to switch-page before setting initial tab. Otherwise the | ||
441 | 130 | # first switch goes unnoticed. | ||
442 | 131 | self.userinterface.tabWidget.currentChanged.connect(self.tab_switched) | ||
443 | 104 | 132 | ||
444 | 105 | self.userinterface.checkbutton_source_code.clicked.connect(self.on_checkbutton_source_code_toggled) | 133 | self.userinterface.checkbutton_source_code.clicked.connect(self.on_checkbutton_source_code_toggled) |
445 | 106 | self.userinterface.button_auth_restore.clicked.connect(self.on_restore_clicked) | 134 | self.userinterface.button_auth_restore.clicked.connect(self.on_restore_clicked) |
446 | @@ -117,15 +145,36 @@ | |||
447 | 117 | self.userinterface.treeview_sources.itemClicked.connect(self.on_treeview_sources_cursor_changed) | 145 | self.userinterface.treeview_sources.itemClicked.connect(self.on_treeview_sources_cursor_changed) |
448 | 118 | self.userinterface.treeview_cdroms.itemChanged.connect(self.on_cdrom_source_toggled) | 146 | self.userinterface.treeview_cdroms.itemChanged.connect(self.on_cdrom_source_toggled) |
449 | 119 | self.userinterface.treeview2.itemClicked.connect(self.on_treeview_keys_cursor_changed) | 147 | self.userinterface.treeview2.itemClicked.connect(self.on_treeview_keys_cursor_changed) |
455 | 120 | button_close = self.userinterface.buttonBox.button(QDialogButtonBox.Close) | 148 | |
456 | 121 | button_close.setIcon(QIcon.fromTheme("dialog-close")) | 149 | self.button_close = self.userinterface.buttonBox.button(QDialogButtonBox.Close) |
457 | 122 | button_revert = self.userinterface.buttonBox.button(QDialogButtonBox.Reset) | 150 | self.button_close.setIcon(QIcon.fromTheme("dialog-close")) |
458 | 123 | button_revert.setIcon(QIcon.fromTheme("edit-undo")) | 151 | self.button_revert = self.userinterface.buttonBox.button(QDialogButtonBox.Reset) |
459 | 124 | button_revert.clicked.connect(self.on_button_revert_clicked) | 152 | self.button_revert.setIcon(QIcon.fromTheme("edit-undo")) |
460 | 153 | self.button_revert.clicked.connect(self.on_button_revert_clicked) | ||
461 | 125 | 154 | ||
462 | 126 | self.init_distro() | 155 | self.init_distro() |
463 | 127 | self.show_distro() | 156 | self.show_distro() |
465 | 128 | 157 | ||
466 | 158 | self.apt_client = client.AptClient() | ||
467 | 159 | |||
468 | 160 | if options and options.open_tab: | ||
469 | 161 | self.userinterface.tabWidget.setCurrentIndex(int(options.open_tab)) | ||
470 | 162 | |||
471 | 163 | def tab_switched(self): | ||
472 | 164 | # On the additional drivers page, don't show the backend revert button. | ||
473 | 165 | if self.userinterface.tabWidget.currentIndex() == 4: #vbox_drivers is 4 | ||
474 | 166 | self.button_revert.setVisible(False) | ||
475 | 167 | if not self.detect_called: | ||
476 | 168 | #WARNING detect_drivers() runs in separate thread | ||
477 | 169 | #in DetectDriverThread class so GUI won't freeze | ||
478 | 170 | #after finish show_drivers() has to run in main thread because it updates the GUI | ||
479 | 171 | self.detect_driver_thread = DetectDriverThread(self) | ||
480 | 172 | self.detect_driver_thread.finished.connect(self.show_drivers) | ||
481 | 173 | self.detect_driver_thread.start() | ||
482 | 174 | |||
483 | 175 | else: | ||
484 | 176 | self.button_revert.setVisible(True) | ||
485 | 177 | |||
486 | 129 | def init_popcon(self): | 178 | def init_popcon(self): |
487 | 130 | """ If popcon is enabled show the statistics tab and an explanation | 179 | """ If popcon is enabled show the statistics tab and an explanation |
488 | 131 | corresponding to the used distro """ | 180 | corresponding to the used distro """ |
489 | @@ -136,8 +185,8 @@ | |||
490 | 136 | self.userinterface.label_popcon_desc.setText(text) | 185 | self.userinterface.label_popcon_desc.setText(text) |
491 | 137 | self.userinterface.checkbutton_popcon.setChecked(is_helpful) | 186 | self.userinterface.checkbutton_popcon.setChecked(is_helpful) |
492 | 138 | else: | 187 | else: |
495 | 139 | self.userinterface.tabWidget.removeTab(4) | 188 | self.userinterface.tabWidget.removeTab(5) |
496 | 140 | 189 | ||
497 | 141 | def init_server_chooser(self): | 190 | def init_server_chooser(self): |
498 | 142 | """ Set up the widgets that allow to choose an alternate download site """ | 191 | """ Set up the widgets that allow to choose an alternate download site """ |
499 | 143 | # nothing to do here, set up signal in show_distro() | 192 | # nothing to do here, set up signal in show_distro() |
500 | @@ -747,3 +796,427 @@ | |||
501 | 747 | 796 | ||
502 | 748 | def run(self): | 797 | def run(self): |
503 | 749 | kapp.exec_() | 798 | kapp.exec_() |
504 | 799 | |||
505 | 800 | def on_driver_changes_progress(self, transaction, progress): | ||
506 | 801 | self.button_driver_revert.setVisible(False) | ||
507 | 802 | self.button_driver_apply.setVisible(False) | ||
508 | 803 | self.button_driver_restart.setVisible(False) | ||
509 | 804 | self.button_driver_cancel.setVisible(True) | ||
510 | 805 | self.progress_bar.setVisible(True) | ||
511 | 806 | |||
512 | 807 | self.userinterface.label_driver_action.setText("Applying changes...") | ||
513 | 808 | self.progress_bar.setValue(progress) | ||
514 | 809 | |||
515 | 810 | def on_driver_changes_finish(self, transaction, exit_state): | ||
516 | 811 | self.progress_bar.setVisible(False) | ||
517 | 812 | self.clear_changes() | ||
518 | 813 | self.apt_cache = apt.Cache() | ||
519 | 814 | self.set_driver_action_status() | ||
520 | 815 | self.update_label_and_icons_from_status() | ||
521 | 816 | self.button_driver_revert.setVisible(True) | ||
522 | 817 | self.button_driver_apply.setVisible(True) | ||
523 | 818 | self.button_driver_cancel.setVisible(False) | ||
524 | 819 | #self.scrolled_window_drivers.set_sensitive(True) | ||
525 | 820 | |||
526 | 821 | def on_driver_changes_error(self, transaction, error_code, error_details): | ||
527 | 822 | self.on_driver_changes_revert() | ||
528 | 823 | self.set_driver_action_status() | ||
529 | 824 | self.update_label_and_icons_from_status() | ||
530 | 825 | self.button_driver_revert.setVisible(True) | ||
531 | 826 | self.button_driver_apply.setVisible(True) | ||
532 | 827 | self.button_driver_cancel.setVisible(False) | ||
533 | 828 | #self.scrolled_window_drivers.set_sensitive(True) | ||
534 | 829 | |||
535 | 830 | def on_driver_changes_cancellable_changed(self, transaction, cancellable): | ||
536 | 831 | self.button_driver_cancel.setEnabled(cancellable) | ||
537 | 832 | |||
538 | 833 | def on_driver_changes_apply(self, button): | ||
539 | 834 | button = self.userinterface.sender() | ||
540 | 835 | installs = [] | ||
541 | 836 | removals = [] | ||
542 | 837 | |||
543 | 838 | for pkg in self.driver_changes: | ||
544 | 839 | if pkg.is_installed: | ||
545 | 840 | removals.append(pkg.shortname) | ||
546 | 841 | # The main NVIDIA package is only a metapackage. | ||
547 | 842 | # We need to collect its dependencies, so that | ||
548 | 843 | # we can uninstall the driver properly. | ||
549 | 844 | if 'nvidia' in pkg.shortname: | ||
550 | 845 | for dep in get_dependencies(self.apt_cache, pkg.shortname, 'nvidia'): | ||
551 | 846 | dep_pkg = self.apt_cache[dep] | ||
552 | 847 | if dep_pkg.is_installed: | ||
553 | 848 | removals.append(dep_pkg.shortname) | ||
554 | 849 | else: | ||
555 | 850 | installs.append(pkg.shortname) | ||
556 | 851 | |||
557 | 852 | try: | ||
558 | 853 | self.transaction = self.apt_client.commit_packages(install=installs, remove=removals, reinstall=[], purge=[], upgrade=[], downgrade=[]) | ||
559 | 854 | self.transaction.connect('progress-changed', self.on_driver_changes_progress) | ||
560 | 855 | self.transaction.connect('cancellable-changed', self.on_driver_changes_cancellable_changed) | ||
561 | 856 | self.transaction.connect('finished', self.on_driver_changes_finish) | ||
562 | 857 | self.transaction.connect('error', self.on_driver_changes_error) | ||
563 | 858 | self.transaction.set_debconf_frontend("gnome") | ||
564 | 859 | self.transaction.run() | ||
565 | 860 | self.button_driver_revert.setEnabled(False) | ||
566 | 861 | self.button_driver_apply.setEnabled(False) | ||
567 | 862 | #self.scrolled_window_drivers.set_sensitive(False) | ||
568 | 863 | except (NotAuthorizedError, TransactionFailed) as e: | ||
569 | 864 | print("Warning: install transaction not completed successfully: {}".format(e)) | ||
570 | 865 | |||
571 | 866 | def on_driver_changes_revert(self, button_revert=None): | ||
572 | 867 | # HACK: set all the "Do not use" first; then go through the list of the | ||
573 | 868 | # actually selected drivers. | ||
574 | 869 | for button in self.no_drv: | ||
575 | 870 | button.setChecked(True) | ||
576 | 871 | |||
577 | 872 | for alias in self.orig_selection: | ||
578 | 873 | button = self.orig_selection[alias] | ||
579 | 874 | button.setChecked(True) | ||
580 | 875 | |||
581 | 876 | self.clear_changes() | ||
582 | 877 | |||
583 | 878 | self.button_driver_revert.setEnabled(False) | ||
584 | 879 | self.button_driver_apply.setEnabled(False) | ||
585 | 880 | |||
586 | 881 | def on_driver_changes_cancel(self, button_cancel): | ||
587 | 882 | self.transaction.cancel() | ||
588 | 883 | self.clear_changes() | ||
589 | 884 | |||
590 | 885 | def on_driver_restart_clicked(self, button_restart): | ||
591 | 886 | if 'XDG_CURRENT_DESKTOP' in os.environ: | ||
592 | 887 | desktop = os.environ['XDG_CURRENT_DESKTOP'] | ||
593 | 888 | else: | ||
594 | 889 | desktop = 'Unknown' | ||
595 | 890 | |||
596 | 891 | if (desktop == 'ubuntu:GNOME' and os.path.exists('/usr/bin/gnome-session-quit')): | ||
597 | 892 | # argument presents a dialog to cancel reboot | ||
598 | 893 | subprocess.call(['gnome-session-quit', '--reboot']) | ||
599 | 894 | elif (desktop == 'XFCE' and | ||
600 | 895 | os.path.exists('/usr/bin/xfce4-session-logout')): | ||
601 | 896 | subprocess.call(['xfce4-session-logout']) | ||
602 | 897 | elif (desktop == 'LXDE' and os.path.exists('/usr/bin/lubuntu-logout')): | ||
603 | 898 | subprocess.call(['lubuntu-logout']) | ||
604 | 899 | elif (desktop == 'LXQt' and os.path.exists('/usr/bin/lxqt-leave')): | ||
605 | 900 | subprocess.call(['lxqt-leave']) | ||
606 | 901 | |||
607 | 902 | def clear_changes(self): | ||
608 | 903 | self.orig_selection = {} | ||
609 | 904 | self.driver_changes = [] | ||
610 | 905 | |||
611 | 906 | def init_drivers(self): | ||
612 | 907 | """Additional Drivers tab""" | ||
613 | 908 | self.button_driver_revert = QPushButton("Revert") | ||
614 | 909 | self.button_driver_apply = QPushButton("Apply Changes") | ||
615 | 910 | self.button_driver_cancel = QPushButton("Cancel") | ||
616 | 911 | self.button_driver_restart = QPushButton("Restart...") | ||
617 | 912 | |||
618 | 913 | self.button_driver_revert.clicked.connect(self.on_driver_changes_revert) | ||
619 | 914 | self.button_driver_apply.clicked.connect(self.on_driver_changes_apply) | ||
620 | 915 | self.button_driver_cancel.clicked.connect(self.on_driver_changes_cancel) | ||
621 | 916 | self.button_driver_restart.clicked.connect(self.on_driver_restart_clicked) | ||
622 | 917 | |||
623 | 918 | self.button_driver_revert.setEnabled(False) | ||
624 | 919 | self.button_driver_revert.setVisible(True) | ||
625 | 920 | self.button_driver_apply.setEnabled(False) | ||
626 | 921 | self.button_driver_apply.setVisible(True) | ||
627 | 922 | self.button_driver_cancel.setVisible(False) | ||
628 | 923 | self.button_driver_restart.setVisible(False) | ||
629 | 924 | |||
630 | 925 | #self.userinterface.box_driver_action.addWidget(self.userinterface.label_driver_action) | ||
631 | 926 | self.userinterface.box_driver_action.addStretch() | ||
632 | 927 | self.userinterface.box_driver_action.addWidget(self.button_driver_apply) | ||
633 | 928 | self.userinterface.box_driver_action.addWidget(self.button_driver_revert) | ||
634 | 929 | self.userinterface.box_driver_action.addWidget(self.button_driver_restart) | ||
635 | 930 | self.userinterface.box_driver_action.addWidget(self.button_driver_cancel) | ||
636 | 931 | |||
637 | 932 | self.label_driver_detail = QLabel("Searching for available drivers...") | ||
638 | 933 | self.label_driver_detail.setAlignment(Qt.AlignCenter) | ||
639 | 934 | self.userinterface.box_driver_detail.addWidget(self.label_driver_detail) | ||
640 | 935 | |||
641 | 936 | self.progress_bar = QProgressBar() | ||
642 | 937 | |||
643 | 938 | self.userinterface.box_driver_action.addWidget(self.progress_bar) | ||
644 | 939 | self.progress_bar.setVisible(False) | ||
645 | 940 | |||
646 | 941 | self.devices = {} | ||
647 | 942 | self.detect_called = False | ||
648 | 943 | self.driver_changes = [] | ||
649 | 944 | self.orig_selection = {} | ||
650 | 945 | # HACK: the case where the selection is actually "Do not use"; is a little | ||
651 | 946 | # tricky to implement because you can't check for whether a package is | ||
652 | 947 | # installed or any such thing. So let's keep a list of all the | ||
653 | 948 | # "Do not use" radios, set those active first, then iterate through | ||
654 | 949 | # orig_selection when doing a Reset. | ||
655 | 950 | self.no_drv = [] | ||
656 | 951 | self.nonfree_drivers = 0 | ||
657 | 952 | self.ui_building = False | ||
658 | 953 | |||
659 | 954 | def detect_drivers(self): | ||
660 | 955 | # WARNING: This is run in a separate thread. | ||
661 | 956 | self.detect_called = True | ||
662 | 957 | try: | ||
663 | 958 | self.apt_cache = apt.Cache() | ||
664 | 959 | self.devices = detect.system_device_drivers(self.apt_cache) | ||
665 | 960 | except: | ||
666 | 961 | # Catch all exceptions and feed them to apport. | ||
667 | 962 | #GLib.idle_add(self.label_driver_detail.set_text, _("An error occurred while searching for drivers.")) | ||
668 | 963 | self.label_driver_detail.setText("An error occurred while searching for drivers.") | ||
669 | 964 | # For apport to catch this exception. See | ||
670 | 965 | # http://bugs.python.org/issue1230540 | ||
671 | 966 | sys.excepthook(*sys.exc_info()) | ||
672 | 967 | return | ||
673 | 968 | def on_driver_selection_changed(self, modalias, pkg_name=None): | ||
674 | 969 | button = self.userinterface.sender() | ||
675 | 970 | #print(modalias) | ||
676 | 971 | #print(pkg_name) | ||
677 | 972 | |||
678 | 973 | if self.ui_building: | ||
679 | 974 | return | ||
680 | 975 | |||
681 | 976 | pkg = None | ||
682 | 977 | try: | ||
683 | 978 | if pkg_name: | ||
684 | 979 | pkg = self.apt_cache[pkg_name] | ||
685 | 980 | # If the package depends on dkms | ||
686 | 981 | # we need to install the correct linux metapackage | ||
687 | 982 | # so that users get the latest headers | ||
688 | 983 | if 'dkms' in pkg.candidate.record['Depends']: | ||
689 | 984 | linux_meta = detect.get_linux(self.apt_cache) | ||
690 | 985 | if (linux_meta and linux_meta not in self.driver_changes): | ||
691 | 986 | # Install the linux metapackage | ||
692 | 987 | lmp = self.apt_cache[linux_meta] | ||
693 | 988 | if not lmp.is_installed: | ||
694 | 989 | self.driver_changes.append(lmp) | ||
695 | 990 | except KeyError: | ||
696 | 991 | pass | ||
697 | 992 | |||
698 | 993 | if button.isChecked(): | ||
699 | 994 | if pkg in self.driver_changes: | ||
700 | 995 | self.driver_changes.remove(pkg) | ||
701 | 996 | |||
702 | 997 | if (pkg is not None and modalias in self.orig_selection and button is not self.orig_selection[modalias]): | ||
703 | 998 | self.driver_changes.append(pkg) | ||
704 | 999 | else: | ||
705 | 1000 | if pkg in self.driver_changes: | ||
706 | 1001 | self.driver_changes.remove(pkg) | ||
707 | 1002 | |||
708 | 1003 | # for revert; to re-activate the original radio buttons. | ||
709 | 1004 | if modalias not in self.orig_selection: | ||
710 | 1005 | self.orig_selection[modalias] = button | ||
711 | 1006 | |||
712 | 1007 | if (pkg is not None and pkg not in self.driver_changes and pkg.is_installed): | ||
713 | 1008 | self.driver_changes.append(pkg) | ||
714 | 1009 | |||
715 | 1010 | self.button_driver_revert.setEnabled(bool(self.driver_changes)) | ||
716 | 1011 | self.button_driver_apply.setEnabled(bool(self.driver_changes)) | ||
717 | 1012 | |||
718 | 1013 | def gather_device_data(self, device): | ||
719 | 1014 | '''Get various device data used to build the GUI. | ||
720 | 1015 | |||
721 | 1016 | return a tuple of (overall_status string, icon, drivers dict). | ||
722 | 1017 | the drivers dict is using this form: | ||
723 | 1018 | {"recommended/alternative": {pkg_name: { | ||
724 | 1019 | 'selected': True/False | ||
725 | 1020 | 'description': | ||
726 | 1021 | 'description' | ||
727 | 1022 | 'builtin': True/False | ||
728 | 1023 | } | ||
729 | 1024 | }} | ||
730 | 1025 | "manually_installed": {"manual": {'selected': True, 'description': | ||
731 | 1026 | description_string}} | ||
732 | 1027 | "no_driver": {"no_driver": {'selected': True/False, 'description': | ||
733 | 1028 | description_string}} | ||
734 | 1029 | |||
735 | 1030 | Please note that either manually_installed and no_driver are set to | ||
736 | 1031 | None if not applicable | ||
737 | 1032 | (no_driver isn't present if there are builtins) | ||
738 | 1033 | ''' | ||
739 | 1034 | |||
740 | 1035 | possible_overall_status = { | ||
741 | 1036 | 'recommended': (_("This device is using the recommended driver."), | ||
742 | 1037 | "recommended-driver"), | ||
743 | 1038 | 'alternative': (_("This device is using an alternative driver."), | ||
744 | 1039 | "other-driver"), | ||
745 | 1040 | 'manually_installed': (_("This device is using a manually-installed driver."), "other-driver"), | ||
746 | 1041 | 'no_driver': (_("This device is not working."), "disable-device") | ||
747 | 1042 | } | ||
748 | 1043 | |||
749 | 1044 | returned_drivers = {'recommended': {}, 'alternative': {}, | ||
750 | 1045 | 'manually_installed': {}, 'no_driver': {}} | ||
751 | 1046 | have_builtin = False | ||
752 | 1047 | one_selected = False | ||
753 | 1048 | try: | ||
754 | 1049 | if device['manual_install']: | ||
755 | 1050 | returned_drivers['manually_installed'] = {True: {'selected': True,'description': _("Continue using a manually installed driver")}} | ||
756 | 1051 | except KeyError: | ||
757 | 1052 | pass | ||
758 | 1053 | |||
759 | 1054 | for pkg_driver_name in device['drivers']: | ||
760 | 1055 | current_driver = device['drivers'][pkg_driver_name] | ||
761 | 1056 | |||
762 | 1057 | # get general status | ||
763 | 1058 | driver_status = 'alternative' | ||
764 | 1059 | try: | ||
765 | 1060 | if current_driver['recommended'] and current_driver['from_distro']: | ||
766 | 1061 | driver_status = 'recommended' | ||
767 | 1062 | except KeyError: | ||
768 | 1063 | pass | ||
769 | 1064 | |||
770 | 1065 | builtin = False | ||
771 | 1066 | try: | ||
772 | 1067 | if current_driver['builtin']: | ||
773 | 1068 | builtin = True | ||
774 | 1069 | have_builtin = True | ||
775 | 1070 | except KeyError: | ||
776 | 1071 | pass | ||
777 | 1072 | |||
778 | 1073 | try: | ||
779 | 1074 | pkg = self.apt_cache[pkg_driver_name] | ||
780 | 1075 | installed = pkg.is_installed | ||
781 | 1076 | if pkg.candidate is not None: | ||
782 | 1077 | description = _("Using {} from {}").format(pkg.candidate.summary, pkg.shortname) | ||
783 | 1078 | else: | ||
784 | 1079 | description = _("Using {}").format(pkg.shortname) | ||
785 | 1080 | except KeyError: | ||
786 | 1081 | print("WARNING: a driver ({}) doesn't have any available package associated: {}".format(pkg_driver_name, current_driver)) | ||
787 | 1082 | continue | ||
788 | 1083 | |||
789 | 1084 | # gather driver description | ||
790 | 1085 | if current_driver['free']: | ||
791 | 1086 | licence = _("open source") | ||
792 | 1087 | else: | ||
793 | 1088 | licence = _("proprietary") | ||
794 | 1089 | |||
795 | 1090 | if driver_status == 'recommended': | ||
796 | 1091 | base_string = _("{base_description} ({licence}, tested)") | ||
797 | 1092 | else: | ||
798 | 1093 | base_string = _("{base_description} ({licence})") | ||
799 | 1094 | description = base_string.format(base_description=description, | ||
800 | 1095 | licence=licence) | ||
801 | 1096 | |||
802 | 1097 | selected = False | ||
803 | 1098 | if not builtin and not returned_drivers['manually_installed']: | ||
804 | 1099 | selected = installed | ||
805 | 1100 | if installed: | ||
806 | 1101 | selected = True | ||
807 | 1102 | one_selected = True | ||
808 | 1103 | |||
809 | 1104 | returned_drivers[driver_status].setdefault(pkg_driver_name, {'selected': selected,'description': description,'builtin': builtin}) | ||
810 | 1105 | |||
811 | 1106 | # adjust making the needed addition | ||
812 | 1107 | if not have_builtin: | ||
813 | 1108 | selected = False | ||
814 | 1109 | if not one_selected: | ||
815 | 1110 | selected = True | ||
816 | 1111 | returned_drivers["no_driver"] = {True: {'selected': selected, 'description': _("Do not use the device")}} | ||
817 | 1112 | else: | ||
818 | 1113 | # we have a builtin and no selection: builtin is the selected one then | ||
819 | 1114 | if not one_selected: | ||
820 | 1115 | for section in ('recommended', 'alternative'): | ||
821 | 1116 | for pkg_name in returned_drivers[section]: | ||
822 | 1117 | if returned_drivers[section][pkg_name]['builtin']: | ||
823 | 1118 | returned_drivers[section][pkg_name]['selected'] = True | ||
824 | 1119 | |||
825 | 1120 | # compute overall status | ||
826 | 1121 | for section in returned_drivers: | ||
827 | 1122 | for keys in returned_drivers[section]: | ||
828 | 1123 | if returned_drivers[section][keys]['selected']: | ||
829 | 1124 | (overall_status, icon) = possible_overall_status[section] | ||
830 | 1125 | |||
831 | 1126 | return (overall_status, icon, returned_drivers) | ||
832 | 1127 | |||
833 | 1128 | def show_drivers(self): | ||
834 | 1129 | if not self.devices: | ||
835 | 1130 | # No drivers found. | ||
836 | 1131 | self.label_driver_detail.setText("No additional drivers available.") | ||
837 | 1132 | return | ||
838 | 1133 | else: | ||
839 | 1134 | self.label_driver_detail.hide() | ||
840 | 1135 | |||
841 | 1136 | self.option_group = {} | ||
842 | 1137 | self.radio_button = {} | ||
843 | 1138 | self.ui_building = True | ||
844 | 1139 | self.dynamic_device_status = {} | ||
845 | 1140 | for device in sorted(self.devices.keys()): | ||
846 | 1141 | (overall_status, icon, drivers) = self.gather_device_data(self.devices[device]) | ||
847 | 1142 | |||
848 | 1143 | driver_status = QLabel() | ||
849 | 1144 | driver_status.setAlignment(Qt.AlignTop) | ||
850 | 1145 | driver_status.setAlignment(Qt.AlignHCenter) | ||
851 | 1146 | pixmap = QIcon.fromTheme(icon).pixmap(QSize(16, 16)) | ||
852 | 1147 | driver_status.setPixmap(pixmap) | ||
853 | 1148 | |||
854 | 1149 | device_box = QHBoxLayout() | ||
855 | 1150 | device_box.addWidget(driver_status) | ||
856 | 1151 | device_detail = QVBoxLayout() | ||
857 | 1152 | device_box.addLayout(device_detail,1)#1 for priority over the icon to stretch | ||
858 | 1153 | |||
859 | 1154 | widget = QLabel("{}: {}".format(self.devices[device].get('vendor', _('Unknown')), self.devices[device].get('model', _('Unknown')))) | ||
860 | 1155 | widget.setAlignment(Qt.AlignLeft) | ||
861 | 1156 | device_detail.addWidget(widget) | ||
862 | 1157 | widget = QLabel("<small>{}</small>".format(overall_status)) | ||
863 | 1158 | widget.setAlignment(Qt.AlignLeft) | ||
864 | 1159 | #widget.set_use_markup(True) | ||
865 | 1160 | device_detail.addWidget(widget) | ||
866 | 1161 | self.dynamic_device_status[device] = (driver_status, widget) | ||
867 | 1162 | |||
868 | 1163 | self.option_group[device] = None | ||
869 | 1164 | # define the order of introspection | ||
870 | 1165 | for section in ('recommended', 'alternative', 'manually_installed', 'no_driver'): | ||
871 | 1166 | for driver in drivers[section]: | ||
872 | 1167 | self.radio_button = QRadioButton(drivers[section][driver]['description']) | ||
873 | 1168 | if self.option_group[device]: | ||
874 | 1169 | self.option_group[device].addButton(self.radio_button) | ||
875 | 1170 | else: | ||
876 | 1171 | self.option_group[device] = QButtonGroup() | ||
877 | 1172 | self.option_group[device].addButton(self.radio_button) | ||
878 | 1173 | |||
879 | 1174 | device_detail.addWidget(self.radio_button) | ||
880 | 1175 | self.radio_button.setChecked(drivers[section][driver]['selected']) | ||
881 | 1176 | |||
882 | 1177 | if section == 'no_driver': | ||
883 | 1178 | self.no_drv.append(self.radio_button) | ||
884 | 1179 | if section in ('manually_install', 'no_driver') or ('builtin' in drivers[section][driver] and drivers[section][driver]['builtin']): | ||
885 | 1180 | self.radio_button.toggled.connect(partial( self.on_driver_selection_changed, device)) | ||
886 | 1181 | else: | ||
887 | 1182 | self.radio_button.toggled.connect(partial( self.on_driver_selection_changed, device, driver)) | ||
888 | 1183 | if drivers['manually_installed'] and section != 'manually_installed': | ||
889 | 1184 | self.radio_button.setEnabled(False) | ||
890 | 1185 | |||
891 | 1186 | self.userinterface.box_driver_detail.addLayout(device_box) | ||
892 | 1187 | |||
893 | 1188 | self.userinterface.box_driver_detail.addStretch() | ||
894 | 1189 | self.ui_building = False | ||
895 | 1190 | #self.userinterface.box_driver_detail.show_all() | ||
896 | 1191 | self.set_driver_action_status() | ||
897 | 1192 | |||
898 | 1193 | def update_label_and_icons_from_status(self): | ||
899 | 1194 | '''Update the current label and icon, computing the new device status''' | ||
900 | 1195 | |||
901 | 1196 | for device in self.devices: | ||
902 | 1197 | (overall_status, icon, drivers) = self.gather_device_data(self.devices[device]) | ||
903 | 1198 | (driver_status, widget) = self.dynamic_device_status[device] | ||
904 | 1199 | |||
905 | 1200 | pixmap = QIcon.fromTheme(icon).pixmap(QSize(16, 16)) | ||
906 | 1201 | driver_status.setPixmap(pixmap) | ||
907 | 1202 | widget.setText("<small>{}</small>".format(overall_status)) | ||
908 | 1203 | |||
909 | 1204 | def set_driver_action_status(self): | ||
910 | 1205 | # Update the label in case we end up having some kind of proprietary driver in use. | ||
911 | 1206 | if (os.path.exists('/var/run/reboot-required')): | ||
912 | 1207 | self.userinterface.label_driver_action.setText("You need to restart the computer to complete the driver changes.") | ||
913 | 1208 | self.button_driver_restart.setVisible(True) | ||
914 | 1209 | return | ||
915 | 1210 | |||
916 | 1211 | self.nonfree_drivers = 0 | ||
917 | 1212 | for device in self.devices: | ||
918 | 1213 | for pkg_name in self.devices[device]['drivers']: | ||
919 | 1214 | pkg = self.apt_cache[pkg_name] | ||
920 | 1215 | if not self.devices[device]['drivers'][pkg_name]['free'] and pkg.is_installed: | ||
921 | 1216 | self.nonfree_drivers = self.nonfree_drivers + 1 | ||
922 | 1217 | |||
923 | 1218 | if self.nonfree_drivers > 0: | ||
924 | 1219 | text = "%s proprietary driver in use." % ( self.nonfree_drivers) | ||
925 | 1220 | self.userinterface.label_driver_action.setText(text) | ||
926 | 1221 | else: | ||
927 | 1222 | self.userinterface.label_driver_action.setText(_("No proprietary drivers are in use.")) |
for testing run software- properties- qt with the --data-dir modifier to use the modified UI. properties- qt --data-dir ./data
lxqt-sudo ./software-