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
=== added directory 'ubiquity/plugins/base'
=== added file 'ubiquity/plugins/base/__init__.py'
=== added file 'ubiquity/plugins/base/language.py'
--- ubiquity/plugins/base/language.py 1970-01-01 00:00:00 +0000
+++ ubiquity/plugins/base/language.py 2013-07-05 16:09:26 +0000
@@ -0,0 +1,29 @@
1from ubiquity import plugin
2
3try:
4 import lsb_release
5 _ver = lsb_release.get_distro_information()['RELEASE']
6except:
7 _ver = '12.04'
8
9class PageBase(plugin.PluginUI):
10 WGET_URL = 'http://changelogs.ubuntu.com/ubiquity/%s-update-available' % _ver
11 RELEASE_NOTES_URL_PATH = '/cdrom/.disk/release_notes_url'
12
13 def set_language_choices(self, unused_choices, choice_map):
14 """Called with language choices and a map to localised names."""
15 self.language_choice_map = dict(choice_map)
16
17 def set_language(self, language):
18 """Set the current selected language."""
19 pass
20
21 def get_language(self):
22 """Get the current selected language."""
23 return 'C'
24
25 def set_oem_id(self, text):
26 pass
27
28 def get_oem_id(self):
29 return ''
030
=== added directory 'ubiquity/plugins/gtk'
=== added file 'ubiquity/plugins/gtk/__init__.py'
=== added file 'ubiquity/plugins/gtk/language.py'
--- ubiquity/plugins/gtk/language.py 1970-01-01 00:00:00 +0000
+++ ubiquity/plugins/gtk/language.py 2013-07-05 16:09:26 +0000
@@ -0,0 +1,319 @@
1import os
2import subprocess
3
4from gi.repository import GLib, Gtk, GObject
5
6from ubiquity import auto_update, i18n, misc, plugin
7
8from base.language import PageBase
9
10class PageGtk(PageBase):
11 plugin_is_language = True
12 plugin_title = 'ubiquity/text/language_heading_label'
13
14 def __init__(self, controller, *args, **kwargs):
15 self.controller = controller
16 self.timeout_id = None
17 self.wget_retcode = None
18 self.wget_proc = None
19 if self.controller.oem_user_config:
20 ui_file = 'stepLanguageOnly.ui'
21 self.only = True
22 else:
23 ui_file = 'stepLanguage.ui'
24 self.only = False
25 builder = Gtk.Builder()
26 builder.add_from_file(os.path.join(
27 os.environ['UBIQUITY_GLADE'], ui_file))
28 builder.connect_signals(self)
29 self.controller.add_builder(builder)
30 self.page = builder.get_object('stepLanguage')
31 self.iconview = builder.get_object('language_iconview')
32 self.treeview = builder.get_object('language_treeview')
33 self.oem_id_entry = builder.get_object('oem_id_entry')
34 if self.controller.oem_config:
35 builder.get_object('oem_id_vbox').show()
36
37 self.release_notes_url = ''
38 self.update_installer = True
39 self.updating_installer = False
40 self.release_notes_label = builder.get_object('release_notes_label')
41 self.release_notes_found = False
42 if self.release_notes_label:
43 self.release_notes_label.connect(
44 'activate-link', self.on_link_clicked)
45 if self.controller.oem_config or auto_update.already_updated():
46 self.update_installer = False
47 try:
48 with open(self.RELEASE_NOTES_URL_PATH) as release_notes:
49 self.release_notes_url = release_notes.read().rstrip('\n')
50 self.release_notes_found = True
51 except (KeyboardInterrupt, SystemExit):
52 raise
53 except:
54 pass
55 self.install_ubuntu = builder.get_object('install_ubuntu')
56 self.try_ubuntu = builder.get_object('try_ubuntu')
57 if not self.only:
58 if not 'UBIQUITY_GREETER' in os.environ:
59 choice_section_vbox = builder.get_object('choice_section_vbox')
60 choice_section_vbox and choice_section_vbox.hide()
61 else:
62 def inst(*args):
63 self.try_ubuntu.set_sensitive(False)
64 self.controller.go_forward()
65 self.install_ubuntu.connect('clicked', inst)
66 self.try_ubuntu.connect('clicked', self.on_try_ubuntu_clicked)
67 self.try_install_text_label = builder.get_object(
68 'try_install_text_label')
69 # We do not want to show the yet to be substituted strings
70 # (${MEDIUM}, etc), so don't show the core of the page until
71 # it's ready.
72 for w in self.page.get_children():
73 w.hide()
74 self.plugin_widgets = self.page
75
76 @plugin.only_this_page
77 def on_try_ubuntu_clicked(self, *args):
78 if not self.controller.allowed_change_step():
79 # The button's already been clicked once, so stop reacting to it.
80 # LP: #911907.
81 return
82 # Spinning cursor.
83 self.controller.allow_change_step(False)
84 # Queue quit.
85 self.install_ubuntu.set_sensitive(False)
86 self.controller._wizard.current_page = None
87 self.controller.dbfilter.ok_handler()
88
89 def set_language_choices(self, choices, choice_map):
90 PageBase.set_language_choices(self, choices, choice_map)
91 list_store = Gtk.ListStore.new([GObject.TYPE_STRING])
92 longest_length = 0
93 longest = ''
94 for choice in choices:
95 list_store.append([choice])
96 # Work around the fact that GtkIconView wraps at 50px or the width
97 # of the icon, which is nonexistent here. See adjust_wrap_width ()
98 # in gtkiconview.c for the details.
99 if self.only:
100 length = len(choice)
101 if length > longest_length:
102 longest_length = length
103 longest = choice
104 # Support both iconview and treeview
105 if self.only:
106 self.iconview.set_model(list_store)
107 self.iconview.set_text_column(0)
108 pad = self.iconview.get_property('item-padding')
109 layout = self.iconview.create_pango_layout(longest)
110 self.iconview.set_item_width(layout.get_pixel_size()[0] + pad * 2)
111 else:
112 if len(self.treeview.get_columns()) < 1:
113 column = Gtk.TreeViewColumn(
114 None, Gtk.CellRendererText(), text=0)
115 column.set_sizing(Gtk.TreeViewColumnSizing.GROW_ONLY)
116 self.treeview.append_column(column)
117 selection = self.treeview.get_selection()
118 selection.connect(
119 'changed', self.on_language_selection_changed)
120 self.treeview.set_model(list_store)
121
122 def set_language(self, language):
123 # Support both iconview and treeview
124 if self.only:
125 model = self.iconview.get_model()
126 iterator = model.iter_children(None)
127 while iterator is not None:
128 if misc.utf8(model.get_value(iterator, 0)) == language:
129 path = model.get_path(iterator)
130 self.iconview.select_path(path)
131 self.iconview.scroll_to_path(path, True, 0.5, 0.5)
132 break
133 iterator = model.iter_next(iterator)
134 else:
135 model = self.treeview.get_model()
136 iterator = model.iter_children(None)
137 while iterator is not None:
138 if misc.utf8(model.get_value(iterator, 0)) == language:
139 path = model.get_path(iterator)
140 self.treeview.get_selection().select_path(path)
141 self.treeview.scroll_to_cell(
142 path, use_align=True, row_align=0.5)
143 break
144 iterator = model.iter_next(iterator)
145
146 if not self.only and 'UBIQUITY_GREETER' in os.environ:
147 self.try_ubuntu.set_sensitive(True)
148 self.install_ubuntu.set_sensitive(True)
149
150 def get_language(self):
151 # Support both iconview and treeview
152 if self.only:
153 model = self.iconview.get_model()
154 items = self.iconview.get_selected_items()
155 if not items:
156 return None
157 iterator = model.get_iter(items[0])
158 else:
159 selection = self.treeview.get_selection()
160 (model, iterator) = selection.get_selected()
161 if iterator is None:
162 return None
163 else:
164 value = misc.utf8(model.get_value(iterator, 0))
165 return self.language_choice_map[value][1]
166
167 def on_language_activated(self, *args, **kwargs):
168 self.controller.go_forward()
169
170 def on_language_selection_changed(self, *args, **kwargs):
171 lang = self.get_language()
172 self.controller.allow_go_forward(bool(lang))
173 if not lang:
174 return
175 if 'UBIQUITY_GREETER' in os.environ:
176 misc.set_indicator_keymaps(lang)
177 # strip encoding; we use UTF-8 internally no matter what
178 lang = lang.split('.')[0]
179 self.controller.translate(lang)
180 ltr = i18n.get_string('default-ltr', lang, 'ubiquity/imported')
181 if ltr == 'default:RTL':
182 Gtk.Widget.set_default_direction(Gtk.TextDirection.RTL)
183 else:
184 Gtk.Widget.set_default_direction(Gtk.TextDirection.LTR)
185
186 if self.only:
187 # The language page for oem-config doesn't have the fancy greeter.
188 return
189
190 # TODO: Cache these.
191 release = misc.get_release()
192 install_medium = misc.get_install_medium()
193 install_medium = i18n.get_string(install_medium, lang)
194 # Set the release name (Ubuntu 10.04) and medium (USB or CD) where
195 # necessary.
196 w = self.try_install_text_label
197 text = i18n.get_string(Gtk.Buildable.get_name(w), lang)
198 text = text.replace('${RELEASE}', release.name)
199 text = text.replace('${MEDIUM}', install_medium)
200 w.set_label(text)
201
202 # Big buttons.
203 for w in (self.try_ubuntu, self.install_ubuntu):
204 text = i18n.get_string(Gtk.Buildable.get_name(w), lang)
205 text = text.replace('${RELEASE}', release.name)
206 text = text.replace('${MEDIUM}', install_medium)
207 w.get_child().set_markup('<span size="x-large">%s</span>' % text)
208
209 # We need to center each button under each image *and* have a homogeous
210 # size between the two buttons.
211 self.try_ubuntu.set_size_request(-1, -1)
212 self.install_ubuntu.set_size_request(-1, -1)
213 try_w = self.try_ubuntu.size_request().width
214 install_w = self.install_ubuntu.size_request().width
215 if try_w > install_w:
216 self.try_ubuntu.set_size_request(try_w, -1)
217 self.install_ubuntu.set_size_request(try_w, -1)
218 elif install_w > try_w:
219 self.try_ubuntu.set_size_request(install_w, -1)
220 self.install_ubuntu.set_size_request(install_w, -1)
221
222 # Make the forward button a consistent size, regardless of its text.
223 install_label = i18n.get_string('install_button', lang)
224 next_button = self.controller._wizard.next
225 next_label = next_button.get_label()
226
227 next_button.set_size_request(-1, -1)
228 next_w = next_button.size_request().width
229 next_button.set_label(install_label)
230 install_w = next_button.size_request().width
231 next_button.set_label(next_label)
232 if next_w > install_w:
233 next_button.set_size_request(next_w, -1)
234 else:
235 next_button.set_size_request(install_w, -1)
236
237 self.update_release_notes_label()
238 for w in self.page.get_children():
239 w.show()
240
241 def plugin_set_online_state(self, state):
242 if self.release_notes_label:
243 if self.timeout_id:
244 GLib.source_remove(self.timeout_id)
245 if state:
246 self.release_notes_label.show()
247 self.timeout_id = GLib.timeout_add(
248 300, self.check_returncode)
249 else:
250 self.release_notes_label.hide()
251
252 def check_returncode(self, *args):
253 if self.wget_retcode is not None or self.wget_proc is None:
254 self.wget_proc = subprocess.Popen(
255 ['wget', '-q', self.WGET_URL, '--timeout=15', '--tries=1',
256 '-O', '/dev/null'])
257 self.wget_retcode = self.wget_proc.poll()
258 if self.wget_retcode is None:
259 return True
260 else:
261 if self.wget_retcode == 0:
262 self.update_installer = True
263 else:
264 self.update_installer = False
265 self.update_release_notes_label()
266 return False
267
268 def update_release_notes_label(self):
269 print("update_release_notes_label()")
270 lang = self.get_language()
271 if not lang:
272 return
273 # strip encoding; we use UTF-8 internally no matter what
274 lang = lang.split('.')[0]
275 # Either leave the release notes label alone (both release notes and a
276 # critical update are available), set it to just the release notes,
277 # just the critical update, or neither, as appropriate.
278 if self.release_notes_label:
279 if self.release_notes_found and self.update_installer:
280 text = i18n.get_string('release_notes_label', lang)
281 self.release_notes_label.set_markup(text)
282 elif self.release_notes_found:
283 text = i18n.get_string('release_notes_only', lang)
284 self.release_notes_label.set_markup(text)
285 elif self.update_installer:
286 text = i18n.get_string('update_installer_only', lang)
287 self.release_notes_label.set_markup(text)
288 else:
289 self.release_notes_label.set_markup('')
290
291 def set_oem_id(self, text):
292 return self.oem_id_entry.set_text(text)
293
294 def get_oem_id(self):
295 return self.oem_id_entry.get_text()
296
297 def on_link_clicked(self, widget, uri):
298 # Connected in glade.
299 lang = self.get_language()
300 if not lang:
301 lang = 'C'
302 lang = lang.split('.')[0] # strip encoding
303 if uri == 'update':
304 if self.updating_installer:
305 return True
306 self.updating_installer = True
307 if not auto_update.update(self.controller._wizard):
308 # no updates, so don't check again
309 if self.release_notes_url:
310 text = i18n.get_string('release_notes_only', lang)
311 self.release_notes_label.set_markup(text)
312 else:
313 self.release_notes_label.hide()
314 self.updating_installer = False
315 elif uri == 'release-notes':
316 uri = self.release_notes_url.replace('${LANG}', lang)
317 subprocess.Popen(['sensible-browser', uri], close_fds=True,
318 preexec_fn=misc.drop_all_privileges)
319 return True
0320
=== added directory 'ubiquity/plugins/kde'
=== added file 'ubiquity/plugins/kde/__init__.py'
=== added file 'ubiquity/plugins/kde/language.py'
--- ubiquity/plugins/kde/language.py 1970-01-01 00:00:00 +0000
+++ ubiquity/plugins/kde/language.py 2013-07-05 16:09:26 +0000
@@ -0,0 +1,237 @@
1import os
2import subprocess
3import syslog
4
5from PyQt4 import uic
6from PyQt4.QtGui import QWidget, QPixmap, QDesktopServices
7from PyQt4.QtCore import QUrl, QTimer, SIGNAL
8
9from ubiquity import auto_update, i18n, misc, plugin
10from ubiquity.misc import drop_privileges_save, regain_privileges_save
11
12from base.language import PageBase
13
14class PageKde(PageBase):
15 plugin_breadcrumb = 'ubiquity/text/breadcrumb_language'
16 plugin_is_language = True
17
18 def __init__(self, controller, *args, **kwargs):
19 self.controller = controller
20 self.wget_retcode = None
21 self.wget_proc = None
22 if self.controller.oem_user_config:
23 self.only = True
24 else:
25 self.only = False
26
27 try:
28 self.page = uic.loadUi('/usr/share/ubiquity/qt/stepLanguage.ui')
29 self.combobox = self.page.language_combobox
30 self.combobox.view().setUniformItemSizes(True)
31 self.combobox.currentIndexChanged[str].connect(
32 self.on_language_selection_changed)
33 if not self.controller.oem_config:
34 self.page.oem_id_label.hide()
35 self.page.oem_id_entry.hide()
36
37 def inst(*args):
38 self.page.try_ubuntu.setEnabled(False)
39 self.controller.go_forward()
40 self.page.install_ubuntu.clicked.connect(inst)
41 self.page.try_ubuntu.clicked.connect(self.on_try_ubuntu_clicked)
42 picture1 = QPixmap(
43 "/usr/share/ubiquity/pixmaps/kubuntu-live-session.png")
44 self.page.image1.setPixmap(picture1)
45 self.page.image1.resize(picture1.size())
46 picture2 = QPixmap(
47 "/usr/share/ubiquity/pixmaps/kubuntu-install.png")
48 self.page.image2.setPixmap(picture2)
49 self.page.image2.resize(picture2.size())
50
51 self.release_notes_url = ''
52 self.update_installer = True
53 self.updating_installer = False
54 if self.controller.oem_config or auto_update.already_updated():
55 self.update_installer = False
56 self.release_notes_found = False
57 try:
58 with open(self.RELEASE_NOTES_URL_PATH) as release_notes:
59 self.release_notes_url = release_notes.read().rstrip('\n')
60 self.release_notes_found = True
61 except (KeyboardInterrupt, SystemExit):
62 raise
63 except:
64 pass
65
66 if self.release_notes_url:
67 self.page.release_notes_label.linkActivated.connect(
68 self.on_release_notes_link)
69 else:
70 self.page.release_notes_label.hide()
71
72 if not 'UBIQUITY_GREETER' in os.environ:
73 self.page.try_ubuntu.hide()
74 self.page.try_install_text_label.hide()
75 self.page.install_ubuntu.hide()
76 self.page.image1.hide()
77 self.page.image2.hide()
78
79 # We do not want to show the yet to be substituted strings
80 # (${MEDIUM}, etc), so don't show the core of the page until
81 # it's ready.
82 self.widgetHidden = []
83 for w in self.page.children():
84 if isinstance(w, QWidget) and not w.isHidden():
85 self.widgetHidden.append(w)
86 w.hide()
87
88 except Exception as e:
89 syslog.syslog('Could not create language page: %s' % e)
90 self.page = None
91
92 self.plugin_widgets = self.page
93
94 @plugin.only_this_page
95 def on_try_ubuntu_clicked(self, *args):
96 if not self.controller.allowed_change_step():
97 # The button's already been clicked once, so stop reacting to it.
98 # LP: #911907.
99 return
100 # Spinning cursor.
101 self.controller.allow_change_step(False)
102 # Queue quit.
103 self.page.install_ubuntu.setEnabled(False)
104 self.controller._wizard.current_page = None
105 self.controller.dbfilter.ok_handler()
106
107 def on_release_notes_link(self, link):
108 lang = self.selected_language()
109 if link == "release-notes":
110 if lang:
111 lang = lang.split('.')[0].lower()
112 url = self.release_notes_url.replace('${LANG}', lang)
113 self.openURL(url)
114 elif link == "update":
115 if self.updating_installer:
116 return
117 self.updating_installer = True
118 if not auto_update.update(self.controller._wizard):
119 # no updates, so don't check again
120 text = i18n.get_string('release_notes_only', lang)
121 self.page.release_notes_label.setText(text)
122 self.updating_installer = False
123
124 def openURL(self, url):
125 # this nonsense is needed because kde doesn't want to be root
126 drop_privileges_save()
127 QDesktopServices.openUrl(QUrl(url))
128 regain_privileges_save()
129
130 def set_language_choices(self, choices, choice_map):
131 PageBase.set_language_choices(self, choices, choice_map)
132 self.combobox.clear()
133 #self.combobox.addItems(choices)
134 for choice in choices:
135 self.combobox.addItem(str(choice))
136
137 def set_language(self, language):
138 index = self.combobox.findText(str(language))
139 if index < 0:
140 self.combobox.addItem("C")
141 else:
142 self.combobox.setCurrentIndex(index)
143
144 if not self.only and 'UBIQUITY_GREETER' in os.environ:
145 self.page.try_ubuntu.setEnabled(True)
146 self.page.install_ubuntu.setEnabled(True)
147
148 def get_language(self):
149 lang = self.selected_language()
150 return lang if lang else 'C'
151
152 def selected_language(self):
153 lang = self.combobox.currentText()
154 if not lang or not hasattr(self, 'language_choice_map'):
155 return None
156 else:
157 return self.language_choice_map[str(lang)][1]
158
159 def on_language_selection_changed(self):
160 lang = self.selected_language()
161 if not lang:
162 return
163 # strip encoding; we use UTF-8 internally no matter what
164 lang = lang.split('.')[0]
165 self.controller.translate(lang)
166 if not self.only:
167 release = misc.get_release()
168 install_medium = misc.get_install_medium()
169 install_medium = i18n.get_string(install_medium, lang)
170 for widget in (self.page.try_install_text_label,
171 self.page.try_ubuntu,
172 self.page.install_ubuntu):
173 text = widget.text()
174 text = text.replace('${RELEASE}', release.name)
175 text = text.replace('${MEDIUM}', install_medium)
176 text = text.replace('Ubuntu', 'Kubuntu')
177 widget.setText(text)
178
179 self.update_release_notes_label()
180 for w in self.widgetHidden:
181 w.show()
182 self.widgetHidden = []
183
184 def plugin_set_online_state(self, state):
185 if self.page.release_notes_label:
186 if state:
187 self.page.release_notes_label.show()
188 QTimer.singleShot(300, self.check_returncode)
189 self.timer = QTimer(self.page)
190 self.timer.connect(
191 self.timer, SIGNAL("timeout()"), self.check_returncode)
192 self.timer.start(300)
193 else:
194 self.page.release_notes_label.hide()
195
196 def check_returncode(self, *args):
197 if self.wget_retcode is not None or self.wget_proc is None:
198 self.wget_proc = subprocess.Popen(
199 ['wget', '-q', self.WGET_URL, '--timeout=15', '--tries=1',
200 '-O', '/dev/null'])
201 self.wget_retcode = self.wget_proc.poll()
202 if self.wget_retcode is None:
203 return True
204 else:
205 if self.wget_retcode == 0:
206 self.update_installer = True
207 else:
208 self.update_installer = False
209 self.update_release_notes_label()
210 self.timer.disconnect(
211 self.timer, SIGNAL("timeout()"), self.check_returncode)
212
213 def update_release_notes_label(self):
214 lang = self.selected_language()
215 if not lang:
216 return
217 # strip encoding; we use UTF-8 internally no matter what
218 lang = lang.split('.')[0]
219 # Either leave the release notes label alone (both release notes and a
220 # critical update are available), set it to just the release notes,
221 # just the critical update, or neither, as appropriate.
222 if self.page.release_notes_label:
223 if self.release_notes_found and self.update_installer:
224 text = i18n.get_string('release_notes_label', lang)
225 self.page.release_notes_label.setText(text)
226 elif self.release_notes_found:
227 text = i18n.get_string('release_notes_only', lang)
228 self.page.release_notes_label.setText(text)
229 elif self.update_installer:
230 text = i18n.get_string('update_installer_only', lang)
231 self.page.release_notes_label.setText(text)
232
233 def set_oem_id(self, text):
234 return self.page.oem_id_entry.setText(text)
235
236 def get_oem_id(self):
237 return str(self.page.oem_id_entry.text())
0238
=== modified file 'ubiquity/plugins/ubi-language.py'
--- ubiquity/plugins/ubi-language.py 2013-04-28 13:46:10 +0000
+++ ubiquity/plugins/ubi-language.py 2013-07-05 16:09:26 +0000
@@ -27,590 +27,20 @@
2727
28from ubiquity import auto_update, i18n, misc, osextras, plugin28from ubiquity import auto_update, i18n, misc, osextras, plugin
2929
30from base.language import PageBase
3031
31NAME = 'language'32NAME = 'language'
32AFTER = None33AFTER = None
33WEIGHT = 1034WEIGHT = 10
3435
35try:36def PageGtk(controller, *args, **kwargs):
36 import lsb_release37 import gtk.language
37 _ver = lsb_release.get_distro_information()['RELEASE']38 return gtk.language.PageGtk(controller, *args, **kwargs)
38except:39
39 _ver = '12.04'40
40_wget_url = 'http://changelogs.ubuntu.com/ubiquity/%s-update-available' % _ver41def PageKde(controller, *args, **kwargs):
4142 import kde.language
42_release_notes_url_path = '/cdrom/.disk/release_notes_url'43 return kde.language.PageKde(controller, *args, **kwargs)
43
44
45class PageBase(plugin.PluginUI):
46 def set_language_choices(self, unused_choices, choice_map):
47 """Called with language choices and a map to localised names."""
48 self.language_choice_map = dict(choice_map)
49
50 def set_language(self, language):
51 """Set the current selected language."""
52 pass
53
54 def get_language(self):
55 """Get the current selected language."""
56 return 'C'
57
58 def set_oem_id(self, text):
59 pass
60
61 def get_oem_id(self):
62 return ''
63
64
65class PageGtk(PageBase):
66 plugin_is_language = True
67 plugin_title = 'ubiquity/text/language_heading_label'
68
69 def __init__(self, controller, *args, **kwargs):
70 self.controller = controller
71 self.timeout_id = None
72 self.wget_retcode = None
73 self.wget_proc = None
74 if self.controller.oem_user_config:
75 ui_file = 'stepLanguageOnly.ui'
76 self.only = True
77 else:
78 ui_file = 'stepLanguage.ui'
79 self.only = False
80 from gi.repository import Gtk
81 builder = Gtk.Builder()
82 builder.add_from_file(os.path.join(
83 os.environ['UBIQUITY_GLADE'], ui_file))
84 builder.connect_signals(self)
85 self.controller.add_builder(builder)
86 self.page = builder.get_object('stepLanguage')
87 self.iconview = builder.get_object('language_iconview')
88 self.treeview = builder.get_object('language_treeview')
89 self.oem_id_entry = builder.get_object('oem_id_entry')
90 if self.controller.oem_config:
91 builder.get_object('oem_id_vbox').show()
92
93 self.release_notes_url = ''
94 self.update_installer = True
95 self.updating_installer = False
96 self.release_notes_label = builder.get_object('release_notes_label')
97 self.release_notes_found = False
98 if self.release_notes_label:
99 self.release_notes_label.connect(
100 'activate-link', self.on_link_clicked)
101 if self.controller.oem_config or auto_update.already_updated():
102 self.update_installer = False
103 try:
104 with open(_release_notes_url_path) as release_notes:
105 self.release_notes_url = release_notes.read().rstrip('\n')
106 self.release_notes_found = True
107 except (KeyboardInterrupt, SystemExit):
108 raise
109 except:
110 pass
111 self.install_ubuntu = builder.get_object('install_ubuntu')
112 self.try_ubuntu = builder.get_object('try_ubuntu')
113 if not self.only:
114 if not 'UBIQUITY_GREETER' in os.environ:
115 choice_section_vbox = builder.get_object('choice_section_vbox')
116 choice_section_vbox and choice_section_vbox.hide()
117 else:
118 def inst(*args):
119 self.try_ubuntu.set_sensitive(False)
120 self.controller.go_forward()
121 self.install_ubuntu.connect('clicked', inst)
122 self.try_ubuntu.connect('clicked', self.on_try_ubuntu_clicked)
123 self.try_install_text_label = builder.get_object(
124 'try_install_text_label')
125 # We do not want to show the yet to be substituted strings
126 # (${MEDIUM}, etc), so don't show the core of the page until
127 # it's ready.
128 for w in self.page.get_children():
129 w.hide()
130 self.plugin_widgets = self.page
131
132 @plugin.only_this_page
133 def on_try_ubuntu_clicked(self, *args):
134 if not self.controller.allowed_change_step():
135 # The button's already been clicked once, so stop reacting to it.
136 # LP: #911907.
137 return
138 # Spinning cursor.
139 self.controller.allow_change_step(False)
140 # Queue quit.
141 self.install_ubuntu.set_sensitive(False)
142 self.controller._wizard.current_page = None
143 self.controller.dbfilter.ok_handler()
144
145 def set_language_choices(self, choices, choice_map):
146 from gi.repository import Gtk, GObject
147 PageBase.set_language_choices(self, choices, choice_map)
148 list_store = Gtk.ListStore.new([GObject.TYPE_STRING])
149 longest_length = 0
150 longest = ''
151 for choice in choices:
152 list_store.append([choice])
153 # Work around the fact that GtkIconView wraps at 50px or the width
154 # of the icon, which is nonexistent here. See adjust_wrap_width ()
155 # in gtkiconview.c for the details.
156 if self.only:
157 length = len(choice)
158 if length > longest_length:
159 longest_length = length
160 longest = choice
161 # Support both iconview and treeview
162 if self.only:
163 self.iconview.set_model(list_store)
164 self.iconview.set_text_column(0)
165 pad = self.iconview.get_property('item-padding')
166 layout = self.iconview.create_pango_layout(longest)
167 self.iconview.set_item_width(layout.get_pixel_size()[0] + pad * 2)
168 else:
169 if len(self.treeview.get_columns()) < 1:
170 column = Gtk.TreeViewColumn(
171 None, Gtk.CellRendererText(), text=0)
172 column.set_sizing(Gtk.TreeViewColumnSizing.GROW_ONLY)
173 self.treeview.append_column(column)
174 selection = self.treeview.get_selection()
175 selection.connect(
176 'changed', self.on_language_selection_changed)
177 self.treeview.set_model(list_store)
178
179 def set_language(self, language):
180 # Support both iconview and treeview
181 if self.only:
182 model = self.iconview.get_model()
183 iterator = model.iter_children(None)
184 while iterator is not None:
185 if misc.utf8(model.get_value(iterator, 0)) == language:
186 path = model.get_path(iterator)
187 self.iconview.select_path(path)
188 self.iconview.scroll_to_path(path, True, 0.5, 0.5)
189 break
190 iterator = model.iter_next(iterator)
191 else:
192 model = self.treeview.get_model()
193 iterator = model.iter_children(None)
194 while iterator is not None:
195 if misc.utf8(model.get_value(iterator, 0)) == language:
196 path = model.get_path(iterator)
197 self.treeview.get_selection().select_path(path)
198 self.treeview.scroll_to_cell(
199 path, use_align=True, row_align=0.5)
200 break
201 iterator = model.iter_next(iterator)
202
203 if not self.only and 'UBIQUITY_GREETER' in os.environ:
204 self.try_ubuntu.set_sensitive(True)
205 self.install_ubuntu.set_sensitive(True)
206
207 def get_language(self):
208 # Support both iconview and treeview
209 if self.only:
210 model = self.iconview.get_model()
211 items = self.iconview.get_selected_items()
212 if not items:
213 return None
214 iterator = model.get_iter(items[0])
215 else:
216 selection = self.treeview.get_selection()
217 (model, iterator) = selection.get_selected()
218 if iterator is None:
219 return None
220 else:
221 value = misc.utf8(model.get_value(iterator, 0))
222 return self.language_choice_map[value][1]
223
224 def on_language_activated(self, *args, **kwargs):
225 self.controller.go_forward()
226
227 def on_language_selection_changed(self, *args, **kwargs):
228 lang = self.get_language()
229 self.controller.allow_go_forward(bool(lang))
230 if not lang:
231 return
232 if 'UBIQUITY_GREETER' in os.environ:
233 misc.set_indicator_keymaps(lang)
234 # strip encoding; we use UTF-8 internally no matter what
235 lang = lang.split('.')[0]
236 self.controller.translate(lang)
237 from gi.repository import Gtk
238 ltr = i18n.get_string('default-ltr', lang, 'ubiquity/imported')
239 if ltr == 'default:RTL':
240 Gtk.Widget.set_default_direction(Gtk.TextDirection.RTL)
241 else:
242 Gtk.Widget.set_default_direction(Gtk.TextDirection.LTR)
243
244 if self.only:
245 # The language page for oem-config doesn't have the fancy greeter.
246 return
247
248 # TODO: Cache these.
249 release = misc.get_release()
250 install_medium = misc.get_install_medium()
251 install_medium = i18n.get_string(install_medium, lang)
252 # Set the release name (Ubuntu 10.04) and medium (USB or CD) where
253 # necessary.
254 w = self.try_install_text_label
255 text = i18n.get_string(Gtk.Buildable.get_name(w), lang)
256 text = text.replace('${RELEASE}', release.name)
257 text = text.replace('${MEDIUM}', install_medium)
258 w.set_label(text)
259
260 # Big buttons.
261 for w in (self.try_ubuntu, self.install_ubuntu):
262 text = i18n.get_string(Gtk.Buildable.get_name(w), lang)
263 text = text.replace('${RELEASE}', release.name)
264 text = text.replace('${MEDIUM}', install_medium)
265 w.get_child().set_markup('<span size="x-large">%s</span>' % text)
266
267 # We need to center each button under each image *and* have a homogeous
268 # size between the two buttons.
269 self.try_ubuntu.set_size_request(-1, -1)
270 self.install_ubuntu.set_size_request(-1, -1)
271 try_w = self.try_ubuntu.size_request().width
272 install_w = self.install_ubuntu.size_request().width
273 if try_w > install_w:
274 self.try_ubuntu.set_size_request(try_w, -1)
275 self.install_ubuntu.set_size_request(try_w, -1)
276 elif install_w > try_w:
277 self.try_ubuntu.set_size_request(install_w, -1)
278 self.install_ubuntu.set_size_request(install_w, -1)
279
280 # Make the forward button a consistent size, regardless of its text.
281 install_label = i18n.get_string('install_button', lang)
282 next_button = self.controller._wizard.next
283 next_label = next_button.get_label()
284
285 next_button.set_size_request(-1, -1)
286 next_w = next_button.size_request().width
287 next_button.set_label(install_label)
288 install_w = next_button.size_request().width
289 next_button.set_label(next_label)
290 if next_w > install_w:
291 next_button.set_size_request(next_w, -1)
292 else:
293 next_button.set_size_request(install_w, -1)
294
295 self.update_release_notes_label()
296 for w in self.page.get_children():
297 w.show()
298
299 def plugin_set_online_state(self, state):
300 from gi.repository import GLib
301 if self.release_notes_label:
302 if self.timeout_id:
303 GLib.source_remove(self.timeout_id)
304 if state:
305 self.release_notes_label.show()
306 self.timeout_id = GLib.timeout_add(
307 300, self.check_returncode)
308 else:
309 self.release_notes_label.hide()
310
311 def check_returncode(self, *args):
312 import subprocess
313 if self.wget_retcode is not None or self.wget_proc is None:
314 self.wget_proc = subprocess.Popen(
315 ['wget', '-q', _wget_url, '--timeout=15', '--tries=1',
316 '-O', '/dev/null'])
317 self.wget_retcode = self.wget_proc.poll()
318 if self.wget_retcode is None:
319 return True
320 else:
321 if self.wget_retcode == 0:
322 self.update_installer = True
323 else:
324 self.update_installer = False
325 self.update_release_notes_label()
326 return False
327
328 def update_release_notes_label(self):
329 print("update_release_notes_label()")
330 lang = self.get_language()
331 if not lang:
332 return
333 # strip encoding; we use UTF-8 internally no matter what
334 lang = lang.split('.')[0]
335 # Either leave the release notes label alone (both release notes and a
336 # critical update are available), set it to just the release notes,
337 # just the critical update, or neither, as appropriate.
338 if self.release_notes_label:
339 if self.release_notes_found and self.update_installer:
340 text = i18n.get_string('release_notes_label', lang)
341 self.release_notes_label.set_markup(text)
342 elif self.release_notes_found:
343 text = i18n.get_string('release_notes_only', lang)
344 self.release_notes_label.set_markup(text)
345 elif self.update_installer:
346 text = i18n.get_string('update_installer_only', lang)
347 self.release_notes_label.set_markup(text)
348 else:
349 self.release_notes_label.set_markup('')
350
351 def set_oem_id(self, text):
352 return self.oem_id_entry.set_text(text)
353
354 def get_oem_id(self):
355 return self.oem_id_entry.get_text()
356
357 def on_link_clicked(self, widget, uri):
358 # Connected in glade.
359 lang = self.get_language()
360 if not lang:
361 lang = 'C'
362 lang = lang.split('.')[0] # strip encoding
363 if uri == 'update':
364 if self.updating_installer:
365 return True
366 self.updating_installer = True
367 if not auto_update.update(self.controller._wizard):
368 # no updates, so don't check again
369 if self.release_notes_url:
370 text = i18n.get_string('release_notes_only', lang)
371 self.release_notes_label.set_markup(text)
372 else:
373 self.release_notes_label.hide()
374 self.updating_installer = False
375 elif uri == 'release-notes':
376 import subprocess
377 uri = self.release_notes_url.replace('${LANG}', lang)
378 subprocess.Popen(['sensible-browser', uri], close_fds=True,
379 preexec_fn=misc.drop_all_privileges)
380 return True
381
382
383class PageKde(PageBase):
384 plugin_breadcrumb = 'ubiquity/text/breadcrumb_language'
385 plugin_is_language = True
386
387 def __init__(self, controller, *args, **kwargs):
388 self.controller = controller
389 self.wget_retcode = None
390 self.wget_proc = None
391 if self.controller.oem_user_config:
392 self.only = True
393 else:
394 self.only = False
395
396 try:
397 from PyQt4 import uic
398 from PyQt4.QtGui import QWidget, QPixmap
399 self.page = uic.loadUi('/usr/share/ubiquity/qt/stepLanguage.ui')
400 self.combobox = self.page.language_combobox
401 self.combobox.currentIndexChanged[str].connect(
402 self.on_language_selection_changed)
403 if not self.controller.oem_config:
404 self.page.oem_id_label.hide()
405 self.page.oem_id_entry.hide()
406
407 def inst(*args):
408 self.page.try_ubuntu.setEnabled(False)
409 self.controller.go_forward()
410 self.page.install_ubuntu.clicked.connect(inst)
411 self.page.try_ubuntu.clicked.connect(self.on_try_ubuntu_clicked)
412 picture1 = QPixmap(
413 "/usr/share/ubiquity/pixmaps/kubuntu-live-session.png")
414 self.page.image1.setPixmap(picture1)
415 self.page.image1.resize(picture1.size())
416 picture2 = QPixmap(
417 "/usr/share/ubiquity/pixmaps/kubuntu-install.png")
418 self.page.image2.setPixmap(picture2)
419 self.page.image2.resize(picture2.size())
420
421 self.release_notes_url = ''
422 self.update_installer = True
423 self.updating_installer = False
424 if self.controller.oem_config or auto_update.already_updated():
425 self.update_installer = False
426 self.release_notes_found = False
427 try:
428 with open(_release_notes_url_path) as release_notes:
429 self.release_notes_url = release_notes.read().rstrip('\n')
430 self.release_notes_found = True
431 except (KeyboardInterrupt, SystemExit):
432 raise
433 except:
434 pass
435
436 if self.release_notes_url:
437 self.page.release_notes_label.linkActivated.connect(
438 self.on_release_notes_link)
439 else:
440 self.page.release_notes_label.hide()
441
442 if not 'UBIQUITY_GREETER' in os.environ:
443 self.page.try_ubuntu.hide()
444 self.page.try_install_text_label.hide()
445 self.page.install_ubuntu.hide()
446 self.page.image1.hide()
447 self.page.image2.hide()
448
449 # We do not want to show the yet to be substituted strings
450 # (${MEDIUM}, etc), so don't show the core of the page until
451 # it's ready.
452 self.widgetHidden = []
453 for w in self.page.children():
454 if isinstance(w, QWidget) and not w.isHidden():
455 self.widgetHidden.append(w)
456 w.hide()
457
458 except Exception as e:
459 self.debug('Could not create language page: %s', e)
460 self.page = None
461
462 self.plugin_widgets = self.page
463
464 @plugin.only_this_page
465 def on_try_ubuntu_clicked(self, *args):
466 if not self.controller.allowed_change_step():
467 # The button's already been clicked once, so stop reacting to it.
468 # LP: #911907.
469 return
470 # Spinning cursor.
471 self.controller.allow_change_step(False)
472 # Queue quit.
473 self.page.install_ubuntu.setEnabled(False)
474 self.controller._wizard.current_page = None
475 self.controller.dbfilter.ok_handler()
476
477 def on_release_notes_link(self, link):
478 lang = self.selected_language()
479 if link == "release-notes":
480 if lang:
481 lang = lang.split('.')[0].lower()
482 url = self.release_notes_url.replace('${LANG}', lang)
483 self.openURL(url)
484 elif link == "update":
485 if self.updating_installer:
486 return
487 self.updating_installer = True
488 if not auto_update.update(self.controller._wizard):
489 # no updates, so don't check again
490 text = i18n.get_string('release_notes_only', lang)
491 self.page.release_notes_label.setText(text)
492 self.updating_installer = False
493
494 def openURL(self, url):
495 from PyQt4.QtGui import QDesktopServices
496 from PyQt4.QtCore import QUrl
497 from ubiquity.misc import drop_privileges_save, regain_privileges_save
498
499 # this nonsense is needed because kde doesn't want to be root
500 drop_privileges_save()
501 QDesktopServices.openUrl(QUrl(url))
502 regain_privileges_save()
503
504 def set_language_choices(self, choices, choice_map):
505 PageBase.set_language_choices(self, choices, choice_map)
506 self.combobox.clear()
507 for choice in choices:
508 self.combobox.addItem(str(choice))
509
510 def set_language(self, language):
511 index = self.combobox.findText(str(language))
512 if index < 0:
513 self.combobox.addItem("C")
514 else:
515 self.combobox.setCurrentIndex(index)
516
517 if not self.only and 'UBIQUITY_GREETER' in os.environ:
518 self.page.try_ubuntu.setEnabled(True)
519 self.page.install_ubuntu.setEnabled(True)
520
521 def get_language(self):
522 lang = self.selected_language()
523 return lang if lang else 'C'
524
525 def selected_language(self):
526 lang = self.combobox.currentText()
527 if not lang or not hasattr(self, 'language_choice_map'):
528 return None
529 else:
530 return self.language_choice_map[str(lang)][1]
531
532 def on_language_selection_changed(self):
533 lang = self.selected_language()
534 if not lang:
535 return
536 # strip encoding; we use UTF-8 internally no matter what
537 lang = lang.split('.')[0]
538 self.controller.translate(lang)
539 if not self.only:
540 release = misc.get_release()
541 install_medium = misc.get_install_medium()
542 install_medium = i18n.get_string(install_medium, lang)
543 for widget in (self.page.try_install_text_label,
544 self.page.try_ubuntu,
545 self.page.install_ubuntu):
546 text = widget.text()
547 text = text.replace('${RELEASE}', release.name)
548 text = text.replace('${MEDIUM}', install_medium)
549 text = text.replace('Ubuntu', 'Kubuntu')
550 widget.setText(text)
551
552 self.update_release_notes_label()
553 for w in self.widgetHidden:
554 w.show()
555 self.widgetHidden = []
556
557 def plugin_set_online_state(self, state):
558 from PyQt4.QtCore import QTimer, SIGNAL
559 if self.page.release_notes_label:
560 if state:
561 self.page.release_notes_label.show()
562 QTimer.singleShot(300, self.check_returncode)
563 self.timer = QTimer(self.page)
564 self.timer.connect(
565 self.timer, SIGNAL("timeout()"), self.check_returncode)
566 self.timer.start(300)
567 else:
568 self.page.release_notes_label.hide()
569
570 def check_returncode(self, *args):
571 import subprocess
572 from PyQt4.QtCore import SIGNAL
573 if self.wget_retcode is not None or self.wget_proc is None:
574 self.wget_proc = subprocess.Popen(
575 ['wget', '-q', _wget_url, '--timeout=15', '--tries=1',
576 '-O', '/dev/null'])
577 self.wget_retcode = self.wget_proc.poll()
578 if self.wget_retcode is None:
579 return True
580 else:
581 if self.wget_retcode == 0:
582 self.update_installer = True
583 else:
584 self.update_installer = False
585 self.update_release_notes_label()
586 self.timer.disconnect(
587 self.timer, SIGNAL("timeout()"), self.check_returncode)
588
589 def update_release_notes_label(self):
590 lang = self.selected_language()
591 if not lang:
592 return
593 # strip encoding; we use UTF-8 internally no matter what
594 lang = lang.split('.')[0]
595 # Either leave the release notes label alone (both release notes and a
596 # critical update are available), set it to just the release notes,
597 # just the critical update, or neither, as appropriate.
598 if self.page.release_notes_label:
599 if self.release_notes_found and self.update_installer:
600 text = i18n.get_string('release_notes_label', lang)
601 self.page.release_notes_label.setText(text)
602 elif self.release_notes_found:
603 text = i18n.get_string('release_notes_only', lang)
604 self.page.release_notes_label.setText(text)
605 elif self.update_installer:
606 text = i18n.get_string('update_installer_only', lang)
607 self.page.release_notes_label.setText(text)
608
609 def set_oem_id(self, text):
610 return self.page.oem_id_entry.setText(text)
611
612 def get_oem_id(self):
613 return str(self.page.oem_id_entry.text())
61444
61545
616class PageDebconf(PageBase):46class PageDebconf(PageBase):

Subscribers

People subscribed via source and target branches

to status/vote changes: