Merge lp:~agateau/ubiquity/split-plugins into lp:ubiquity

Proposed by Aurélien Gâteau
Status: Work in progress
Proposed branch: lp:~agateau/ubiquity/split-plugins
Merge into: lp:ubiquity
Diff against target: 1209 lines (+594/-579)
4 files modified
ubiquity/plugins/base/language.py (+29/-0)
ubiquity/plugins/gtk/language.py (+319/-0)
ubiquity/plugins/kde/language.py (+237/-0)
ubiquity/plugins/ubi-language.py (+9/-579)
To merge this branch: bzr merge lp:~agateau/ubiquity/split-plugins
Reviewer Review Type Date Requested Status
Dimitri John Ledkov Needs Resubmitting
Ubuntu Installer Team Pending
Review via email: mp+173241@code.launchpad.net

Description of the change

Disclaimer: this branch is not ready yet, I am putting it here to start a discussion.

What I dislike in Ubiquity code-base is that files in the ubiquity/plugins/ dir contain code for all frontends. This makes them difficult to work with for a number of reasons:

- files are huge
- searching through a file often hits code I am not interested in
- frontend-specific imports must be done inside def()

I experimented on this and came up with the proposal in this branch, which moves the KDE and GTK frontends of the ubi-language.py plugin to their own files.

The branch introduces these new files inside ubiquity/plugins:
base/
- __init__.py
- language.py
kde/
- __init__.py
- language.py
gtk/
- __init__.py
- language.py

PageBase class is moved to base/language.py. PageGtk goes to gtk/language.py, PageKde goes to kde/language.py. Both PageGtk and PageKde import PageBase since they inherit from it.

To avoid changes outside the plugin itself, ubi-language.py contains functions named PageGtk() and PageKde(). These functions import the frontend module, create an instance of the frontend class and returns it, making them behave the same as the frontend class constructor.

I haven't moved the debconf and non-interactive frontends, but it should be trivial to do so.

If you agree this is a good thing to do, I am happy to split the other plugins.

What do you think?

To post a comment you must log in.
Revision history for this message
Jonathan Riddell (jr) wrote :

I think I'm neutral-to-positive to this idea. It's a slight faff navigating through a file to compere different frontends as I have to do. It's also a slight faff switching between different files but possible easier to compare and you could do interesting things like "grep def gtk/*py; grep def kde/*py" as a simple way of comparing the methods. So yes good with me although don't spend too long on it I'd say.

Revision history for this message
Dimitri John Ledkov (xnox) wrote :

Thinking more about this I'm negative about it, as it will make ordering of plugins slightly more complex, especially for ubuntu flavours that customize ubiquity with additional plugins.

Revision history for this message
Dimitri John Ledkov (xnox) wrote :

The development of ubiquity has moved to git, still hosted on launchpad. If this merge proposal is still relevant, please resubmit it against the git branches found at https://code.launchpad.net/ubiquity

Sorry for any inconvenience caused.

review: Needs Resubmitting

Unmerged revisions

5950. By Aurélien Gâteau

Move language.PageKde and language.PageGtk to their own files

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== added directory 'ubiquity/plugins/base'
2=== added file 'ubiquity/plugins/base/__init__.py'
3=== added file 'ubiquity/plugins/base/language.py'
4--- ubiquity/plugins/base/language.py 1970-01-01 00:00:00 +0000
5+++ ubiquity/plugins/base/language.py 2013-07-05 16:09:26 +0000
6@@ -0,0 +1,29 @@
7+from ubiquity import plugin
8+
9+try:
10+ import lsb_release
11+ _ver = lsb_release.get_distro_information()['RELEASE']
12+except:
13+ _ver = '12.04'
14+
15+class PageBase(plugin.PluginUI):
16+ WGET_URL = 'http://changelogs.ubuntu.com/ubiquity/%s-update-available' % _ver
17+ RELEASE_NOTES_URL_PATH = '/cdrom/.disk/release_notes_url'
18+
19+ def set_language_choices(self, unused_choices, choice_map):
20+ """Called with language choices and a map to localised names."""
21+ self.language_choice_map = dict(choice_map)
22+
23+ def set_language(self, language):
24+ """Set the current selected language."""
25+ pass
26+
27+ def get_language(self):
28+ """Get the current selected language."""
29+ return 'C'
30+
31+ def set_oem_id(self, text):
32+ pass
33+
34+ def get_oem_id(self):
35+ return ''
36
37=== added directory 'ubiquity/plugins/gtk'
38=== added file 'ubiquity/plugins/gtk/__init__.py'
39=== added file 'ubiquity/plugins/gtk/language.py'
40--- ubiquity/plugins/gtk/language.py 1970-01-01 00:00:00 +0000
41+++ ubiquity/plugins/gtk/language.py 2013-07-05 16:09:26 +0000
42@@ -0,0 +1,319 @@
43+import os
44+import subprocess
45+
46+from gi.repository import GLib, Gtk, GObject
47+
48+from ubiquity import auto_update, i18n, misc, plugin
49+
50+from base.language import PageBase
51+
52+class PageGtk(PageBase):
53+ plugin_is_language = True
54+ plugin_title = 'ubiquity/text/language_heading_label'
55+
56+ def __init__(self, controller, *args, **kwargs):
57+ self.controller = controller
58+ self.timeout_id = None
59+ self.wget_retcode = None
60+ self.wget_proc = None
61+ if self.controller.oem_user_config:
62+ ui_file = 'stepLanguageOnly.ui'
63+ self.only = True
64+ else:
65+ ui_file = 'stepLanguage.ui'
66+ self.only = False
67+ builder = Gtk.Builder()
68+ builder.add_from_file(os.path.join(
69+ os.environ['UBIQUITY_GLADE'], ui_file))
70+ builder.connect_signals(self)
71+ self.controller.add_builder(builder)
72+ self.page = builder.get_object('stepLanguage')
73+ self.iconview = builder.get_object('language_iconview')
74+ self.treeview = builder.get_object('language_treeview')
75+ self.oem_id_entry = builder.get_object('oem_id_entry')
76+ if self.controller.oem_config:
77+ builder.get_object('oem_id_vbox').show()
78+
79+ self.release_notes_url = ''
80+ self.update_installer = True
81+ self.updating_installer = False
82+ self.release_notes_label = builder.get_object('release_notes_label')
83+ self.release_notes_found = False
84+ if self.release_notes_label:
85+ self.release_notes_label.connect(
86+ 'activate-link', self.on_link_clicked)
87+ if self.controller.oem_config or auto_update.already_updated():
88+ self.update_installer = False
89+ try:
90+ with open(self.RELEASE_NOTES_URL_PATH) as release_notes:
91+ self.release_notes_url = release_notes.read().rstrip('\n')
92+ self.release_notes_found = True
93+ except (KeyboardInterrupt, SystemExit):
94+ raise
95+ except:
96+ pass
97+ self.install_ubuntu = builder.get_object('install_ubuntu')
98+ self.try_ubuntu = builder.get_object('try_ubuntu')
99+ if not self.only:
100+ if not 'UBIQUITY_GREETER' in os.environ:
101+ choice_section_vbox = builder.get_object('choice_section_vbox')
102+ choice_section_vbox and choice_section_vbox.hide()
103+ else:
104+ def inst(*args):
105+ self.try_ubuntu.set_sensitive(False)
106+ self.controller.go_forward()
107+ self.install_ubuntu.connect('clicked', inst)
108+ self.try_ubuntu.connect('clicked', self.on_try_ubuntu_clicked)
109+ self.try_install_text_label = builder.get_object(
110+ 'try_install_text_label')
111+ # We do not want to show the yet to be substituted strings
112+ # (${MEDIUM}, etc), so don't show the core of the page until
113+ # it's ready.
114+ for w in self.page.get_children():
115+ w.hide()
116+ self.plugin_widgets = self.page
117+
118+ @plugin.only_this_page
119+ def on_try_ubuntu_clicked(self, *args):
120+ if not self.controller.allowed_change_step():
121+ # The button's already been clicked once, so stop reacting to it.
122+ # LP: #911907.
123+ return
124+ # Spinning cursor.
125+ self.controller.allow_change_step(False)
126+ # Queue quit.
127+ self.install_ubuntu.set_sensitive(False)
128+ self.controller._wizard.current_page = None
129+ self.controller.dbfilter.ok_handler()
130+
131+ def set_language_choices(self, choices, choice_map):
132+ PageBase.set_language_choices(self, choices, choice_map)
133+ list_store = Gtk.ListStore.new([GObject.TYPE_STRING])
134+ longest_length = 0
135+ longest = ''
136+ for choice in choices:
137+ list_store.append([choice])
138+ # Work around the fact that GtkIconView wraps at 50px or the width
139+ # of the icon, which is nonexistent here. See adjust_wrap_width ()
140+ # in gtkiconview.c for the details.
141+ if self.only:
142+ length = len(choice)
143+ if length > longest_length:
144+ longest_length = length
145+ longest = choice
146+ # Support both iconview and treeview
147+ if self.only:
148+ self.iconview.set_model(list_store)
149+ self.iconview.set_text_column(0)
150+ pad = self.iconview.get_property('item-padding')
151+ layout = self.iconview.create_pango_layout(longest)
152+ self.iconview.set_item_width(layout.get_pixel_size()[0] + pad * 2)
153+ else:
154+ if len(self.treeview.get_columns()) < 1:
155+ column = Gtk.TreeViewColumn(
156+ None, Gtk.CellRendererText(), text=0)
157+ column.set_sizing(Gtk.TreeViewColumnSizing.GROW_ONLY)
158+ self.treeview.append_column(column)
159+ selection = self.treeview.get_selection()
160+ selection.connect(
161+ 'changed', self.on_language_selection_changed)
162+ self.treeview.set_model(list_store)
163+
164+ def set_language(self, language):
165+ # Support both iconview and treeview
166+ if self.only:
167+ model = self.iconview.get_model()
168+ iterator = model.iter_children(None)
169+ while iterator is not None:
170+ if misc.utf8(model.get_value(iterator, 0)) == language:
171+ path = model.get_path(iterator)
172+ self.iconview.select_path(path)
173+ self.iconview.scroll_to_path(path, True, 0.5, 0.5)
174+ break
175+ iterator = model.iter_next(iterator)
176+ else:
177+ model = self.treeview.get_model()
178+ iterator = model.iter_children(None)
179+ while iterator is not None:
180+ if misc.utf8(model.get_value(iterator, 0)) == language:
181+ path = model.get_path(iterator)
182+ self.treeview.get_selection().select_path(path)
183+ self.treeview.scroll_to_cell(
184+ path, use_align=True, row_align=0.5)
185+ break
186+ iterator = model.iter_next(iterator)
187+
188+ if not self.only and 'UBIQUITY_GREETER' in os.environ:
189+ self.try_ubuntu.set_sensitive(True)
190+ self.install_ubuntu.set_sensitive(True)
191+
192+ def get_language(self):
193+ # Support both iconview and treeview
194+ if self.only:
195+ model = self.iconview.get_model()
196+ items = self.iconview.get_selected_items()
197+ if not items:
198+ return None
199+ iterator = model.get_iter(items[0])
200+ else:
201+ selection = self.treeview.get_selection()
202+ (model, iterator) = selection.get_selected()
203+ if iterator is None:
204+ return None
205+ else:
206+ value = misc.utf8(model.get_value(iterator, 0))
207+ return self.language_choice_map[value][1]
208+
209+ def on_language_activated(self, *args, **kwargs):
210+ self.controller.go_forward()
211+
212+ def on_language_selection_changed(self, *args, **kwargs):
213+ lang = self.get_language()
214+ self.controller.allow_go_forward(bool(lang))
215+ if not lang:
216+ return
217+ if 'UBIQUITY_GREETER' in os.environ:
218+ misc.set_indicator_keymaps(lang)
219+ # strip encoding; we use UTF-8 internally no matter what
220+ lang = lang.split('.')[0]
221+ self.controller.translate(lang)
222+ ltr = i18n.get_string('default-ltr', lang, 'ubiquity/imported')
223+ if ltr == 'default:RTL':
224+ Gtk.Widget.set_default_direction(Gtk.TextDirection.RTL)
225+ else:
226+ Gtk.Widget.set_default_direction(Gtk.TextDirection.LTR)
227+
228+ if self.only:
229+ # The language page for oem-config doesn't have the fancy greeter.
230+ return
231+
232+ # TODO: Cache these.
233+ release = misc.get_release()
234+ install_medium = misc.get_install_medium()
235+ install_medium = i18n.get_string(install_medium, lang)
236+ # Set the release name (Ubuntu 10.04) and medium (USB or CD) where
237+ # necessary.
238+ w = self.try_install_text_label
239+ text = i18n.get_string(Gtk.Buildable.get_name(w), lang)
240+ text = text.replace('${RELEASE}', release.name)
241+ text = text.replace('${MEDIUM}', install_medium)
242+ w.set_label(text)
243+
244+ # Big buttons.
245+ for w in (self.try_ubuntu, self.install_ubuntu):
246+ text = i18n.get_string(Gtk.Buildable.get_name(w), lang)
247+ text = text.replace('${RELEASE}', release.name)
248+ text = text.replace('${MEDIUM}', install_medium)
249+ w.get_child().set_markup('<span size="x-large">%s</span>' % text)
250+
251+ # We need to center each button under each image *and* have a homogeous
252+ # size between the two buttons.
253+ self.try_ubuntu.set_size_request(-1, -1)
254+ self.install_ubuntu.set_size_request(-1, -1)
255+ try_w = self.try_ubuntu.size_request().width
256+ install_w = self.install_ubuntu.size_request().width
257+ if try_w > install_w:
258+ self.try_ubuntu.set_size_request(try_w, -1)
259+ self.install_ubuntu.set_size_request(try_w, -1)
260+ elif install_w > try_w:
261+ self.try_ubuntu.set_size_request(install_w, -1)
262+ self.install_ubuntu.set_size_request(install_w, -1)
263+
264+ # Make the forward button a consistent size, regardless of its text.
265+ install_label = i18n.get_string('install_button', lang)
266+ next_button = self.controller._wizard.next
267+ next_label = next_button.get_label()
268+
269+ next_button.set_size_request(-1, -1)
270+ next_w = next_button.size_request().width
271+ next_button.set_label(install_label)
272+ install_w = next_button.size_request().width
273+ next_button.set_label(next_label)
274+ if next_w > install_w:
275+ next_button.set_size_request(next_w, -1)
276+ else:
277+ next_button.set_size_request(install_w, -1)
278+
279+ self.update_release_notes_label()
280+ for w in self.page.get_children():
281+ w.show()
282+
283+ def plugin_set_online_state(self, state):
284+ if self.release_notes_label:
285+ if self.timeout_id:
286+ GLib.source_remove(self.timeout_id)
287+ if state:
288+ self.release_notes_label.show()
289+ self.timeout_id = GLib.timeout_add(
290+ 300, self.check_returncode)
291+ else:
292+ self.release_notes_label.hide()
293+
294+ def check_returncode(self, *args):
295+ if self.wget_retcode is not None or self.wget_proc is None:
296+ self.wget_proc = subprocess.Popen(
297+ ['wget', '-q', self.WGET_URL, '--timeout=15', '--tries=1',
298+ '-O', '/dev/null'])
299+ self.wget_retcode = self.wget_proc.poll()
300+ if self.wget_retcode is None:
301+ return True
302+ else:
303+ if self.wget_retcode == 0:
304+ self.update_installer = True
305+ else:
306+ self.update_installer = False
307+ self.update_release_notes_label()
308+ return False
309+
310+ def update_release_notes_label(self):
311+ print("update_release_notes_label()")
312+ lang = self.get_language()
313+ if not lang:
314+ return
315+ # strip encoding; we use UTF-8 internally no matter what
316+ lang = lang.split('.')[0]
317+ # Either leave the release notes label alone (both release notes and a
318+ # critical update are available), set it to just the release notes,
319+ # just the critical update, or neither, as appropriate.
320+ if self.release_notes_label:
321+ if self.release_notes_found and self.update_installer:
322+ text = i18n.get_string('release_notes_label', lang)
323+ self.release_notes_label.set_markup(text)
324+ elif self.release_notes_found:
325+ text = i18n.get_string('release_notes_only', lang)
326+ self.release_notes_label.set_markup(text)
327+ elif self.update_installer:
328+ text = i18n.get_string('update_installer_only', lang)
329+ self.release_notes_label.set_markup(text)
330+ else:
331+ self.release_notes_label.set_markup('')
332+
333+ def set_oem_id(self, text):
334+ return self.oem_id_entry.set_text(text)
335+
336+ def get_oem_id(self):
337+ return self.oem_id_entry.get_text()
338+
339+ def on_link_clicked(self, widget, uri):
340+ # Connected in glade.
341+ lang = self.get_language()
342+ if not lang:
343+ lang = 'C'
344+ lang = lang.split('.')[0] # strip encoding
345+ if uri == 'update':
346+ if self.updating_installer:
347+ return True
348+ self.updating_installer = True
349+ if not auto_update.update(self.controller._wizard):
350+ # no updates, so don't check again
351+ if self.release_notes_url:
352+ text = i18n.get_string('release_notes_only', lang)
353+ self.release_notes_label.set_markup(text)
354+ else:
355+ self.release_notes_label.hide()
356+ self.updating_installer = False
357+ elif uri == 'release-notes':
358+ uri = self.release_notes_url.replace('${LANG}', lang)
359+ subprocess.Popen(['sensible-browser', uri], close_fds=True,
360+ preexec_fn=misc.drop_all_privileges)
361+ return True
362
363=== added directory 'ubiquity/plugins/kde'
364=== added file 'ubiquity/plugins/kde/__init__.py'
365=== added file 'ubiquity/plugins/kde/language.py'
366--- ubiquity/plugins/kde/language.py 1970-01-01 00:00:00 +0000
367+++ ubiquity/plugins/kde/language.py 2013-07-05 16:09:26 +0000
368@@ -0,0 +1,237 @@
369+import os
370+import subprocess
371+import syslog
372+
373+from PyQt4 import uic
374+from PyQt4.QtGui import QWidget, QPixmap, QDesktopServices
375+from PyQt4.QtCore import QUrl, QTimer, SIGNAL
376+
377+from ubiquity import auto_update, i18n, misc, plugin
378+from ubiquity.misc import drop_privileges_save, regain_privileges_save
379+
380+from base.language import PageBase
381+
382+class PageKde(PageBase):
383+ plugin_breadcrumb = 'ubiquity/text/breadcrumb_language'
384+ plugin_is_language = True
385+
386+ def __init__(self, controller, *args, **kwargs):
387+ self.controller = controller
388+ self.wget_retcode = None
389+ self.wget_proc = None
390+ if self.controller.oem_user_config:
391+ self.only = True
392+ else:
393+ self.only = False
394+
395+ try:
396+ self.page = uic.loadUi('/usr/share/ubiquity/qt/stepLanguage.ui')
397+ self.combobox = self.page.language_combobox
398+ self.combobox.view().setUniformItemSizes(True)
399+ self.combobox.currentIndexChanged[str].connect(
400+ self.on_language_selection_changed)
401+ if not self.controller.oem_config:
402+ self.page.oem_id_label.hide()
403+ self.page.oem_id_entry.hide()
404+
405+ def inst(*args):
406+ self.page.try_ubuntu.setEnabled(False)
407+ self.controller.go_forward()
408+ self.page.install_ubuntu.clicked.connect(inst)
409+ self.page.try_ubuntu.clicked.connect(self.on_try_ubuntu_clicked)
410+ picture1 = QPixmap(
411+ "/usr/share/ubiquity/pixmaps/kubuntu-live-session.png")
412+ self.page.image1.setPixmap(picture1)
413+ self.page.image1.resize(picture1.size())
414+ picture2 = QPixmap(
415+ "/usr/share/ubiquity/pixmaps/kubuntu-install.png")
416+ self.page.image2.setPixmap(picture2)
417+ self.page.image2.resize(picture2.size())
418+
419+ self.release_notes_url = ''
420+ self.update_installer = True
421+ self.updating_installer = False
422+ if self.controller.oem_config or auto_update.already_updated():
423+ self.update_installer = False
424+ self.release_notes_found = False
425+ try:
426+ with open(self.RELEASE_NOTES_URL_PATH) as release_notes:
427+ self.release_notes_url = release_notes.read().rstrip('\n')
428+ self.release_notes_found = True
429+ except (KeyboardInterrupt, SystemExit):
430+ raise
431+ except:
432+ pass
433+
434+ if self.release_notes_url:
435+ self.page.release_notes_label.linkActivated.connect(
436+ self.on_release_notes_link)
437+ else:
438+ self.page.release_notes_label.hide()
439+
440+ if not 'UBIQUITY_GREETER' in os.environ:
441+ self.page.try_ubuntu.hide()
442+ self.page.try_install_text_label.hide()
443+ self.page.install_ubuntu.hide()
444+ self.page.image1.hide()
445+ self.page.image2.hide()
446+
447+ # We do not want to show the yet to be substituted strings
448+ # (${MEDIUM}, etc), so don't show the core of the page until
449+ # it's ready.
450+ self.widgetHidden = []
451+ for w in self.page.children():
452+ if isinstance(w, QWidget) and not w.isHidden():
453+ self.widgetHidden.append(w)
454+ w.hide()
455+
456+ except Exception as e:
457+ syslog.syslog('Could not create language page: %s' % e)
458+ self.page = None
459+
460+ self.plugin_widgets = self.page
461+
462+ @plugin.only_this_page
463+ def on_try_ubuntu_clicked(self, *args):
464+ if not self.controller.allowed_change_step():
465+ # The button's already been clicked once, so stop reacting to it.
466+ # LP: #911907.
467+ return
468+ # Spinning cursor.
469+ self.controller.allow_change_step(False)
470+ # Queue quit.
471+ self.page.install_ubuntu.setEnabled(False)
472+ self.controller._wizard.current_page = None
473+ self.controller.dbfilter.ok_handler()
474+
475+ def on_release_notes_link(self, link):
476+ lang = self.selected_language()
477+ if link == "release-notes":
478+ if lang:
479+ lang = lang.split('.')[0].lower()
480+ url = self.release_notes_url.replace('${LANG}', lang)
481+ self.openURL(url)
482+ elif link == "update":
483+ if self.updating_installer:
484+ return
485+ self.updating_installer = True
486+ if not auto_update.update(self.controller._wizard):
487+ # no updates, so don't check again
488+ text = i18n.get_string('release_notes_only', lang)
489+ self.page.release_notes_label.setText(text)
490+ self.updating_installer = False
491+
492+ def openURL(self, url):
493+ # this nonsense is needed because kde doesn't want to be root
494+ drop_privileges_save()
495+ QDesktopServices.openUrl(QUrl(url))
496+ regain_privileges_save()
497+
498+ def set_language_choices(self, choices, choice_map):
499+ PageBase.set_language_choices(self, choices, choice_map)
500+ self.combobox.clear()
501+ #self.combobox.addItems(choices)
502+ for choice in choices:
503+ self.combobox.addItem(str(choice))
504+
505+ def set_language(self, language):
506+ index = self.combobox.findText(str(language))
507+ if index < 0:
508+ self.combobox.addItem("C")
509+ else:
510+ self.combobox.setCurrentIndex(index)
511+
512+ if not self.only and 'UBIQUITY_GREETER' in os.environ:
513+ self.page.try_ubuntu.setEnabled(True)
514+ self.page.install_ubuntu.setEnabled(True)
515+
516+ def get_language(self):
517+ lang = self.selected_language()
518+ return lang if lang else 'C'
519+
520+ def selected_language(self):
521+ lang = self.combobox.currentText()
522+ if not lang or not hasattr(self, 'language_choice_map'):
523+ return None
524+ else:
525+ return self.language_choice_map[str(lang)][1]
526+
527+ def on_language_selection_changed(self):
528+ lang = self.selected_language()
529+ if not lang:
530+ return
531+ # strip encoding; we use UTF-8 internally no matter what
532+ lang = lang.split('.')[0]
533+ self.controller.translate(lang)
534+ if not self.only:
535+ release = misc.get_release()
536+ install_medium = misc.get_install_medium()
537+ install_medium = i18n.get_string(install_medium, lang)
538+ for widget in (self.page.try_install_text_label,
539+ self.page.try_ubuntu,
540+ self.page.install_ubuntu):
541+ text = widget.text()
542+ text = text.replace('${RELEASE}', release.name)
543+ text = text.replace('${MEDIUM}', install_medium)
544+ text = text.replace('Ubuntu', 'Kubuntu')
545+ widget.setText(text)
546+
547+ self.update_release_notes_label()
548+ for w in self.widgetHidden:
549+ w.show()
550+ self.widgetHidden = []
551+
552+ def plugin_set_online_state(self, state):
553+ if self.page.release_notes_label:
554+ if state:
555+ self.page.release_notes_label.show()
556+ QTimer.singleShot(300, self.check_returncode)
557+ self.timer = QTimer(self.page)
558+ self.timer.connect(
559+ self.timer, SIGNAL("timeout()"), self.check_returncode)
560+ self.timer.start(300)
561+ else:
562+ self.page.release_notes_label.hide()
563+
564+ def check_returncode(self, *args):
565+ if self.wget_retcode is not None or self.wget_proc is None:
566+ self.wget_proc = subprocess.Popen(
567+ ['wget', '-q', self.WGET_URL, '--timeout=15', '--tries=1',
568+ '-O', '/dev/null'])
569+ self.wget_retcode = self.wget_proc.poll()
570+ if self.wget_retcode is None:
571+ return True
572+ else:
573+ if self.wget_retcode == 0:
574+ self.update_installer = True
575+ else:
576+ self.update_installer = False
577+ self.update_release_notes_label()
578+ self.timer.disconnect(
579+ self.timer, SIGNAL("timeout()"), self.check_returncode)
580+
581+ def update_release_notes_label(self):
582+ lang = self.selected_language()
583+ if not lang:
584+ return
585+ # strip encoding; we use UTF-8 internally no matter what
586+ lang = lang.split('.')[0]
587+ # Either leave the release notes label alone (both release notes and a
588+ # critical update are available), set it to just the release notes,
589+ # just the critical update, or neither, as appropriate.
590+ if self.page.release_notes_label:
591+ if self.release_notes_found and self.update_installer:
592+ text = i18n.get_string('release_notes_label', lang)
593+ self.page.release_notes_label.setText(text)
594+ elif self.release_notes_found:
595+ text = i18n.get_string('release_notes_only', lang)
596+ self.page.release_notes_label.setText(text)
597+ elif self.update_installer:
598+ text = i18n.get_string('update_installer_only', lang)
599+ self.page.release_notes_label.setText(text)
600+
601+ def set_oem_id(self, text):
602+ return self.page.oem_id_entry.setText(text)
603+
604+ def get_oem_id(self):
605+ return str(self.page.oem_id_entry.text())
606
607=== modified file 'ubiquity/plugins/ubi-language.py'
608--- ubiquity/plugins/ubi-language.py 2013-04-28 13:46:10 +0000
609+++ ubiquity/plugins/ubi-language.py 2013-07-05 16:09:26 +0000
610@@ -27,590 +27,20 @@
611
612 from ubiquity import auto_update, i18n, misc, osextras, plugin
613
614+from base.language import PageBase
615
616 NAME = 'language'
617 AFTER = None
618 WEIGHT = 10
619
620-try:
621- import lsb_release
622- _ver = lsb_release.get_distro_information()['RELEASE']
623-except:
624- _ver = '12.04'
625-_wget_url = 'http://changelogs.ubuntu.com/ubiquity/%s-update-available' % _ver
626-
627-_release_notes_url_path = '/cdrom/.disk/release_notes_url'
628-
629-
630-class PageBase(plugin.PluginUI):
631- def set_language_choices(self, unused_choices, choice_map):
632- """Called with language choices and a map to localised names."""
633- self.language_choice_map = dict(choice_map)
634-
635- def set_language(self, language):
636- """Set the current selected language."""
637- pass
638-
639- def get_language(self):
640- """Get the current selected language."""
641- return 'C'
642-
643- def set_oem_id(self, text):
644- pass
645-
646- def get_oem_id(self):
647- return ''
648-
649-
650-class PageGtk(PageBase):
651- plugin_is_language = True
652- plugin_title = 'ubiquity/text/language_heading_label'
653-
654- def __init__(self, controller, *args, **kwargs):
655- self.controller = controller
656- self.timeout_id = None
657- self.wget_retcode = None
658- self.wget_proc = None
659- if self.controller.oem_user_config:
660- ui_file = 'stepLanguageOnly.ui'
661- self.only = True
662- else:
663- ui_file = 'stepLanguage.ui'
664- self.only = False
665- from gi.repository import Gtk
666- builder = Gtk.Builder()
667- builder.add_from_file(os.path.join(
668- os.environ['UBIQUITY_GLADE'], ui_file))
669- builder.connect_signals(self)
670- self.controller.add_builder(builder)
671- self.page = builder.get_object('stepLanguage')
672- self.iconview = builder.get_object('language_iconview')
673- self.treeview = builder.get_object('language_treeview')
674- self.oem_id_entry = builder.get_object('oem_id_entry')
675- if self.controller.oem_config:
676- builder.get_object('oem_id_vbox').show()
677-
678- self.release_notes_url = ''
679- self.update_installer = True
680- self.updating_installer = False
681- self.release_notes_label = builder.get_object('release_notes_label')
682- self.release_notes_found = False
683- if self.release_notes_label:
684- self.release_notes_label.connect(
685- 'activate-link', self.on_link_clicked)
686- if self.controller.oem_config or auto_update.already_updated():
687- self.update_installer = False
688- try:
689- with open(_release_notes_url_path) as release_notes:
690- self.release_notes_url = release_notes.read().rstrip('\n')
691- self.release_notes_found = True
692- except (KeyboardInterrupt, SystemExit):
693- raise
694- except:
695- pass
696- self.install_ubuntu = builder.get_object('install_ubuntu')
697- self.try_ubuntu = builder.get_object('try_ubuntu')
698- if not self.only:
699- if not 'UBIQUITY_GREETER' in os.environ:
700- choice_section_vbox = builder.get_object('choice_section_vbox')
701- choice_section_vbox and choice_section_vbox.hide()
702- else:
703- def inst(*args):
704- self.try_ubuntu.set_sensitive(False)
705- self.controller.go_forward()
706- self.install_ubuntu.connect('clicked', inst)
707- self.try_ubuntu.connect('clicked', self.on_try_ubuntu_clicked)
708- self.try_install_text_label = builder.get_object(
709- 'try_install_text_label')
710- # We do not want to show the yet to be substituted strings
711- # (${MEDIUM}, etc), so don't show the core of the page until
712- # it's ready.
713- for w in self.page.get_children():
714- w.hide()
715- self.plugin_widgets = self.page
716-
717- @plugin.only_this_page
718- def on_try_ubuntu_clicked(self, *args):
719- if not self.controller.allowed_change_step():
720- # The button's already been clicked once, so stop reacting to it.
721- # LP: #911907.
722- return
723- # Spinning cursor.
724- self.controller.allow_change_step(False)
725- # Queue quit.
726- self.install_ubuntu.set_sensitive(False)
727- self.controller._wizard.current_page = None
728- self.controller.dbfilter.ok_handler()
729-
730- def set_language_choices(self, choices, choice_map):
731- from gi.repository import Gtk, GObject
732- PageBase.set_language_choices(self, choices, choice_map)
733- list_store = Gtk.ListStore.new([GObject.TYPE_STRING])
734- longest_length = 0
735- longest = ''
736- for choice in choices:
737- list_store.append([choice])
738- # Work around the fact that GtkIconView wraps at 50px or the width
739- # of the icon, which is nonexistent here. See adjust_wrap_width ()
740- # in gtkiconview.c for the details.
741- if self.only:
742- length = len(choice)
743- if length > longest_length:
744- longest_length = length
745- longest = choice
746- # Support both iconview and treeview
747- if self.only:
748- self.iconview.set_model(list_store)
749- self.iconview.set_text_column(0)
750- pad = self.iconview.get_property('item-padding')
751- layout = self.iconview.create_pango_layout(longest)
752- self.iconview.set_item_width(layout.get_pixel_size()[0] + pad * 2)
753- else:
754- if len(self.treeview.get_columns()) < 1:
755- column = Gtk.TreeViewColumn(
756- None, Gtk.CellRendererText(), text=0)
757- column.set_sizing(Gtk.TreeViewColumnSizing.GROW_ONLY)
758- self.treeview.append_column(column)
759- selection = self.treeview.get_selection()
760- selection.connect(
761- 'changed', self.on_language_selection_changed)
762- self.treeview.set_model(list_store)
763-
764- def set_language(self, language):
765- # Support both iconview and treeview
766- if self.only:
767- model = self.iconview.get_model()
768- iterator = model.iter_children(None)
769- while iterator is not None:
770- if misc.utf8(model.get_value(iterator, 0)) == language:
771- path = model.get_path(iterator)
772- self.iconview.select_path(path)
773- self.iconview.scroll_to_path(path, True, 0.5, 0.5)
774- break
775- iterator = model.iter_next(iterator)
776- else:
777- model = self.treeview.get_model()
778- iterator = model.iter_children(None)
779- while iterator is not None:
780- if misc.utf8(model.get_value(iterator, 0)) == language:
781- path = model.get_path(iterator)
782- self.treeview.get_selection().select_path(path)
783- self.treeview.scroll_to_cell(
784- path, use_align=True, row_align=0.5)
785- break
786- iterator = model.iter_next(iterator)
787-
788- if not self.only and 'UBIQUITY_GREETER' in os.environ:
789- self.try_ubuntu.set_sensitive(True)
790- self.install_ubuntu.set_sensitive(True)
791-
792- def get_language(self):
793- # Support both iconview and treeview
794- if self.only:
795- model = self.iconview.get_model()
796- items = self.iconview.get_selected_items()
797- if not items:
798- return None
799- iterator = model.get_iter(items[0])
800- else:
801- selection = self.treeview.get_selection()
802- (model, iterator) = selection.get_selected()
803- if iterator is None:
804- return None
805- else:
806- value = misc.utf8(model.get_value(iterator, 0))
807- return self.language_choice_map[value][1]
808-
809- def on_language_activated(self, *args, **kwargs):
810- self.controller.go_forward()
811-
812- def on_language_selection_changed(self, *args, **kwargs):
813- lang = self.get_language()
814- self.controller.allow_go_forward(bool(lang))
815- if not lang:
816- return
817- if 'UBIQUITY_GREETER' in os.environ:
818- misc.set_indicator_keymaps(lang)
819- # strip encoding; we use UTF-8 internally no matter what
820- lang = lang.split('.')[0]
821- self.controller.translate(lang)
822- from gi.repository import Gtk
823- ltr = i18n.get_string('default-ltr', lang, 'ubiquity/imported')
824- if ltr == 'default:RTL':
825- Gtk.Widget.set_default_direction(Gtk.TextDirection.RTL)
826- else:
827- Gtk.Widget.set_default_direction(Gtk.TextDirection.LTR)
828-
829- if self.only:
830- # The language page for oem-config doesn't have the fancy greeter.
831- return
832-
833- # TODO: Cache these.
834- release = misc.get_release()
835- install_medium = misc.get_install_medium()
836- install_medium = i18n.get_string(install_medium, lang)
837- # Set the release name (Ubuntu 10.04) and medium (USB or CD) where
838- # necessary.
839- w = self.try_install_text_label
840- text = i18n.get_string(Gtk.Buildable.get_name(w), lang)
841- text = text.replace('${RELEASE}', release.name)
842- text = text.replace('${MEDIUM}', install_medium)
843- w.set_label(text)
844-
845- # Big buttons.
846- for w in (self.try_ubuntu, self.install_ubuntu):
847- text = i18n.get_string(Gtk.Buildable.get_name(w), lang)
848- text = text.replace('${RELEASE}', release.name)
849- text = text.replace('${MEDIUM}', install_medium)
850- w.get_child().set_markup('<span size="x-large">%s</span>' % text)
851-
852- # We need to center each button under each image *and* have a homogeous
853- # size between the two buttons.
854- self.try_ubuntu.set_size_request(-1, -1)
855- self.install_ubuntu.set_size_request(-1, -1)
856- try_w = self.try_ubuntu.size_request().width
857- install_w = self.install_ubuntu.size_request().width
858- if try_w > install_w:
859- self.try_ubuntu.set_size_request(try_w, -1)
860- self.install_ubuntu.set_size_request(try_w, -1)
861- elif install_w > try_w:
862- self.try_ubuntu.set_size_request(install_w, -1)
863- self.install_ubuntu.set_size_request(install_w, -1)
864-
865- # Make the forward button a consistent size, regardless of its text.
866- install_label = i18n.get_string('install_button', lang)
867- next_button = self.controller._wizard.next
868- next_label = next_button.get_label()
869-
870- next_button.set_size_request(-1, -1)
871- next_w = next_button.size_request().width
872- next_button.set_label(install_label)
873- install_w = next_button.size_request().width
874- next_button.set_label(next_label)
875- if next_w > install_w:
876- next_button.set_size_request(next_w, -1)
877- else:
878- next_button.set_size_request(install_w, -1)
879-
880- self.update_release_notes_label()
881- for w in self.page.get_children():
882- w.show()
883-
884- def plugin_set_online_state(self, state):
885- from gi.repository import GLib
886- if self.release_notes_label:
887- if self.timeout_id:
888- GLib.source_remove(self.timeout_id)
889- if state:
890- self.release_notes_label.show()
891- self.timeout_id = GLib.timeout_add(
892- 300, self.check_returncode)
893- else:
894- self.release_notes_label.hide()
895-
896- def check_returncode(self, *args):
897- import subprocess
898- if self.wget_retcode is not None or self.wget_proc is None:
899- self.wget_proc = subprocess.Popen(
900- ['wget', '-q', _wget_url, '--timeout=15', '--tries=1',
901- '-O', '/dev/null'])
902- self.wget_retcode = self.wget_proc.poll()
903- if self.wget_retcode is None:
904- return True
905- else:
906- if self.wget_retcode == 0:
907- self.update_installer = True
908- else:
909- self.update_installer = False
910- self.update_release_notes_label()
911- return False
912-
913- def update_release_notes_label(self):
914- print("update_release_notes_label()")
915- lang = self.get_language()
916- if not lang:
917- return
918- # strip encoding; we use UTF-8 internally no matter what
919- lang = lang.split('.')[0]
920- # Either leave the release notes label alone (both release notes and a
921- # critical update are available), set it to just the release notes,
922- # just the critical update, or neither, as appropriate.
923- if self.release_notes_label:
924- if self.release_notes_found and self.update_installer:
925- text = i18n.get_string('release_notes_label', lang)
926- self.release_notes_label.set_markup(text)
927- elif self.release_notes_found:
928- text = i18n.get_string('release_notes_only', lang)
929- self.release_notes_label.set_markup(text)
930- elif self.update_installer:
931- text = i18n.get_string('update_installer_only', lang)
932- self.release_notes_label.set_markup(text)
933- else:
934- self.release_notes_label.set_markup('')
935-
936- def set_oem_id(self, text):
937- return self.oem_id_entry.set_text(text)
938-
939- def get_oem_id(self):
940- return self.oem_id_entry.get_text()
941-
942- def on_link_clicked(self, widget, uri):
943- # Connected in glade.
944- lang = self.get_language()
945- if not lang:
946- lang = 'C'
947- lang = lang.split('.')[0] # strip encoding
948- if uri == 'update':
949- if self.updating_installer:
950- return True
951- self.updating_installer = True
952- if not auto_update.update(self.controller._wizard):
953- # no updates, so don't check again
954- if self.release_notes_url:
955- text = i18n.get_string('release_notes_only', lang)
956- self.release_notes_label.set_markup(text)
957- else:
958- self.release_notes_label.hide()
959- self.updating_installer = False
960- elif uri == 'release-notes':
961- import subprocess
962- uri = self.release_notes_url.replace('${LANG}', lang)
963- subprocess.Popen(['sensible-browser', uri], close_fds=True,
964- preexec_fn=misc.drop_all_privileges)
965- return True
966-
967-
968-class PageKde(PageBase):
969- plugin_breadcrumb = 'ubiquity/text/breadcrumb_language'
970- plugin_is_language = True
971-
972- def __init__(self, controller, *args, **kwargs):
973- self.controller = controller
974- self.wget_retcode = None
975- self.wget_proc = None
976- if self.controller.oem_user_config:
977- self.only = True
978- else:
979- self.only = False
980-
981- try:
982- from PyQt4 import uic
983- from PyQt4.QtGui import QWidget, QPixmap
984- self.page = uic.loadUi('/usr/share/ubiquity/qt/stepLanguage.ui')
985- self.combobox = self.page.language_combobox
986- self.combobox.currentIndexChanged[str].connect(
987- self.on_language_selection_changed)
988- if not self.controller.oem_config:
989- self.page.oem_id_label.hide()
990- self.page.oem_id_entry.hide()
991-
992- def inst(*args):
993- self.page.try_ubuntu.setEnabled(False)
994- self.controller.go_forward()
995- self.page.install_ubuntu.clicked.connect(inst)
996- self.page.try_ubuntu.clicked.connect(self.on_try_ubuntu_clicked)
997- picture1 = QPixmap(
998- "/usr/share/ubiquity/pixmaps/kubuntu-live-session.png")
999- self.page.image1.setPixmap(picture1)
1000- self.page.image1.resize(picture1.size())
1001- picture2 = QPixmap(
1002- "/usr/share/ubiquity/pixmaps/kubuntu-install.png")
1003- self.page.image2.setPixmap(picture2)
1004- self.page.image2.resize(picture2.size())
1005-
1006- self.release_notes_url = ''
1007- self.update_installer = True
1008- self.updating_installer = False
1009- if self.controller.oem_config or auto_update.already_updated():
1010- self.update_installer = False
1011- self.release_notes_found = False
1012- try:
1013- with open(_release_notes_url_path) as release_notes:
1014- self.release_notes_url = release_notes.read().rstrip('\n')
1015- self.release_notes_found = True
1016- except (KeyboardInterrupt, SystemExit):
1017- raise
1018- except:
1019- pass
1020-
1021- if self.release_notes_url:
1022- self.page.release_notes_label.linkActivated.connect(
1023- self.on_release_notes_link)
1024- else:
1025- self.page.release_notes_label.hide()
1026-
1027- if not 'UBIQUITY_GREETER' in os.environ:
1028- self.page.try_ubuntu.hide()
1029- self.page.try_install_text_label.hide()
1030- self.page.install_ubuntu.hide()
1031- self.page.image1.hide()
1032- self.page.image2.hide()
1033-
1034- # We do not want to show the yet to be substituted strings
1035- # (${MEDIUM}, etc), so don't show the core of the page until
1036- # it's ready.
1037- self.widgetHidden = []
1038- for w in self.page.children():
1039- if isinstance(w, QWidget) and not w.isHidden():
1040- self.widgetHidden.append(w)
1041- w.hide()
1042-
1043- except Exception as e:
1044- self.debug('Could not create language page: %s', e)
1045- self.page = None
1046-
1047- self.plugin_widgets = self.page
1048-
1049- @plugin.only_this_page
1050- def on_try_ubuntu_clicked(self, *args):
1051- if not self.controller.allowed_change_step():
1052- # The button's already been clicked once, so stop reacting to it.
1053- # LP: #911907.
1054- return
1055- # Spinning cursor.
1056- self.controller.allow_change_step(False)
1057- # Queue quit.
1058- self.page.install_ubuntu.setEnabled(False)
1059- self.controller._wizard.current_page = None
1060- self.controller.dbfilter.ok_handler()
1061-
1062- def on_release_notes_link(self, link):
1063- lang = self.selected_language()
1064- if link == "release-notes":
1065- if lang:
1066- lang = lang.split('.')[0].lower()
1067- url = self.release_notes_url.replace('${LANG}', lang)
1068- self.openURL(url)
1069- elif link == "update":
1070- if self.updating_installer:
1071- return
1072- self.updating_installer = True
1073- if not auto_update.update(self.controller._wizard):
1074- # no updates, so don't check again
1075- text = i18n.get_string('release_notes_only', lang)
1076- self.page.release_notes_label.setText(text)
1077- self.updating_installer = False
1078-
1079- def openURL(self, url):
1080- from PyQt4.QtGui import QDesktopServices
1081- from PyQt4.QtCore import QUrl
1082- from ubiquity.misc import drop_privileges_save, regain_privileges_save
1083-
1084- # this nonsense is needed because kde doesn't want to be root
1085- drop_privileges_save()
1086- QDesktopServices.openUrl(QUrl(url))
1087- regain_privileges_save()
1088-
1089- def set_language_choices(self, choices, choice_map):
1090- PageBase.set_language_choices(self, choices, choice_map)
1091- self.combobox.clear()
1092- for choice in choices:
1093- self.combobox.addItem(str(choice))
1094-
1095- def set_language(self, language):
1096- index = self.combobox.findText(str(language))
1097- if index < 0:
1098- self.combobox.addItem("C")
1099- else:
1100- self.combobox.setCurrentIndex(index)
1101-
1102- if not self.only and 'UBIQUITY_GREETER' in os.environ:
1103- self.page.try_ubuntu.setEnabled(True)
1104- self.page.install_ubuntu.setEnabled(True)
1105-
1106- def get_language(self):
1107- lang = self.selected_language()
1108- return lang if lang else 'C'
1109-
1110- def selected_language(self):
1111- lang = self.combobox.currentText()
1112- if not lang or not hasattr(self, 'language_choice_map'):
1113- return None
1114- else:
1115- return self.language_choice_map[str(lang)][1]
1116-
1117- def on_language_selection_changed(self):
1118- lang = self.selected_language()
1119- if not lang:
1120- return
1121- # strip encoding; we use UTF-8 internally no matter what
1122- lang = lang.split('.')[0]
1123- self.controller.translate(lang)
1124- if not self.only:
1125- release = misc.get_release()
1126- install_medium = misc.get_install_medium()
1127- install_medium = i18n.get_string(install_medium, lang)
1128- for widget in (self.page.try_install_text_label,
1129- self.page.try_ubuntu,
1130- self.page.install_ubuntu):
1131- text = widget.text()
1132- text = text.replace('${RELEASE}', release.name)
1133- text = text.replace('${MEDIUM}', install_medium)
1134- text = text.replace('Ubuntu', 'Kubuntu')
1135- widget.setText(text)
1136-
1137- self.update_release_notes_label()
1138- for w in self.widgetHidden:
1139- w.show()
1140- self.widgetHidden = []
1141-
1142- def plugin_set_online_state(self, state):
1143- from PyQt4.QtCore import QTimer, SIGNAL
1144- if self.page.release_notes_label:
1145- if state:
1146- self.page.release_notes_label.show()
1147- QTimer.singleShot(300, self.check_returncode)
1148- self.timer = QTimer(self.page)
1149- self.timer.connect(
1150- self.timer, SIGNAL("timeout()"), self.check_returncode)
1151- self.timer.start(300)
1152- else:
1153- self.page.release_notes_label.hide()
1154-
1155- def check_returncode(self, *args):
1156- import subprocess
1157- from PyQt4.QtCore import SIGNAL
1158- if self.wget_retcode is not None or self.wget_proc is None:
1159- self.wget_proc = subprocess.Popen(
1160- ['wget', '-q', _wget_url, '--timeout=15', '--tries=1',
1161- '-O', '/dev/null'])
1162- self.wget_retcode = self.wget_proc.poll()
1163- if self.wget_retcode is None:
1164- return True
1165- else:
1166- if self.wget_retcode == 0:
1167- self.update_installer = True
1168- else:
1169- self.update_installer = False
1170- self.update_release_notes_label()
1171- self.timer.disconnect(
1172- self.timer, SIGNAL("timeout()"), self.check_returncode)
1173-
1174- def update_release_notes_label(self):
1175- lang = self.selected_language()
1176- if not lang:
1177- return
1178- # strip encoding; we use UTF-8 internally no matter what
1179- lang = lang.split('.')[0]
1180- # Either leave the release notes label alone (both release notes and a
1181- # critical update are available), set it to just the release notes,
1182- # just the critical update, or neither, as appropriate.
1183- if self.page.release_notes_label:
1184- if self.release_notes_found and self.update_installer:
1185- text = i18n.get_string('release_notes_label', lang)
1186- self.page.release_notes_label.setText(text)
1187- elif self.release_notes_found:
1188- text = i18n.get_string('release_notes_only', lang)
1189- self.page.release_notes_label.setText(text)
1190- elif self.update_installer:
1191- text = i18n.get_string('update_installer_only', lang)
1192- self.page.release_notes_label.setText(text)
1193-
1194- def set_oem_id(self, text):
1195- return self.page.oem_id_entry.setText(text)
1196-
1197- def get_oem_id(self):
1198- return str(self.page.oem_id_entry.text())
1199+def PageGtk(controller, *args, **kwargs):
1200+ import gtk.language
1201+ return gtk.language.PageGtk(controller, *args, **kwargs)
1202+
1203+
1204+def PageKde(controller, *args, **kwargs):
1205+ import kde.language
1206+ return kde.language.PageKde(controller, *args, **kwargs)
1207
1208
1209 class PageDebconf(PageBase):

Subscribers

People subscribed via source and target branches

to status/vote changes: