1/*
2 * Copyright 2019 Michael Gratton <mike@vee.net>
3 *
4 * This software is licensed under the GNU Lesser General Public License
5 * (version 2.1 or later). See the COPYING file in this distribution.
6 */
7
8/**
9 * A simple, high-level interface for the Unity Launcher API.
10 *
11 * See https://wiki.ubuntu.com/Unity/LauncherAPI for documentation.
12 */
13public class UnityLauncherEntry : Geary.BaseObject {
14
15
16    private const string DBUS_NAME = "com.canonical.Unity.LauncherEntry";
17
18
19    [DBus (name = "com.canonical.Unity.LauncherEntry")]
20    private class Entry : Geary.BaseObject {
21
22
23        public signal void update (string app_uri,
24                                   HashTable<string,Variant> properties);
25
26    }
27
28    private string app_uri;
29    private Entry entry = new Entry();
30    private GLib.DBusConnection connection;
31    private uint object_id;
32    private uint watch_id;
33
34    // Launcher entry properties
35    private int64 count = 0;
36    private bool count_visible = false;
37
38
39    /**
40     * Constructions a new launcher entry for the given DBus connection.
41     *
42     * The given path is used as the path of the DBus object that
43     * interacts with the Uniti API, and should be bus-unique. The
44     * given desktop identifier must match the name of the desktop
45     * file for the application.
46     */
47    public UnityLauncherEntry(GLib.DBusConnection connection,
48                              string dbus_path,
49                              string desktop_id)
50        throws GLib.Error {
51        this.app_uri = "application://%s".printf(desktop_id);
52        this.connection = connection;
53        this.object_id = connection.register_object(dbus_path, this.entry);
54        this.watch_id = GLib.Bus.watch_name_on_connection(
55            connection,
56            DBUS_NAME,
57            NONE,
58            on_name_appeared,
59            null
60        );
61
62        update_all();
63    }
64
65    ~UnityLauncherEntry() {
66        GLib.Bus.unwatch_name(this.watch_id);
67        this.connection.unregister_object(this.object_id);
68    }
69
70    /** Sets and shows the count for the application. */
71    public void set_count(int64 count) {
72        var props = new_properties();
73        if (this.count != count) {
74            this.count = count;
75            put_count(props);
76        }
77        if (!this.count_visible) {
78            this.count_visible = true;
79            put_count_visible(props);
80        }
81        send(props);
82    }
83
84    /** Clears and hides any count for the application. */
85    public void clear_count() {
86        var props = new_properties();
87        if (this.count != 0) {
88            this.count = 0;
89            put_count(props);
90        }
91        if (this.count_visible) {
92            this.count_visible = false;
93            put_count_visible(props);
94        }
95        send(props);
96    }
97
98    private void update_all() {
99        var props = new_properties();
100        if (this.count != 0) {
101            put_count(props);
102        }
103        if (!this.count_visible) {
104            put_count_visible(props);
105        }
106        send(props);
107    }
108
109    private void send(GLib.HashTable<string,GLib.Variant> properties) {
110        if (properties.size() > 0) {
111            this.entry.update(this.app_uri, properties);
112        }
113    }
114
115    private GLib.HashTable<string,GLib.Variant> new_properties() {
116        return new GLib.HashTable<string,GLib.Variant>(str_hash, str_equal);
117    }
118
119    private void put_count(GLib.HashTable<string,GLib.Variant> properties) {
120        properties.insert(
121            "count", new GLib.Variant.int64(this.count)
122        );
123    }
124
125    private void put_count_visible(GLib.HashTable<string,GLib.Variant> properties) {
126        properties.insert(
127            "count-visible",
128            new GLib.Variant.boolean(this.count_visible)
129        );
130    }
131
132    private void on_name_appeared() {
133        update_all();
134    }
135
136}
137