diff --git a/src/Application.vala b/src/Application.vala index 2880efcda..273648653 100644 --- a/src/Application.vala +++ b/src/Application.vala @@ -15,11 +15,13 @@ */ public class AppCenter.App : Granite.Application { - const OptionEntry[] appcenter_options = { + public const OptionEntry[] APPCENTER_OPTIONS = { { "show-updates", 'u', 0, OptionArg.NONE, out show_updates, "Display the Installed Panel", null}, { "silent", 's', 0, OptionArg.NONE, out silent, "Run the Application in background", null}, + { "load-local", 'l', 0, OptionArg.FILENAME, out local_path, + "Add a local AppStream XML file to the package list", "FILENAME" }, { null } }; @@ -27,6 +29,8 @@ public class AppCenter.App : Granite.Application { public static bool show_updates; public static bool silent; + public static string? local_path; + public static AppCenterCore.Package? local_package; private MainWindow? main_window; private uint registration_id = 0; @@ -47,7 +51,6 @@ public class AppCenter.App : Granite.Application { build_version_info = Build.VERSION_INFO; app_launcher = "io.elementary.appcenter.desktop"; - add_main_option_entries (appcenter_options); var quit_action = new SimpleAction ("quit", null); quit_action.activate.connect (() => { @@ -123,6 +126,16 @@ public class AppCenter.App : Granite.Application { return; } + if (local_path != null) { + var file = File.new_for_commandline_arg (local_path); + + try { + local_package = client.add_local_component_file (file); + } catch (Error e) { + warning ("Failed to load local AppStream XML file: %s", e.message); + } + } + if (main_window == null) { main_window = new MainWindow (this); @@ -239,6 +252,17 @@ public class AppCenter.App : Granite.Application { } public static int main (string[] args) { + try { + var opt_context = new OptionContext (null); + opt_context.set_help_enabled (true); + opt_context.add_main_entries (AppCenter.App.APPCENTER_OPTIONS, null); + opt_context.parse (ref args); + } catch (OptionError e) { + stdout.printf ("error: %s\n", e.message); + stdout.printf ("Run '%s --help' to see a full list of available command line options.\n", args[0]); + return 0; + } + var application = new AppCenter.App (); return application.run (args); } diff --git a/src/Core/Client.vala b/src/Core/Client.vala index 5416a8f27..68ede53ff 100644 --- a/src/Core/Client.vala +++ b/src/Core/Client.vala @@ -123,6 +123,34 @@ public class AppCenterCore.Client : Object { return task_count > 0; } + public Package? add_local_component_file (File file) throws Error { + var metadata = new AppStream.Metadata (); + try { + metadata.parse_file (file, AppStream.FormatKind.XML); + } catch (Error e) { + throw e; + } + + var component = metadata.get_component (); + if (component != null) { + string name = _("%s (local)").printf (component.get_name ()); + string id = "%s%s".printf (component.get_id (), Package.LOCAL_ID_SUFFIX); + + component.set_name (name, null); + component.set_id (id); + component.set_origin (Package.APPCENTER_PACKAGE_ORIGIN); + + appstream_pool.add_component (component); + + var package = new AppCenterCore.Package (component); + package_list[id] = package; + + return package; + } + + return null; + } + public async Pk.Exit install_package (Package package, Pk.ProgressCallback cb, GLib.Cancellable cancellable) throws GLib.Error { task_count++; diff --git a/src/Core/Package.vala b/src/Core/Package.vala index cb50fc6ef..806daa69b 100644 --- a/src/Core/Package.vala +++ b/src/Core/Package.vala @@ -24,7 +24,7 @@ public errordomain PackageLaunchError { } public class AppCenterCore.Package : Object { - private const string APPCENTER_PACKAGE_ORIGIN = "appcenter-xenial-main"; + public const string APPCENTER_PACKAGE_ORIGIN = "appcenter-xenial-main"; private const string ELEMENTARY_STABLE_PACKAGE_ORIGIN = "stable-xenial-main"; private const string ELEMENTARY_DAILY_PACKAGE_ORIGIN = "daily-xenial-main"; @@ -41,6 +41,7 @@ public class AppCenterCore.Package : Object { } public const string OS_UPDATES_ID = "xxx-os-updates"; + public const string LOCAL_ID_SUFFIX = ".appcenter-local"; public const string DEFAULT_PRICE_DOLLARS = "1"; public AppStream.Component component { get; construct; } @@ -104,6 +105,12 @@ public class AppCenterCore.Package : Object { } } + public bool is_local { + get { + return component.get_id ().has_suffix (LOCAL_ID_SUFFIX); + } + } + public bool is_native { get { switch (component.get_origin ()) { @@ -442,7 +449,7 @@ public class AppCenterCore.Package : Object { } public Pk.Package? find_package () { - if (component.id == OS_UPDATES_ID) { + if (component.id == OS_UPDATES_ID || is_local) { return null; } diff --git a/src/Views/AppInfoView.vala b/src/Views/AppInfoView.vala index 438e62b2a..dfaf29f26 100644 --- a/src/Views/AppInfoView.vala +++ b/src/Views/AppInfoView.vala @@ -196,7 +196,11 @@ namespace AppCenter.Views { package_summary.valign = Gtk.Align.START; header_grid.attach (package_summary, 1, 1, 3, 1); } - header_grid.attach (action_stack, 3, 0, 1, 1); + + if (!package.is_local) { + header_grid.attach (action_stack, 3, 0, 1, 1); + } + header_box.add (header_grid); var footer_grid = new Gtk.Grid (); diff --git a/src/Views/Homepage.vala b/src/Views/Homepage.vala index 755e3f833..9bad9fb64 100644 --- a/src/Views/Homepage.vala +++ b/src/Views/Homepage.vala @@ -117,6 +117,11 @@ namespace AppCenter { add (category_scrolled); + var local_package = App.local_package; + if (local_package != null) { + newest_banner.add_package (local_package); + } + houston.get_app_ids.begin ("/newest/project", (obj, res) => { var newest_ids = houston.get_app_ids.end (res); new Thread ("update-banner", () => { diff --git a/src/Widgets/PackageRow.vala b/src/Widgets/PackageRow.vala index c38390931..761ac3af0 100644 --- a/src/Widgets/PackageRow.vala +++ b/src/Widgets/PackageRow.vala @@ -180,6 +180,12 @@ namespace AppCenter.Widgets { protected override void set_up_package (uint icon_size = 48) { package_summary.label = package.get_summary (); package_summary.ellipsize = Pango.EllipsizeMode.END; + + if (package.is_local) { + action_stack.no_show_all = true; + action_stack.visible = false; + } + base.set_up_package (icon_size); } }