Merge ~nteodosio/update-manager:jammy-ua into update-manager:ubuntu/jammy

Proposed by Nathan Teodosio
Status: Merged
Approved by: Sebastien Bacher
Approved revision: a57881918b0d905272bdcb967ce7248ced4fafc5
Merged at revision: a57881918b0d905272bdcb967ce7248ced4fafc5
Proposed branch: ~nteodosio/update-manager:jammy-ua
Merge into: update-manager:ubuntu/jammy
Diff against target: 644 lines (+165/-155)
6 files modified
UpdateManager/Core/UpdateList.py (+17/-7)
UpdateManager/Core/utils.py (+10/-0)
UpdateManager/UpdateManager.py (+21/-19)
UpdateManager/UpdatesAvailable.py (+59/-24)
data/gtkbuilder/UpdateManager.ui (+45/-105)
debian/changelog (+13/-0)
Reviewer Review Type Date Requested Status
Sebastien Bacher Approve
Robert Ancell (community) Approve
Ubuntu Core Development Team Pending
Review via email: mp+450056@code.launchpad.net

Description of the change

PPA can be tested in https://launchpad.net/~nteodosio/+archive/ubuntu/ubuntu-pro.

Internal discussion in UDENG-361.

To post a comment you must log in.
Revision history for this message
Robert Ancell (robert-ancell) wrote :

Looks generally good, just a few comments about some minor stuff.

review: Needs Fixing
Revision history for this message
Nathan Teodosio (nteodosio) wrote :

Thank you for the review, Robert!

I addressed your comments and also removed pkgsystem_unlock call, which was accidentally merged from the Bionic changes.

Revision history for this message
Robert Ancell (robert-ancell) wrote :

LGTM

review: Approve
Revision history for this message
Sebastien Bacher (seb128) wrote (last edit ):

Thanks, I'm testing the deb from https://launchpad.net/~nteodosio/+archive/ubuntu/ubuntu-pro/+build/26458291 , some notes

- I don't see the news sections, I guess I needed a newer ubuntu-advantage-tools, should we update the depends?

- clicking on 'settings...' triggers an error dialog

Traceback (most recent call last):
  File "/usr/lib/python3/dist-packages/UpdateManager/Dialogs.py", line 118, in <lambda>
    button.connect("clicked", lambda x: callback())
  File "/usr/lib/python3/dist-packages/UpdateManager/Dialogs.py", line 133, in on_settings_button_clicked
    self.window_main.show_settings(2)
  File "/usr/lib/python3/dist-packages/UpdateManager/UpdateManager.py", line 203, in show_settings
    apt_pkg.pkgsystem_unlock()
NameError: name 'apt_pkg' is not defined

Revision history for this message
Nathan Teodosio (nteodosio) wrote :

 > - I don't see the news sections, I guess I needed a newer
ubuntu-advantage-tools, should we update the depends?

Last time I checked there were no valid news, and this remains so:

   curl https://motd.ubuntu.com/aptnews.json

Messages expire after one month.

About the settings error, I'm checking that, seen that before.

Revision history for this message
Sebastien Bacher (seb128) wrote :

Thanks, the new build fixes the settings issue indeed. The news isn't showing indeed but I was able to test using a local server configuration

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1diff --git a/UpdateManager/Core/UpdateList.py b/UpdateManager/Core/UpdateList.py
2index 6979050..8d30317 100644
3--- a/UpdateManager/Core/UpdateList.py
4+++ b/UpdateManager/Core/UpdateList.py
5@@ -221,6 +221,7 @@ class UpdateList():
6 self.kernel_autoremove_groups = []
7 self.duplicate_groups = []
8 self.ubuntu_pro_groups = []
9+ self.ubuntu_pro_fake_groups = []
10 self.num_updates = 0
11 self.random = random.Random()
12 self.ignored_phased_updates = []
13@@ -477,6 +478,7 @@ class UpdateList():
14 self.distUpgradeWouldDelete = cache.saveDistUpgrade()
15
16 oem_pkgs = []
17+ pro_pkgs = []
18 security_pkgs = []
19 upgrade_pkgs = []
20 kernel_autoremove_pkgs = []
21@@ -508,9 +510,13 @@ class UpdateList():
22 def mark_delete(self):
23 pass
24 fake_ua_packages = []
25- for (package_name, version, size) in ua_security_packages:
26- fake_ua_packages.append(FakeUbuntuProPackage(package_name,
27- version, size))
28+ ua_packages_names = []
29+ for (package_name, version, size, downloadable) in ua_security_packages:
30+ if downloadable:
31+ ua_packages_names.append(package_name)
32+ else:
33+ fake_ua_packages.append(FakeUbuntuProPackage(package_name,
34+ version, size))
35
36 # Find all upgradable packages
37 for pkg in cache:
38@@ -533,6 +539,9 @@ class UpdateList():
39
40 if fnmatch.fnmatch(pkg.name, 'oem-*-meta'):
41 oem_pkgs.append(pkg)
42+ comes_from_pro = pkg.name in ua_packages_names
43+ if comes_from_pro:
44+ pro_pkgs.append(pkg)
45 elif is_security_update:
46 security_pkgs.append(pkg)
47 else:
48@@ -561,11 +570,10 @@ class UpdateList():
49 for pkg in self.ignored_phased_updates:
50 pkg.mark_keep()
51
52- if security_pkgs or upgrade_pkgs:
53+ if security_pkgs or upgrade_pkgs or pro_pkgs:
54 # There's updates available. Initiate the desktop file cache.
55 pkg_names = [p.name for p in
56- security_pkgs + upgrade_pkgs
57- + kernel_autoremove_pkgs + duplicate_pkgs]
58+ pro_pkgs + security_pkgs + upgrade_pkgs + kernel_autoremove_pkgs + duplicate_pkgs]
59 self._populate_desktop_cache(pkg_names)
60 self.oem_groups = self._make_groups(cache, oem_pkgs,
61 eventloop_callback)
62@@ -577,5 +585,7 @@ class UpdateList():
63 cache, kernel_autoremove_pkgs, eventloop_callback, True)
64 self.duplicate_groups = self._make_groups(
65 cache, duplicate_pkgs, eventloop_callback, True)
66- self.ubuntu_pro_groups = self._make_groups(
67+ self.ubuntu_pro_fake_groups = self._make_groups(
68 cache, fake_ua_packages, eventloop_callback, sensitive=False)
69+ self.ubuntu_pro_groups = self._make_groups(
70+ cache, pro_pkgs, eventloop_callback)
71diff --git a/UpdateManager/Core/utils.py b/UpdateManager/Core/utils.py
72index 67f96c5..9ccdad5 100644
73--- a/UpdateManager/Core/utils.py
74+++ b/UpdateManager/Core/utils.py
75@@ -78,6 +78,16 @@ class ExecutionTime(object):
76 print("%s: %s" % (self.info, time.time() - self.now))
77
78
79+class SoftwarePropertiesPage():
80+ ubuntu_software = 0
81+ other_software = 1
82+ updates = 2
83+ authentication = 3
84+ additional_drivers = 4
85+ developer_options = 5
86+ ubuntu_pro = 6
87+
88+
89 def get_string_with_no_auth_from_source_entry(entry):
90 tmp = copy(entry)
91 url_parts = urlsplit(tmp.uri)
92diff --git a/UpdateManager/UpdateManager.py b/UpdateManager/UpdateManager.py
93index b3920b1..259c0e6 100644
94--- a/UpdateManager/UpdateManager.py
95+++ b/UpdateManager/UpdateManager.py
96@@ -65,7 +65,7 @@ from .Core.AlertWatcher import AlertWatcher
97 from .Core.MyCache import MyCache
98 from .Core.roam import NetworkManagerHelper
99 from .Core.UpdateList import UpdateList
100-from .Core.utils import get_arch, get_dist
101+from .Core.utils import get_arch, get_dist, SoftwarePropertiesPage
102 from .backend import (InstallBackend,
103 get_backend)
104
105@@ -198,9 +198,9 @@ class UpdateManager(Gtk.Window):
106 self._start_pane(None)
107 sys.exit(0)
108
109- def show_settings(self):
110+ def show_settings(self, page_number = SoftwarePropertiesPage.updates):
111 cmd = ["/usr/bin/software-properties-gtk",
112- "--open-tab", "2"]
113+ "--open-tab", str(page_number)]
114
115 if "WAYLAND_DISPLAY" not in os.environ:
116 cmd += ["--toplevel", "%s" % self.get_window().get_xid()]
117@@ -284,30 +284,19 @@ class UpdateManager(Gtk.Window):
118 time.sleep(0.05)
119 s = json.load(p.stdout)
120 for package in s.get('packages', []):
121+ if package.get('service_name', '') == 'standard-security': continue
122 status = package.get('status', '')
123- if status == 'pending_attach':
124+ if status == 'pending_attach' or status == 'pending_enable' or status == 'upgrade_available':
125 name = package.get('package', '')
126 version = package.get('version', '')
127 size = package.get('download_size', 0)
128- self.ua_security_packages.append((name, version, size))
129+ downloadable = status == 'upgrade_available'
130+ self.ua_security_packages.append((name, version, size, downloadable))
131
132 def _make_available_pane(self, install_count, need_reboot=False,
133 cancelled_update=False, error_occurred=False):
134 self._check_hwe_support_status()
135- if install_count == 0:
136- # Need Restart > New Release > No Updates
137- if need_reboot:
138- return NeedRestartDialog(self)
139- dist_upgrade = self._check_meta_release()
140- if dist_upgrade:
141- return dist_upgrade
142- elif cancelled_update:
143- return StoppedUpdatesDialog(self)
144- elif self.hwe_replacement_packages:
145- return HWEUpgradeDialog(self)
146- else:
147- return NoUpdatesDialog(self, error_occurred=error_occurred)
148- else:
149+ if install_count != 0 or len(self.ua_security_packages) > 0:
150 header = None
151 desc = None
152 if error_occurred:
153@@ -320,6 +309,19 @@ class UpdateManager(Gtk.Window):
154 elif self.hwe_replacement_packages:
155 return HWEUpgradeDialog(self)
156 return UpdatesAvailable(self, header, desc, need_reboot)
157+ else:
158+ # Need Restart > New Release > No Updates
159+ if need_reboot:
160+ return NeedRestartDialog(self)
161+ dist_upgrade = self._check_meta_release()
162+ if dist_upgrade:
163+ return dist_upgrade
164+ elif cancelled_update:
165+ return StoppedUpdatesDialog(self)
166+ elif self.hwe_replacement_packages:
167+ return HWEUpgradeDialog(self)
168+ else:
169+ return NoUpdatesDialog(self, error_occurred=error_occurred)
170
171 def start_error(self, update_and_retry, header, desc):
172 if update_and_retry:
173diff --git a/UpdateManager/UpdatesAvailable.py b/UpdateManager/UpdatesAvailable.py
174index 78bd365..add06fe 100644
175--- a/UpdateManager/UpdatesAvailable.py
176+++ b/UpdateManager/UpdatesAvailable.py
177@@ -55,7 +55,7 @@ import threading
178 from gettext import gettext as _
179 from gettext import ngettext
180
181-from .Core.utils import humanize_size
182+from .Core.utils import humanize_size, SoftwarePropertiesPage
183 from .Core.AlertWatcher import AlertWatcher
184 from .Core.UpdateList import UpdateSystemGroup
185 from .Dialogs import InternalDialog
186@@ -250,16 +250,21 @@ class UpdatesAvailable(InternalDialog):
187 self.add_settings_button()
188 self.button_close = self.add_button(Gtk.STOCK_CANCEL,
189 self.window_main.close)
190+ self.button_pro = self.add_button(_("Enable Ubuntu Pro..."),
191+ self.on_button_pro_clicked)
192 self.button_install = self.add_button(_("Install Now"),
193 self.on_button_install_clicked)
194 self.focus_button = self.button_install
195
196 # create text view
197 self.textview_changes = ChangelogViewer()
198+ self.textview_changes.set_wrap_mode(Gtk.WrapMode.WORD)
199 self.textview_changes.show()
200 self.scrolledwindow_changes.add(self.textview_changes)
201 changes_buffer = self.textview_changes.get_buffer()
202 changes_buffer.create_tag("versiontag", weight=Pango.Weight.BOLD)
203+ changes_buffer.create_tag("changestag", weight=Pango.Weight.BOLD)
204+ changes_buffer.create_tag("descriptiontag", weight=Pango.Weight.BOLD)
205
206 # the treeview (move into it's own code!)
207 self.store = Gtk.TreeStore(str, GObject.TYPE_PYOBJECT, str, bool, bool)
208@@ -347,7 +352,6 @@ class UpdatesAvailable(InternalDialog):
209 self.expander_details.connect("activate", self.pre_activate_details)
210 self.expander_details.connect("notify::expanded",
211 self.activate_details)
212- self.expander_desc.connect("notify::expanded", self.activate_desc)
213
214 # If auto-updates are on, change cancel label
215 self.notifier_settings = Gio.Settings.new("com.ubuntu.update-notifier")
216@@ -363,6 +367,16 @@ class UpdatesAvailable(InternalDialog):
217 self.alert_watcher.connect("network-3g-alert",
218 self._on_network_3g_alert)
219
220+ try:
221+ from uaclient.api.u.apt_news.current_news.v1 import current_news
222+ apt_news = current_news().current_news
223+ except ImportError:
224+ pro_client_apt_news_api_supported = False
225+ apt_news = self._get_apt_news("/var/lib/ubuntu-advantage/messages/apt-news")
226+ if apt_news:
227+ self.news.get_buffer().set_text(apt_news)
228+ self.expander_news.set_visible(True)
229+
230 def stop(self):
231 InternalDialog.stop(self)
232 self._save_state()
233@@ -508,8 +522,16 @@ class UpdatesAvailable(InternalDialog):
234
235 renderer.set_property("markup", markup)
236
237- def set_changes_buffer(self, changes_buffer, text, name, srcpkg):
238- changes_buffer.set_text("")
239+ def set_changes_buffer(self, changes_buffer, long_desc, text, name, srcpkg):
240+ changes_buffer.set_text("") # Clear "downloading list of changes..."
241+
242+ # Write the technical description section
243+ changes_buffer.insert_with_tags_by_name(changes_buffer.get_end_iter(),
244+ "Technical description\n",
245+ "descriptiontag")
246+ changes_buffer.insert(changes_buffer.get_end_iter(), long_desc + "\n\n")
247+
248+ # Write the changes section
249 lines = text.split("\n")
250 if len(lines) == 1:
251 changes_buffer.set_text(text)
252@@ -521,12 +543,16 @@ class UpdatesAvailable(InternalDialog):
253 r'^%s \((.*)\)(.*)\;.*$' % re.escape(srcpkg), line)
254 #bullet_match = re.match("^.*[\*-]", line)
255 author_match = re.match("^.*--.*<.*@.*>.*$", line)
256+ changes_match = re.match(r'^Changes for [^ ]+ versions:$', line)
257 if version_match:
258 version = version_match.group(1)
259 #upload_archive = version_match.group(2).strip()
260 version_text = _("Version %s: \n") % version
261 changes_buffer.insert_with_tags_by_name(end_iter, version_text,
262 "versiontag")
263+ elif changes_match:
264+ changes_buffer.insert_with_tags_by_name(end_iter, line + "\n",
265+ "changestag")
266 elif (author_match):
267 pass
268 else:
269@@ -551,12 +577,8 @@ class UpdatesAvailable(InternalDialog):
270 or item.pkg.candidate.description is None):
271 changes_buffer = self.textview_changes.get_buffer()
272 changes_buffer.set_text("")
273- desc_buffer = self.textview_descr.get_buffer()
274- desc_buffer.set_text("")
275- self.notebook_details.set_sensitive(False)
276 return
277 long_desc = item.pkg.candidate.description
278- self.notebook_details.set_sensitive(True)
279 # do some regular expression magic on the description
280 # Add a newline before each bullet
281 p = re.compile(r'^(\s|\t)*(\*|0|-)', re.MULTILINE)
282@@ -570,9 +592,6 @@ class UpdatesAvailable(InternalDialog):
283 long_desc = ("Package: %s\n%s" %
284 (item.pkg.name, long_desc))
285
286- desc_buffer = self.textview_descr.get_buffer()
287- desc_buffer.set_text(long_desc)
288-
289 # now do the changelog
290 name = item.pkg.name
291 if name is None:
292@@ -585,7 +604,7 @@ class UpdatesAvailable(InternalDialog):
293 if name in self.cache.all_changes:
294 changes = self.cache.all_changes[name]
295 srcpkg = self.cache[name].candidate.source_name
296- self.set_changes_buffer(changes_buffer, changes, name, srcpkg)
297+ self.set_changes_buffer(changes_buffer, long_desc, changes, name, srcpkg)
298 # if not connected, do not even attempt to get the changes
299 elif not self.connected:
300 changes_buffer.set_text(
301@@ -630,8 +649,9 @@ class UpdatesAvailable(InternalDialog):
302 changes += self.cache.all_news[name]
303 if name in self.cache.all_changes:
304 changes += self.cache.all_changes[name]
305- if changes:
306- self.set_changes_buffer(changes_buffer, changes, name, srcpkg)
307+
308+ if changes or long_desc:
309+ self.set_changes_buffer(changes_buffer, long_desc, changes, name, srcpkg)
310
311 def on_treeview_button_press(self, widget, event):
312 """
313@@ -658,6 +678,11 @@ class UpdatesAvailable(InternalDialog):
314 menu.show()
315 return True
316
317+ def _get_apt_news(self, apt_news_file):
318+ if os.access(apt_news_file, os.R_OK):
319+ with open(apt_news_file) as f:
320+ return f.read()
321+
322 # we need this for select all/unselect all
323 def _toggle_group_headers(self, new_selection_value):
324 """ small helper that will set/unset the group headers
325@@ -756,6 +781,7 @@ class UpdatesAvailable(InternalDialog):
326 # self.button_install.set_sensitive(True)
327 self.button_install.set_sensitive(True)
328 self.unity.set_install_menuitem_visible(True)
329+ self.button_pro.destroy()
330 else:
331 if inst_count > 0:
332 download_str = ngettext(
333@@ -764,10 +790,15 @@ class UpdatesAvailable(InternalDialog):
334 inst_count)
335 self.button_install.set_sensitive(True)
336 self.unity.set_install_menuitem_visible(True)
337+ self.button_pro.destroy()
338+ elif self.list.ubuntu_pro_fake_groups and not self.list.ubuntu_pro_groups:
339+ download_str = _("You need to enable Ubuntu Pro to install these updates.")
340+ self.button_install.destroy()
341 else:
342 download_str = _("There are no updates to install.")
343 self.button_install.set_sensitive(False)
344 self.unity.set_install_menuitem_visible(False)
345+ self.button_pro.destroy()
346 self.image_downsize.set_sensitive(False)
347 self.label_downsize.set_text(download_str)
348 self.hbox_downsize.show()
349@@ -812,7 +843,6 @@ class UpdatesAvailable(InternalDialog):
350 text_desc = _("The computer also needs to restart "
351 "to finish installing previous updates.")
352
353- self.notebook_details.set_sensitive(True)
354 self.treeview_update.set_sensitive(True)
355 self.set_header(text_header)
356 self.set_desc(text_desc)
357@@ -833,8 +863,10 @@ class UpdatesAvailable(InternalDialog):
358 self._restore_state()
359
360 def activate_desc(self, expander, data):
361- expanded = self.expander_desc.get_expanded()
362- self.expander_desc.set_vexpand(expanded)
363+ return
364+
365+ def on_button_pro_clicked(self):
366+ self.window_main.show_settings(SoftwarePropertiesPage.ubuntu_pro)
367
368 def on_button_install_clicked(self):
369 self.unity.set_install_menuitem_visible(False)
370@@ -1032,6 +1064,8 @@ class UpdatesAvailable(InternalDialog):
371 len(group.items) == 1:
372 group_is_item = group.items[0]
373
374+ if group.name == "Ubuntu base":
375+ group.name = "System components"
376 group_row = [
377 group.name,
378 UpdateData(None, group, group_is_item),
379@@ -1074,13 +1108,8 @@ class UpdatesAvailable(InternalDialog):
380 if self.list.security_groups:
381 self._add_header(_("Security updates"), self.list.security_groups)
382 self._add_groups(self.list.security_groups)
383- if ((self.list.security_groups or self.list.oem_groups)
384- and self.list.update_groups):
385- self._add_header(_("Other updates"), self.list.update_groups)
386- elif self.list.update_groups and (self.list.kernel_autoremove_groups
387- or self.list.duplicate_groups):
388- self._add_header(_("Updates"), self.list.update_groups)
389 if self.list.update_groups:
390+ self._add_header(_("Other updates"), self.list.update_groups)
391 self._add_groups(self.list.update_groups)
392 if self.list.kernel_autoremove_groups:
393 self._add_header(
394@@ -1093,11 +1122,17 @@ class UpdatesAvailable(InternalDialog):
395 self.list.duplicate_groups)
396 self._add_groups(self.list.duplicate_groups)
397 if self.list.ubuntu_pro_groups:
398- self._add_header(_("Ubuntu Pro (enable in Settingsā€¦)"), self.list.ubuntu_pro_groups, sensitive=False)
399+ self._add_header(_("Ubuntu Pro security updates"), self.list.ubuntu_pro_groups, sensitive=True)
400 self._add_groups(self.list.ubuntu_pro_groups)
401+ if self.list.ubuntu_pro_fake_groups:
402+ self._add_header(_("Ubuntu Pro security updates (enable in Settingsā€¦)"), self.list.ubuntu_pro_fake_groups, sensitive=False)
403+ self._add_groups(self.list.ubuntu_pro_fake_groups)
404
405 self.treeview_update.set_model(self.store)
406 self.pkg_cell_area.indent_toplevel = (
407+ bool(self.list.ubuntu_pro_fake_groups) or
408+ bool(self.list.ubuntu_pro_groups) or
409+ bool(self.list.update_groups) or
410 bool(self.list.security_groups)
411 or bool(self.list.kernel_autoremove_groups)
412 or bool(self.list.duplicate_groups))
413diff --git a/data/gtkbuilder/UpdateManager.ui b/data/gtkbuilder/UpdateManager.ui
414index d38eeaf..d82f816 100644
415--- a/data/gtkbuilder/UpdateManager.ui
416+++ b/data/gtkbuilder/UpdateManager.ui
417@@ -6,17 +6,48 @@
418 <property name="can_focus">False</property>
419 <property name="spacing">12</property>
420 <child>
421+ <object class="GtkExpander" id="expander_news">
422+ <property name="visible">False</property>
423+ <property name="can_focus">True</property>
424+ <property name="label">News</property>
425+ <property name="spacing">6</property>
426+ <property name="expanded">True</property>
427+ <child>
428+ <object class="GtkScrolledWindow">
429+ <property name="visible">True</property>
430+ <property name="can_focus">True</property>
431+ <property name="shadow_type">in</property>
432+ <property name="min_content_height">80</property>
433+ <child>
434+ <object class="GtkTextView" id="news">
435+ <property name="visible">True</property>
436+ <property name="editable">False</property>
437+ <property name="pixels_above_lines">6</property>
438+ <property name="left_margin">6</property>
439+ <property name="right_margin">6</property>
440+ <property name="wrap_mode">word</property>
441+ <property name="cursor_visible">False</property>
442+ <property name="accepts_tab">False</property>
443+ </object>
444+ </child>
445+ </object>
446+ </child>
447+ </object>
448+ <packing>
449+ <property name="expand">False</property>
450+ <property name="position">0</property>
451+ </packing>
452+ </child>
453+ <child>
454 <object class="GtkExpander" id="expander_details">
455 <property name="visible">True</property>
456 <property name="can_focus">True</property>
457 <property name="spacing">6</property>
458 <property name="resize_toplevel">True</property>
459 <child>
460- <object class="GtkVBox" id="vbox4">
461+ <object class="GtkPaned" id="paned">
462 <property name="visible">True</property>
463- <property name="can_focus">False</property>
464- <property name="vexpand">True</property>
465- <property name="spacing">6</property>
466+ <property name="orientation">vertical</property>
467 <child>
468 <object class="GtkScrolledWindow" id="scrolledwindow_update">
469 <property name="visible">True</property>
470@@ -44,113 +75,21 @@
471 </child>
472 </object>
473 <packing>
474- <property name="expand">True</property>
475- <property name="fill">True</property>
476- <property name="position">0</property>
477+ <property name="shrink">False</property>
478+ <property name="resize">True</property>
479 </packing>
480 </child>
481 <child>
482- <object class="GtkExpander" id="expander_desc">
483+ <object class="GtkScrolledWindow" id="scrolledwindow_changes">
484 <property name="visible">True</property>
485 <property name="can_focus">True</property>
486+ <property name="shadow_type">in</property>
487 <child>
488- <object class="GtkNotebook" id="notebook_details">
489- <property name="visible">True</property>
490- <property name="can_focus">True</property>
491- <property name="show_border">False</property>
492- <child>
493- <object class="GtkVBox" id="vbox5">
494- <property name="visible">True</property>
495- <property name="can_focus">False</property>
496- <property name="border_width">6</property>
497- <property name="spacing">6</property>
498- <child>
499- <object class="GtkScrolledWindow" id="scrolledwindow_changes">
500- <property name="visible">True</property>
501- <property name="can_focus">True</property>
502- <property name="shadow_type">in</property>
503- <child>
504- <placeholder/>
505- </child>
506- </object>
507- <packing>
508- <property name="expand">True</property>
509- <property name="fill">True</property>
510- <property name="position">0</property>
511- </packing>
512- </child>
513- </object>
514- </child>
515- <child type="tab">
516- <object class="GtkLabel" id="label8">
517- <property name="visible">True</property>
518- <property name="can_focus">False</property>
519- <property name="label" translatable="yes">Changes</property>
520- </object>
521- <packing>
522- <property name="tab_fill">False</property>
523- </packing>
524- </child>
525- <child>
526- <object class="GtkScrolledWindow" id="scrolledwindow3">
527- <property name="visible">True</property>
528- <property name="can_focus">True</property>
529- <property name="border_width">6</property>
530- <property name="shadow_type">in</property>
531- <property name="min_content_height">80</property>
532- <child>
533- <object class="GtkTextView" id="textview_descr">
534- <property name="visible">True</property>
535- <property name="can_focus">True</property>
536- <property name="pixels_above_lines">6</property>
537- <property name="editable">False</property>
538- <property name="wrap_mode">word</property>
539- <property name="left_margin">6</property>
540- <property name="right_margin">6</property>
541- <property name="cursor_visible">False</property>
542- <property name="accepts_tab">False</property>
543- <child internal-child="accessible">
544- <object class="AtkObject" id="textview_descr-atkobject">
545- <property name="AtkObject::accessible-name" translatable="yes">Description</property>
546- </object>
547- </child>
548- </object>
549- </child>
550- </object>
551- <packing>
552- <property name="position">1</property>
553- </packing>
554- </child>
555- <child type="tab">
556- <object class="GtkLabel" id="label9">
557- <property name="visible">True</property>
558- <property name="can_focus">False</property>
559- <property name="label" translatable="yes">Description</property>
560- <child internal-child="accessible">
561- <object class="AtkObject" id="label9-atkobject">
562- <property name="AtkObject::accessible-name" translatable="yes">Description</property>
563- </object>
564- </child>
565- </object>
566- <packing>
567- <property name="position">1</property>
568- <property name="tab_fill">False</property>
569- </packing>
570- </child>
571- </object>
572- </child>
573- <child type="label">
574- <object class="GtkLabel" id="label13">
575- <property name="visible">True</property>
576- <property name="can_focus">False</property>
577- <property name="label" translatable="yes">Technical description</property>
578- </object>
579+ <placeholder/>
580 </child>
581 </object>
582 <packing>
583- <property name="expand">False</property>
584- <property name="fill">True</property>
585- <property name="position">1</property>
586+ <property name="resize">True</property>
587 </packing>
588 </child>
589 </object>
590@@ -167,7 +106,7 @@
591 <packing>
592 <property name="expand">True</property>
593 <property name="fill">True</property>
594- <property name="position">2</property>
595+ <property name="position">1</property>
596 </packing>
597 </child>
598 <child>
599@@ -177,13 +116,14 @@
600 <child>
601 <object class="GtkHBox" id="hbox_downsize">
602 <property name="can_focus">False</property>
603- <property name="spacing">12</property>
604+ <property name="spacing">8</property>
605 <child>
606 <object class="GtkImage" id="image_downsize">
607 <property name="visible">True</property>
608 <property name="can_focus">False</property>
609 <property name="pixel-size">16</property>
610 <property name="icon_name">aptdaemon-download</property>
611+ <property name="pixel_size">16</property>
612 </object>
613 <packing>
614 <property name="expand">False</property>
615@@ -401,7 +341,7 @@
616 <packing>
617 <property name="expand">False</property>
618 <property name="fill">True</property>
619- <property name="position">3</property>
620+ <property name="position">2</property>
621 </packing>
622 </child>
623 </object>
624diff --git a/debian/changelog b/debian/changelog
625index 2fdb443..749da13 100644
626--- a/debian/changelog
627+++ b/debian/changelog
628@@ -1,3 +1,16 @@
629+update-manager (1:22.04.14) jammy; urgency=medium
630+
631+ * Ubuntu Pro (LP: #1990450):
632+ - Show Ubuntu Pro packages, whether the system is attached to Ubuntu Pro
633+ or not.
634+ - Replace Install now button by Enable Ubuntu Pro button when only Ubuntu
635+ Pro packages are available and the machine is not attached.
636+ - Fix checkbox and expander widget from overlapping.
637+ - Add News pane in a expander.
638+ - Replace notebook with Description and Changes tabs by a pane.
639+
640+ -- Nathan Pratta Teodosio <nathan.teodosio@canonical.com> Tue, 29 Aug 2023 07:47:20 +0200
641+
642 update-manager (1:22.04.13) jammy; urgency=medium
643
644 * Fix Ubuntu Pro updates checkbox and expander widget from overlapping (LP: #1990450)

Subscribers

People subscribed via source and target branches