Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement drivers (AppStream) #243

Closed
wants to merge 3 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
98 changes: 98 additions & 0 deletions src/Core/Client.vala
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ public class AppCenterCore.Client : Object {

private Gee.HashMap<string, AppCenterCore.Package> package_list;
private AppStream.Pool appstream_pool;
private Gee.TreeSet<AppStream.Component> drivers;
private GLib.Cancellable cancellable;
private GLib.DateTime last_cache_update;
private GLib.DateTime last_action;
Expand Down Expand Up @@ -80,9 +81,16 @@ public class AppCenterCore.Client : Object {
// We don't want to show installed desktop files here
appstream_pool.set_flags (appstream_pool.get_flags () & ~AppStream.PoolFlags.READ_DESKTOP_FILES);

drivers = new Gee.TreeSet<AppStream.Component> ();
try {
appstream_pool.load ();
appstream_pool.get_components ().foreach ((comp) => {
var kind = comp.get_kind ();
if (kind == AppStream.ComponentKind.DRIVER || kind == AppStream.ComponentKind.FIRMWARE) {
drivers.add (comp);
return;
}

var package = new AppCenterCore.Package (comp);
foreach (var pkg_name in comp.get_pkgnames ()) {
package_list[pkg_name] = package;
Expand Down Expand Up @@ -286,6 +294,31 @@ public class AppCenterCore.Client : Object {
updates_available ();
}

/**
* Filters and checks if previously added driver components
* match a system modalias, are suitable for this system
*
* This could be done in get_components () block but since
* scanning all modaliases takes some time , it is done here separately
* to not interrupt populating UI lists with other applications
*/
public async void get_drivers () {
string[] aliases = yield scan_modaliases (null);
foreach (var comp in drivers) {
var provided = comp.get_provided_for_kind (AppStream.ProvidedKind.MODALIAS);
if (provided != null) {
foreach (string alias in aliases) {
if (provided.has_item (alias)) {
var package = new AppCenterCore.Package (comp);
foreach (var pkg_name in comp.get_pkgnames ()) {
package_list[pkg_name] = package;
}
}
}
}
}
}

public async Gee.Collection<AppCenterCore.Package> get_installed_applications () {
var packages = new Gee.TreeSet<AppCenterCore.Package> ();
var installed = yield get_installed_packages ();
Expand Down Expand Up @@ -561,6 +594,71 @@ public class AppCenterCore.Client : Object {
return null;
}

/**
* Scans for system modaliases
*
* This is mostly just a Vala version of UbuntuDrivers system_modaliases () function:
* http://bazaar.launchpad.net/~ubuntu-branches/ubuntu/vivid/ubuntu-drivers-common/vivid/view/head:/UbuntuDrivers/detect.py#L23
*/
private async static string[] scan_modaliases (owned File? root) {
if (root == null) {
root = File.new_for_path ("/sys/devices");
}

string[] aliases = {};
try {
var enumerator = yield root.enumerate_children_async ("standard::*", FileQueryInfoFlags.NOFOLLOW_SYMLINKS);
FileInfo? info = null;
while ((info = enumerator.next_file (null)) != null) {
string? alias = null;

if (info.get_file_type () == FileType.DIRECTORY) {
var subdir = root.resolve_relative_path (info.get_name ());
string[] subaliases = yield scan_modaliases (subdir);
foreach (string subalias in subaliases) {
aliases += subalias;
}
} else if (info.get_name () == "modalias") {
var subfile = root.resolve_relative_path (info.get_name ());
uint8[] contents;
yield subfile.load_contents_async (null, out contents, null);

alias = ((string)contents).strip ();
} else if ("ssb" in root.get_path () && info.get_name () == "uevent") {
var subfile = root.resolve_relative_path (info.get_name ());
uint8[] contents;
yield subfile.load_contents_async (null, out contents, null);

string[] lines = ((string)contents).split ("\n");
foreach (string line in lines) {
string[] tokens = line.split ("=");
if (tokens.length == 2 && tokens[0] == "MODALIAS") {
alias = tokens[1].strip ();
break;
}
}
}

if (alias == null) {
continue;
}

string driver_link = Path.build_filename (root.get_path (), "driver");
string modlink = Path.build_filename (driver_link, "module");

if (FileUtils.test (driver_link, FileTest.IS_SYMLINK) && !FileUtils.test (modlink, FileTest.IS_SYMLINK)) {
continue;
}

aliases += alias;
}
} catch (Error e) {
warning (e.message);
}

return aliases;
}

private static GLib.Once<Client> instance;
public static unowned Client get_default () {
return instance.once (() => { return new Client (); });
Expand Down
7 changes: 7 additions & 0 deletions src/Core/Package.vala
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,13 @@ public class AppCenterCore.Package : Object {
}
}

public bool is_driver {
get {
var kind = component.get_kind ();
return kind == AppStream.ComponentKind.DRIVER || kind == AppStream.ComponentKind.FIRMWARE;
}
}

private string? name = null;
private string? description = null;
private string? summary = null;
Expand Down
33 changes: 28 additions & 5 deletions src/Views/AppListView.vala
Original file line number Diff line number Diff line change
Expand Up @@ -183,18 +183,27 @@ namespace AppCenter.Views {
return a_has_updates ? -1 : 1;
}

bool a_is_driver = row1.get_is_driver ();
bool b_is_driver = row2.get_is_driver ();

if ((a_is_driver && !b_is_driver) || (!a_is_driver && b_is_driver)) {
return a_is_driver ? - 1 : 1;
}

return row1.get_name_label ().collate (row2.get_name_label ()); /* Else sort in name order */
}

[CCode (instance_pos = -1)]
private void row_update_header (Widgets.AppListRow row, Widgets.AppListRow? before) {
bool update_available = row.get_update_available ();
if (before != null && update_available == before.get_update_available ()) {
row.set_header (null);
return;
}
bool is_driver = row.get_is_driver ();

if (update_available) {
if (before != null && update_available == before.get_update_available ()) {
row.set_header (null);
return;
}

var header = new Widgets.UpdatesGrid ();

uint update_numbers = 0U;
Expand All @@ -220,8 +229,22 @@ namespace AppCenter.Views {
}

header.show_all ();
row.set_header (header);
row.set_header (header);
} else if (is_driver) {
if (before != null && is_driver == before.get_is_driver ()) {
row.set_header (null);
return;
}

var header = new Widgets.DriverGrid ();
header.show_all ();
row.set_header (header);
} else {
if (before != null && is_driver == before.get_is_driver () && update_available == before.get_update_available ()) {
row.set_header (null);
return;
}

var header = new Widgets.UpdatedGrid ();
header.update (0, 0, updating_cache);
header.show_all ();
Expand Down
2 changes: 2 additions & 0 deletions src/Views/InstalledView.vala
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,8 @@ public class AppCenter.Views.InstalledView : View {
public async void get_apps () {
unowned Client client = Client.get_default ();

yield client.get_drivers ();

var installed_apps = yield client.get_installed_applications ();
app_list_view.add_packages (installed_apps);

Expand Down
6 changes: 6 additions & 0 deletions src/Widgets/AbstractAppContainer.vala
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,12 @@ namespace AppCenter {
}
}

public bool is_driver {
get {
return package.is_driver;
}
}

public bool update_available {
get {
return package.update_available || package.is_updating;
Expand Down
1 change: 1 addition & 0 deletions src/Widgets/AppListRow.vala
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ namespace AppCenter.Widgets {
public interface AppListRow : Gtk.ListBoxRow {
public abstract bool get_update_available ();
public abstract bool get_is_os_updates ();
public abstract bool get_is_driver ();
public abstract bool get_is_updating ();
public abstract string get_name_label ();
public abstract bool has_package ();
Expand Down
4 changes: 4 additions & 0 deletions src/Widgets/PackageRow.vala
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,10 @@ namespace AppCenter.Widgets {
return grid.is_os_updates;
}

public bool get_is_driver () {
return grid.is_driver;
}

public string get_name_label () {
return grid.name_label;
}
Expand Down
15 changes: 15 additions & 0 deletions src/Widgets/UpdateHeaderRow.vala
Original file line number Diff line number Diff line change
Expand Up @@ -114,4 +114,19 @@ namespace AppCenter.Widgets {
}
}
}

public class DriverGrid : AbstractHeaderGrid {
construct {
var label = new Gtk.Label (_("Drivers"));
label.get_style_context ().add_class ("h4");
label.hexpand = true;
((Gtk.Misc)label).xalign = 0;

add (label);
}

public override void update (uint _update_numbers, uint64 _update_real_size, bool _is_updating) {

}
}
}