Merge lp:~3v1n0/unity/zeitgeist-quicklists into lp:unity
- zeitgeist-quicklists
- Merge into trunk
Status: | Work in progress |
---|---|
Proposed branch: | lp:~3v1n0/unity/zeitgeist-quicklists |
Merge into: | lp:unity |
Diff against target: |
935 lines (+701/-57) 8 files modified
CMakeLists.txt (+1/-1) UnityCore/CMakeLists.txt (+5/-1) UnityCore/ZeitgeistApplication.cpp (+269/-0) UnityCore/ZeitgeistApplication.h (+86/-0) UnityCore/ZeitgeistSubject.cpp (+91/-0) UnityCore/ZeitgeistSubject.h (+64/-0) plugins/unityshell/src/BamfLauncherIcon.cpp (+174/-55) plugins/unityshell/src/BamfLauncherIcon.h (+11/-0) |
To merge this branch: | bzr merge lp:~3v1n0/unity/zeitgeist-quicklists |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Tim Penhey (community) | Needs Fixing | ||
Review via email: mp+93126@code.launchpad.net |
Commit message
Description of the change
Implemented design backlog bug #893652 adding quicklist entries with recently used files to launcher icons.
This adds Zeitgeist support to unity, using lp:libzeitgeist through an UnityCore wrapper where I've added two main classes, ZeitgeistApplic
ZeitgeistSubject is a kind of a mix between a pure zeitgeist-event and a native zeitgeist-subject. In fact each ZeitgeistSubject is actually wrapping a native subject, but it has also the references to the native (parent) event id.
ZeitgeistApplic
Each application can store also a defined number of subjects received by the monitor and these elements are stored into a deque that acts like a circular-buffer cache.
BamfLauncherIcon use now ZeitgeistApplic
- 1978. By Marco Trevisan (Treviño)
-
ZeitgeistApplic
ation: some string optimization... - 1979. By Marco Trevisan (Treviño)
-
ZeitgeistApplic
ation: share the instance of ZeitgeistLog, fix memory leaks - 1980. By Marco Trevisan (Treviño)
-
BamfLauncherIcon: don't open the content of a quicklist if the uri is empty
- 1981. By Marco Trevisan (Treviño)
-
ZeitgeistApplic
ation: don't use a pointer to handle the shared log... - 1982. By Marco Trevisan (Treviño)
-
ZeitgeistApplic
ation: use manifestation and reorder the received items
Marco Trevisan (Treviño) (3v1n0) wrote : | # |
> > std::string const& basename =
> glib::String(
>
> This takes a reference to a temporary. Remove the "const&" bit.
Ok.
> If you have a shared log, why delete it when the last reference was there?
> why not let the log just live on?
>
> > UnityCore/
>
> Has the same two lines about 6 times. Consider a simple function.
That's something I was thinking on, but I didn't like to do something like that just for this case (also considering that I'm repeating something that is not so different from calling a shared function).
I think that this a reason why can make sense supporting const strings in glib::String as I told some time ago... Wouldn't be better something like this: http://
> The ZeitgeistSubject is obviously not meant to be inherited from, so please
> don't add a protected section.
Sure, I added it for another reason... Then I forgot to change it.
> Secondly, please don't use friend. What is wrong with having a public
> constructor?
I know that friend classes aren't the best thing, but I neither loved the idea of allowing everybody to construct a ZeitgeistSubject, as that's something that only a ZetigeistApplic
> As you mentioned, this branch is missing tests. A key question is how to
> ensure it is working.
>
> What needs to exist for this to work properly? How can we minimally test it?
In the real world we'd need to create a new zeitgeist application, install a monitor on it, and check that we get some subjects both when the monitor is installed (if there are events for that) and when we open a new file with the given application.
Testing it through a mock would be maybe useless to really check that this is working.
> We need to export the relevant bits through autopilot, then we can have some
> functional tests that show when we do "stuff" we get "other stuff" showing in
> the quicklists.
I see what I can do on this.
Marco Trevisan (Treviño) (3v1n0) wrote : | # |
Ah, I forgot to reply at:
> If you have a shared log, why delete it when the last reference was there?
> why not let the log just live on?
Well, why should we leak memory if no one really needs a log?
When all the applications that have used a log are destroyed, we make sure that our log is removed... Maybe I could just switch to zetigeist_
- 1983. By Marco Trevisan (Treviño)
-
Merging with trunk
- 1984. By Marco Trevisan (Treviño)
-
glib::String: add support for constant strings
- 1985. By Marco Trevisan (Treviño)
-
ZeitgeistSubject: moving to glib::String with const support.
- 1986. By Marco Trevisan (Treviño)
-
ZeitgeistSubject: setting the constructor private.
Michal Hruby (mhr3) wrote : | # |
112 + explicit String(const gchar* str);
Woooo, no, no, no, the glib::String class is meant to own the string, this way it can easily break if the real owner goes out of scope, we definitely don't want that kind of breakage.
- 1987. By Marco Trevisan (Treviño)
-
Removing debug test code
- 1988. By Marco Trevisan (Treviño)
-
ZeitgeistSubject: add GetConstString to stafely convert gchar* to std::string
Marco Trevisan (Treviño) (3v1n0) wrote : | # |
> 112 + explicit String(const gchar* str);
>
> Woooo, no, no, no, the glib::String class is meant to own the string, this way
> it can easily break if the real owner goes out of scope, we definitely don't
> want that kind of breakage.
It didn't look so bad to me as I don't think it would introduce any breakage that using a simple const gchar* wouldn't, but if that's your thinking, I go back to the Tim's advice, even if it's out of scope there, imho.
Unmerged revisions
- 1988. By Marco Trevisan (Treviño)
-
ZeitgeistSubject: add GetConstString to stafely convert gchar* to std::string
- 1987. By Marco Trevisan (Treviño)
-
Removing debug test code
- 1986. By Marco Trevisan (Treviño)
-
ZeitgeistSubject: setting the constructor private.
- 1985. By Marco Trevisan (Treviño)
-
ZeitgeistSubject: moving to glib::String with const support.
- 1984. By Marco Trevisan (Treviño)
-
glib::String: add support for constant strings
- 1983. By Marco Trevisan (Treviño)
-
Merging with trunk
- 1982. By Marco Trevisan (Treviño)
-
ZeitgeistApplic
ation: use manifestation and reorder the received items - 1981. By Marco Trevisan (Treviño)
-
ZeitgeistApplic
ation: don't use a pointer to handle the shared log... - 1980. By Marco Trevisan (Treviño)
-
BamfLauncherIcon: don't open the content of a quicklist if the uri is empty
- 1979. By Marco Trevisan (Treviño)
-
ZeitgeistApplic
ation: share the instance of ZeitgeistLog, fix memory leaks
Preview Diff
1 | === modified file 'CMakeLists.txt' |
2 | --- CMakeLists.txt 2012-02-23 07:43:46 +0000 |
3 | +++ CMakeLists.txt 2012-02-28 17:40:24 +0000 |
4 | @@ -122,7 +122,7 @@ |
5 | # |
6 | # Compiz Plugins |
7 | # |
8 | -set (UNITY_PLUGIN_DEPS "compiz;nux-2.0>=2.0.0;libbamf3;dee-1.0;gio-2.0;gio-unix-2.0;dbusmenu-glib-0.4;x11;libstartup-notification-1.0;gthread-2.0;indicator3-0.4;atk;unity-misc>=0.4.0;gconf-2.0;libutouch-geis;gtk+-3.0>=3.1;sigc++-2.0;json-glib-1.0;libnotify;gnome-desktop-3.0;gdu") |
9 | +set (UNITY_PLUGIN_DEPS "compiz;nux-2.0>=2.0.0;libbamf3;dee-1.0;gio-2.0;gio-unix-2.0;dbusmenu-glib-0.4;x11;libstartup-notification-1.0;gthread-2.0;indicator3-0.4;atk;unity-misc>=0.4.0;gconf-2.0;libutouch-geis;gtk+-3.0>=3.1;sigc++-2.0;json-glib-1.0;libnotify;gnome-desktop-3.0;gdu;zeitgeist-1.0") |
10 | |
11 | add_subdirectory(plugins/unityshell) |
12 | add_subdirectory(plugins/gtkloader) |
13 | |
14 | === modified file 'UnityCore/CMakeLists.txt' |
15 | --- UnityCore/CMakeLists.txt 2012-02-07 07:42:12 +0000 |
16 | +++ UnityCore/CMakeLists.txt 2012-02-28 17:40:24 +0000 |
17 | @@ -1,5 +1,5 @@ |
18 | find_package (PkgConfig) |
19 | -pkg_check_modules (CORE_DEPS REQUIRED glib-2.0 gio-2.0 dee-1.0 sigc++-2.0 nux-core-2.0 gdk-pixbuf-2.0 unity) |
20 | +pkg_check_modules (CORE_DEPS REQUIRED glib-2.0 gio-2.0 dee-1.0 sigc++-2.0 nux-core-2.0 gdk-pixbuf-2.0 unity zeitgeist-1.0) |
21 | |
22 | execute_process (COMMAND ${PKG_CONFIG_EXECUTABLE} unity --variable lensesdir OUTPUT_VARIABLE _lensesdir OUTPUT_STRIP_TRAILING_WHITESPACE) |
23 | |
24 | @@ -40,6 +40,8 @@ |
25 | Result.h |
26 | Results.h |
27 | Variant.h |
28 | + ZeitgeistApplication.h |
29 | + ZeitgeistSubject.h |
30 | ) |
31 | |
32 | set (CORE_SOURCES |
33 | @@ -70,6 +72,8 @@ |
34 | Result.cpp |
35 | Results.cpp |
36 | Variant.cpp |
37 | + ZeitgeistApplication.cpp |
38 | + ZeitgeistSubject.cpp |
39 | ) |
40 | |
41 | # |
42 | |
43 | === added file 'UnityCore/ZeitgeistApplication.cpp' |
44 | --- UnityCore/ZeitgeistApplication.cpp 1970-01-01 00:00:00 +0000 |
45 | +++ UnityCore/ZeitgeistApplication.cpp 2012-02-28 17:40:24 +0000 |
46 | @@ -0,0 +1,269 @@ |
47 | +// -*- Mode: C++; indent-tabs-mode: nil; tab-width: 2 -*- |
48 | +/* |
49 | + * Copyright (C) 2012 Canonical Ltd |
50 | + * |
51 | + * This program is free software: you can redistribute it and/or modify |
52 | + * it under the terms of the GNU General Public License version 3 as |
53 | + * published by the Free Software Foundation. |
54 | + * |
55 | + * This program is distributed in the hope that it will be useful, |
56 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
57 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
58 | + * GNU General Public License for more details. |
59 | + * |
60 | + * You should have received a copy of the GNU General Public License |
61 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
62 | + * |
63 | + * Authored by: Marco Trevisan (Treviño) <3v1n0@ubuntu.com> |
64 | + */ |
65 | + |
66 | +#include "ZeitgeistApplication.h" |
67 | + |
68 | +namespace unity |
69 | +{ |
70 | +namespace zeitgeist |
71 | +{ |
72 | +static glib::Object<ZeitgeistLog> shared_log_; |
73 | + |
74 | +Application::Application(std::string const& desktop_file) |
75 | + : application_event_(zeitgeist_event_new()) |
76 | +{ |
77 | + if (!shared_log_ || !ZEITGEIST_IS_LOG(shared_log_.RawPtr())) |
78 | + { |
79 | + shared_log_ = glib::Object<ZeitgeistLog>(zeitgeist_log_new()); |
80 | + } |
81 | + |
82 | + log_ = shared_log_; |
83 | + |
84 | + if (!desktop_file.empty()) |
85 | + { |
86 | + std::string basename = glib::String(g_path_get_basename(desktop_file.c_str())).Str(); |
87 | + |
88 | + if (!basename.empty()) |
89 | + { |
90 | + const std::string prefix = "application://"; |
91 | + application_uri_ = prefix + basename; |
92 | + |
93 | + ZeitgeistSubject* subj = zeitgeist_subject_new(); |
94 | + glib::Object<ZeitgeistSubject> application_subject(subj, glib::AddRef()); |
95 | + zeitgeist_subject_set_manifestation(application_subject, "!" ZEITGEIST_NFO_SOFTWARE_ITEM); |
96 | + zeitgeist_event_add_subject(application_event_, application_subject); |
97 | + zeitgeist_event_set_actor(application_event_, application_uri_.c_str()); |
98 | + } |
99 | + } |
100 | +} |
101 | + |
102 | +Application::~Application() |
103 | +{ |
104 | + if (ZEITGEIST_IS_LOG(shared_log_.RawPtr())) |
105 | + { |
106 | + auto glog = reinterpret_cast<GObject*>(shared_log_.RawPtr()); |
107 | + |
108 | + /* If the log has 2 references we can safely nullify the shared instance |
109 | + * In fact, at this point both the application log_ member and the |
110 | + * shared member owns a reference, that's why of this "magic" number */ |
111 | + if (glog->ref_count == 2) |
112 | + { |
113 | + shared_log_ = nullptr; |
114 | + } |
115 | + } |
116 | + else if (shared_log_) |
117 | + { |
118 | + shared_log_ = nullptr; |
119 | + } |
120 | +} |
121 | + |
122 | +std::string const& Application::Uri() const |
123 | +{ |
124 | + return application_uri_; |
125 | +} |
126 | + |
127 | +ZeitgeistResultType Application::GetResultTypeByMonitorType(MonitorType mtype) |
128 | +{ |
129 | + switch (mtype) |
130 | + { |
131 | + case MOST_RECENT_EVENTS: |
132 | + return ZEITGEIST_RESULT_TYPE_MOST_RECENT_EVENTS; |
133 | + case LEAST_RECENT_EVENTS: |
134 | + return ZEITGEIST_RESULT_TYPE_LEAST_RECENT_EVENTS; |
135 | + case MOST_RECENT_SUBJECTS: |
136 | + return ZEITGEIST_RESULT_TYPE_MOST_RECENT_SUBJECTS; |
137 | + case LEAST_RECENT_SUBJECTS: |
138 | + return ZEITGEIST_RESULT_TYPE_LEAST_RECENT_SUBJECTS; |
139 | + case MOST_POPULAR_SUBJECTS: |
140 | + return ZEITGEIST_RESULT_TYPE_MOST_POPULAR_SUBJECTS; |
141 | + case LEAST_POPULAR_SUBJECTS: |
142 | + return ZEITGEIST_RESULT_TYPE_LEAST_POPULAR_SUBJECTS; |
143 | + default: |
144 | + return ZEITGEIST_RESULT_TYPE_RELEVANCY; |
145 | + } |
146 | +} |
147 | + |
148 | +void Application::HandleResultSet(glib::Object<ZeitgeistResultSet> const& results, MonitorType mtype) |
149 | +{ |
150 | + Subjects& subjects = subjects_[mtype]; |
151 | + std::deque<std::pair<ZeitgeistEvent*, ZeitgeistSubject*>> new_subjects; |
152 | + unsigned int max_items = subjects_pools_[mtype]; |
153 | + |
154 | + // Reversing the list of the new items. |
155 | + while (zeitgeist_result_set_has_next(results)) |
156 | + { |
157 | + ZeitgeistEvent* event = zeitgeist_result_set_next(results); |
158 | + |
159 | + for (int i = 0; i < zeitgeist_event_num_subjects(event); ++i) |
160 | + { |
161 | + ZeitgeistSubject* subj = zeitgeist_event_get_subject(event, i); |
162 | + if (!ZEITGEIST_IS_SUBJECT(subj)) |
163 | + continue; |
164 | + |
165 | + std::pair<ZeitgeistEvent*, ZeitgeistSubject*> new_event(event, subj); |
166 | + new_subjects.push_front(new_event); |
167 | + } |
168 | + } |
169 | + |
170 | + for (auto new_pair : new_subjects) |
171 | + { |
172 | + ZeitgeistEvent* event = new_pair.first; |
173 | + guint32 event_id = zeitgeist_event_get_id(event); |
174 | + gint64 timestamp = zeitgeist_event_get_timestamp(event); |
175 | + |
176 | + glib::Object<ZeitgeistSubject> gsubject(new_pair.second, glib::AddRef()); |
177 | + Subject::Ptr subject_ptr(new Subject(gsubject, event_id, timestamp)); |
178 | + |
179 | + for (auto it = subjects.begin(); it != subjects.end(); ++it) |
180 | + { |
181 | + if ((*it)->Uri() == subject_ptr->Uri()) |
182 | + { |
183 | + subject_removed.emit(mtype, *it); |
184 | + subjects.erase(it); |
185 | + break; |
186 | + } |
187 | + } |
188 | + |
189 | + if (subjects.size() == max_items) |
190 | + { |
191 | + subject_removed.emit(mtype, subjects.front()); |
192 | + subjects.pop_front(); |
193 | + } |
194 | + |
195 | + subjects.push_back(subject_ptr); |
196 | + subject_added.emit(mtype, subject_ptr); |
197 | + } |
198 | +} |
199 | + |
200 | +void Application::AddMonitor(MonitorType mtype, unsigned int pool_size) |
201 | +{ |
202 | + if (monitors_.find(mtype) != monitors_.end() || pool_size == 0) |
203 | + { |
204 | + return; |
205 | + } |
206 | + |
207 | + glib::Object<ZeitgeistTimeRange> time_range(zeitgeist_time_range_new_to_now()); |
208 | + |
209 | + // This must not be free'd, libzeitgeist will take care of it. |
210 | + GPtrArray* event_template = g_ptr_array_sized_new(1); |
211 | + glib::Object<ZeitgeistEvent> event(application_event_, glib::AddRef()); |
212 | + g_ptr_array_add(event_template, event); |
213 | + |
214 | + subjects_pools_[mtype] = pool_size; |
215 | + |
216 | + struct FindEventsData |
217 | + { |
218 | + Application* self; |
219 | + Application::MonitorType type; |
220 | + }; |
221 | + |
222 | + auto data = new FindEventsData(); |
223 | + data->self = this; |
224 | + data->type = mtype; |
225 | + |
226 | + zeitgeist_log_find_events(log_, time_range, event_template, ZEITGEIST_STORAGE_STATE_AVAILABLE, |
227 | + pool_size, GetResultTypeByMonitorType(mtype), nullptr, |
228 | + [] (GObject* object, GAsyncResult* res, gpointer data) |
229 | + { |
230 | + glib::Error error; |
231 | + glib::Object<ZeitgeistResultSet> results; |
232 | + auto find_data = static_cast<FindEventsData*>(data); |
233 | + auto log = reinterpret_cast<ZeitgeistLog*>(object); |
234 | + |
235 | + results = zeitgeist_log_find_events_finish(log, res, &error); |
236 | + |
237 | + if (!error) |
238 | + find_data->self->HandleResultSet(results, find_data->type); |
239 | + |
240 | + delete find_data; |
241 | + }, |
242 | + data); |
243 | + |
244 | + GPtrArray* monitor_template = g_ptr_array_sized_new(1); |
245 | + g_ptr_array_add(monitor_template, event); |
246 | + |
247 | + glib::Object<ZeitgeistTimeRange> monitor_time_range(zeitgeist_time_range_new_from_now(), glib::AddRef()); |
248 | + glib::Object<ZeitgeistMonitor> monitor(zeitgeist_monitor_new(monitor_time_range, monitor_template), glib::AddRef()); |
249 | + g_object_set_data(glib::object_cast<GObject>(monitor), "monitor-type", GUINT_TO_POINTER(mtype)); |
250 | + |
251 | + monitors_[mtype] = monitor; |
252 | + zeitgeist_log_install_monitor(log_, monitor); |
253 | + |
254 | + typedef glib::Signal<void, ZeitgeistMonitor*, ZeitgeistTimeRange*, ZeitgeistResultSet*> EventsAddedSignal; |
255 | + |
256 | + signal_manager_.Add(new EventsAddedSignal(monitor, "events-inserted", |
257 | + [&] (ZeitgeistMonitor* zmon, ZeitgeistTimeRange* tm, ZeitgeistResultSet* events) |
258 | + { |
259 | + glib::Object<ZeitgeistTimeRange> time(tm); |
260 | + glib::Object<ZeitgeistResultSet> results(events); |
261 | + gpointer data = g_object_get_data(reinterpret_cast<GObject*>(zmon), "monitor-type"); |
262 | + HandleResultSet(results, static_cast<MonitorType>(GPOINTER_TO_UINT(data))); |
263 | + })); |
264 | + |
265 | + typedef glib::Signal<void, ZeitgeistMonitor*, ZeitgeistTimeRange*, GArray*> EventsDeletedSignal; |
266 | + |
267 | + signal_manager_.Add(new EventsDeletedSignal(monitor, "events-deleted", |
268 | + [&] (ZeitgeistMonitor* zmon, ZeitgeistTimeRange* tm, GArray* events) |
269 | + { |
270 | + glib::Object<ZeitgeistTimeRange> time(tm); |
271 | + gpointer data = g_object_get_data(reinterpret_cast<GObject*>(zmon), "monitor-type"); |
272 | + MonitorType mon_type = static_cast<MonitorType>(GPOINTER_TO_UINT(data)); |
273 | + |
274 | + Subjects& subjects = subjects_[mon_type]; |
275 | + std::vector<Subjects::iterator> to_rm; |
276 | + |
277 | + for (unsigned int i = 0; events && i < events->len; ++i) |
278 | + { |
279 | + guint32 event_id = g_array_index(events, guint32, i); |
280 | + |
281 | + for (auto it = subjects.begin(); it != subjects.end(); ++it) |
282 | + { |
283 | + if ((*it)->EventId() == event_id) |
284 | + { |
285 | + subject_removed.emit(mon_type, *it); |
286 | + to_rm.push_back(it); |
287 | + } |
288 | + } |
289 | + } |
290 | + |
291 | + for (auto subject_it : to_rm) |
292 | + subjects.erase(subject_it); |
293 | + |
294 | + g_array_unref(events); |
295 | + })); |
296 | +} |
297 | + |
298 | +void Application::RemoveMonitor(MonitorType mtype) |
299 | +{ |
300 | + if (monitors_.find(mtype) == monitors_.end()) |
301 | + return; |
302 | + |
303 | + glib::Object<ZeitgeistMonitor> &monitor = monitors_[mtype]; |
304 | + signal_manager_.Disconnect(monitor.RawPtr(), "events-inserted"); |
305 | + signal_manager_.Disconnect(monitor.RawPtr(), "events-deleted"); |
306 | + |
307 | + for (auto subject : subjects_[mtype]) |
308 | + subject_removed.emit(mtype, subject); |
309 | + |
310 | + subjects_.erase(mtype); |
311 | + monitors_.erase(mtype); |
312 | +} |
313 | + |
314 | +} |
315 | +} |
316 | |
317 | === added file 'UnityCore/ZeitgeistApplication.h' |
318 | --- UnityCore/ZeitgeistApplication.h 1970-01-01 00:00:00 +0000 |
319 | +++ UnityCore/ZeitgeistApplication.h 2012-02-28 17:40:24 +0000 |
320 | @@ -0,0 +1,86 @@ |
321 | +// -*- Mode: C++; indent-tabs-mode: nil; tab-width: 2 -*- |
322 | +/* |
323 | + * Copyright (C) 2012 Canonical Ltd |
324 | + * |
325 | + * This program is free software: you can redistribute it and/or modify |
326 | + * it under the terms of the GNU General Public License version 3 as |
327 | + * published by the Free Software Foundation. |
328 | + * |
329 | + * This program is distributed in the hope that it will be useful, |
330 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
331 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
332 | + * GNU General Public License for more details. |
333 | + * |
334 | + * You should have received a copy of the GNU General Public License |
335 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
336 | + * |
337 | + * Authored by: Marco Trevisan (Treviño) <3v1n0@ubuntu.com> |
338 | + */ |
339 | + |
340 | +#ifndef UNITY_ZEITGEIST_APPLICATION_H |
341 | +#define UNITY_ZEITGEIST_APPLICATION_H |
342 | + |
343 | +#include <zeitgeist.h> |
344 | + |
345 | +#include <sigc++/signal.h> |
346 | +#include <deque> |
347 | +#include <map> |
348 | + |
349 | +#include "ZeitgeistSubject.h" |
350 | +#include "GLibSignal.h" |
351 | + |
352 | +namespace unity |
353 | +{ |
354 | +namespace zeitgeist |
355 | +{ |
356 | + |
357 | +class Application : public sigc::trackable, boost::noncopyable |
358 | +{ |
359 | +public: |
360 | + typedef boost::shared_ptr<Application> Ptr; |
361 | + typedef std::deque<Subject::Ptr> Subjects; |
362 | + |
363 | + Application(std::string const& desktop_file); |
364 | + ~Application(); |
365 | + |
366 | + enum MonitorType |
367 | + { |
368 | + MOST_RECENT_EVENTS = 1, |
369 | + LEAST_RECENT_EVENTS, |
370 | + MOST_RECENT_SUBJECTS, |
371 | + LEAST_RECENT_SUBJECTS, |
372 | + MOST_POPULAR_SUBJECTS, |
373 | + LEAST_POPULAR_SUBJECTS, |
374 | + RELEVANCY |
375 | + }; |
376 | + |
377 | + std::string const& Uri() const; |
378 | + |
379 | + void AddMonitor(MonitorType type, unsigned int pool_size = 10); |
380 | + void RemoveMonitor(MonitorType type); |
381 | + |
382 | + Subjects GetSubjectsForMonitor(MonitorType type) const; |
383 | + |
384 | + // Signals |
385 | + sigc::signal<void, MonitorType, Subject::Ptr const&> subject_added; |
386 | + sigc::signal<void, MonitorType, Subject::Ptr const&> subject_removed; |
387 | + |
388 | +private: |
389 | + ZeitgeistResultType GetResultTypeByMonitorType(MonitorType mtype); |
390 | + void HandleResultSet(glib::Object<ZeitgeistResultSet> const& results, MonitorType mtype); |
391 | + |
392 | + glib::Object<ZeitgeistLog> log_; |
393 | + glib::Object<ZeitgeistEvent> application_event_; |
394 | + std::string application_uri_; |
395 | + glib::SignalManager signal_manager_; |
396 | + |
397 | + std::map<MonitorType, glib::Object<ZeitgeistMonitor>> monitors_; |
398 | + std::map<MonitorType, Subjects> subjects_; |
399 | + std::map<MonitorType, unsigned int> subjects_pools_; |
400 | +}; |
401 | + |
402 | + |
403 | +} |
404 | +} |
405 | + |
406 | +#endif // UNITY_ZEITGEIST_APPLICATION_H |
407 | |
408 | === added file 'UnityCore/ZeitgeistSubject.cpp' |
409 | --- UnityCore/ZeitgeistSubject.cpp 1970-01-01 00:00:00 +0000 |
410 | +++ UnityCore/ZeitgeistSubject.cpp 2012-02-28 17:40:24 +0000 |
411 | @@ -0,0 +1,91 @@ |
412 | +// -*- Mode: C++; indent-tabs-mode: nil; tab-width: 2 -*- |
413 | +/* |
414 | + * Copyright (C) 2012 Canonical Ltd |
415 | + * |
416 | + * This program is free software: you can redistribute it and/or modify |
417 | + * it under the terms of the GNU General Public License version 3 as |
418 | + * published by the Free Software Foundation. |
419 | + * |
420 | + * This program is distributed in the hope that it will be useful, |
421 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
422 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
423 | + * GNU General Public License for more details. |
424 | + * |
425 | + * You should have received a copy of the GNU General Public License |
426 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
427 | + * |
428 | + * Authored by: Marco Trevisan (Treviño) <3v1n0@ubuntu.com> |
429 | + */ |
430 | + |
431 | +#include "ZeitgeistSubject.h" |
432 | + |
433 | +namespace unity |
434 | +{ |
435 | +namespace zeitgeist |
436 | +{ |
437 | + |
438 | +Subject::Subject(glib::Object<ZeitgeistSubject> const& subject, unsigned int id, long long timestamp) |
439 | + : subject_(subject, glib::AddRef()), |
440 | + event_id_(id), |
441 | + event_timestamp_(timestamp) |
442 | +{} |
443 | + |
444 | +unsigned int Subject::EventId() const |
445 | +{ |
446 | + return event_id_; |
447 | +} |
448 | + |
449 | +long long Subject::EventTimestamp() const |
450 | +{ |
451 | + return event_timestamp_; |
452 | +} |
453 | + |
454 | +std::string Subject::GetConstString(const gchar* str) |
455 | +{ |
456 | + return (str) ? str : ""; |
457 | +} |
458 | + |
459 | +std::string Subject::Interpretation() const |
460 | +{ |
461 | + const gchar* str = zeitgeist_subject_get_interpretation(subject_); |
462 | + return GetConstString(str); |
463 | +} |
464 | + |
465 | +std::string Subject::Manifestation() const |
466 | +{ |
467 | + const gchar* str = zeitgeist_subject_get_manifestation(subject_); |
468 | + return GetConstString(str); |
469 | +} |
470 | + |
471 | +std::string Subject::MimeType() const |
472 | +{ |
473 | + const gchar* str = zeitgeist_subject_get_mimetype(subject_); |
474 | + return GetConstString(str); |
475 | +} |
476 | + |
477 | +std::string Subject::Origin() const |
478 | +{ |
479 | + const gchar* str = zeitgeist_subject_get_origin(subject_); |
480 | + return GetConstString(str); |
481 | +} |
482 | + |
483 | +std::string Subject::Storage() const |
484 | +{ |
485 | + const gchar* str = zeitgeist_subject_get_storage(subject_); |
486 | + return GetConstString(str); |
487 | +} |
488 | + |
489 | +std::string Subject::Text() const |
490 | +{ |
491 | + const gchar* str = zeitgeist_subject_get_text(subject_); |
492 | + return GetConstString(str); |
493 | +} |
494 | + |
495 | +std::string Subject::Uri() const |
496 | +{ |
497 | + const gchar* str = zeitgeist_subject_get_uri(subject_); |
498 | + return GetConstString(str); |
499 | +} |
500 | + |
501 | +} // namespace zeitgeist |
502 | +} // namespace unity |
503 | |
504 | === added file 'UnityCore/ZeitgeistSubject.h' |
505 | --- UnityCore/ZeitgeistSubject.h 1970-01-01 00:00:00 +0000 |
506 | +++ UnityCore/ZeitgeistSubject.h 2012-02-28 17:40:24 +0000 |
507 | @@ -0,0 +1,64 @@ |
508 | +// -*- Mode: C++; indent-tabs-mode: nil; tab-width: 2 -*- |
509 | +/* |
510 | + * Copyright (C) 2012 Canonical Ltd |
511 | + * |
512 | + * This program is free software: you can redistribute it and/or modify |
513 | + * it under the terms of the GNU General Public License version 3 as |
514 | + * published by the Free Software Foundation. |
515 | + * |
516 | + * This program is distributed in the hope that it will be useful, |
517 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
518 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
519 | + * GNU General Public License for more details. |
520 | + * |
521 | + * You should have received a copy of the GNU General Public License |
522 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
523 | + * |
524 | + * Authored by: Marco Trevisan (Treviño) <3v1n0@ubuntu.com> |
525 | + */ |
526 | + |
527 | +#ifndef UNITY_ZEITGEIST_SUBJECT_H |
528 | +#define UNITY_ZEITGEIST_SUBJECT_H |
529 | + |
530 | +#include <zeitgeist.h> |
531 | +#include <boost/utility.hpp> |
532 | +#include <boost/shared_ptr.hpp> |
533 | + |
534 | +#include "GLibWrapper.h" |
535 | + |
536 | +namespace unity |
537 | +{ |
538 | +namespace zeitgeist |
539 | +{ |
540 | + |
541 | +class Subject : public boost::noncopyable |
542 | +{ |
543 | +public: |
544 | + typedef boost::shared_ptr<Subject> Ptr; |
545 | + |
546 | + unsigned int EventId() const; |
547 | + long long EventTimestamp() const; |
548 | + |
549 | + std::string Interpretation() const; |
550 | + std::string Manifestation() const; |
551 | + std::string MimeType() const; |
552 | + std::string Origin() const; |
553 | + std::string Storage() const; |
554 | + std::string Text() const; |
555 | + std::string Uri() const; |
556 | + |
557 | +private: |
558 | + Subject(glib::Object<ZeitgeistSubject> const& subject, unsigned int id, long long timestamp); |
559 | + static std::string GetConstString(const gchar* str); |
560 | + |
561 | + glib::Object<ZeitgeistSubject> subject_; |
562 | + unsigned int event_id_; |
563 | + long long event_timestamp_; |
564 | + |
565 | + friend class Application; |
566 | +}; |
567 | + |
568 | +} |
569 | +} |
570 | + |
571 | +#endif // UNITY_ZEITGEIST_SUBJECT_H |
572 | |
573 | === modified file 'plugins/unityshell/src/BamfLauncherIcon.cpp' |
574 | --- plugins/unityshell/src/BamfLauncherIcon.cpp 2012-02-22 02:17:08 +0000 |
575 | +++ plugins/unityshell/src/BamfLauncherIcon.cpp 2012-02-28 17:40:24 +0000 |
576 | @@ -70,52 +70,52 @@ |
577 | glib::SignalBase* sig; |
578 | |
579 | sig = new glib::Signal<void, BamfView*, BamfView*>(bamf_view, "child-added", |
580 | - [&] (BamfView*, BamfView*) { |
581 | - EnsureWindowState(); |
582 | - UpdateMenus(); |
583 | - UpdateIconGeometries(GetCenters()); |
584 | - }); |
585 | + [&] (BamfView*, BamfView*) { |
586 | + EnsureWindowState(); |
587 | + UpdateMenus(); |
588 | + UpdateIconGeometries(GetCenters()); |
589 | + }); |
590 | _gsignals.Add(sig); |
591 | |
592 | sig = new glib::Signal<void, BamfView*, BamfView*>(bamf_view, "child-removed", |
593 | [&] (BamfView*, BamfView*) { EnsureWindowState(); }); |
594 | _gsignals.Add(sig); |
595 | |
596 | - sig = new glib::Signal<void, BamfView*, gboolean>(bamf_view, "urgent-changed", |
597 | - [&] (BamfView*, gboolean urgent) { |
598 | - SetQuirk(QUIRK_URGENT, urgent); |
599 | - }); |
600 | - _gsignals.Add(sig); |
601 | - |
602 | - sig = new glib::Signal<void, BamfView*, gboolean>(bamf_view, "active-changed", |
603 | - [&] (BamfView*, gboolean active) { |
604 | - SetQuirk(QUIRK_ACTIVE, active); |
605 | - }); |
606 | - _gsignals.Add(sig); |
607 | - |
608 | - sig = new glib::Signal<void, BamfView*, gboolean>(bamf_view, "running-changed", |
609 | - [&] (BamfView*, gboolean running) { |
610 | - SetQuirk(QUIRK_RUNNING, running); |
611 | - if (running) |
612 | - { |
613 | - EnsureWindowState(); |
614 | - UpdateIconGeometries(GetCenters()); |
615 | - } |
616 | - }); |
617 | - _gsignals.Add(sig); |
618 | - |
619 | - sig = new glib::Signal<void, BamfView*, gboolean>(bamf_view, "user-visible-changed", |
620 | - [&] (BamfView*, gboolean visible) { |
621 | - if (!IsSticky()) |
622 | - SetQuirk(QUIRK_VISIBLE, visible); |
623 | - }); |
624 | + sig = new BamfPropertyChangedSignal(bamf_view, "urgent-changed", |
625 | + [&] (BamfView*, gboolean urgent) { |
626 | + SetQuirk(QUIRK_URGENT, urgent); |
627 | + }); |
628 | + _gsignals.Add(sig); |
629 | + |
630 | + sig = new BamfPropertyChangedSignal(bamf_view, "active-changed", |
631 | + [&] (BamfView*, gboolean active) { |
632 | + SetQuirk(QUIRK_ACTIVE, active); |
633 | + }); |
634 | + _gsignals.Add(sig); |
635 | + |
636 | + sig = new BamfPropertyChangedSignal(bamf_view, "running-changed", |
637 | + [&] (BamfView*, gboolean running) { |
638 | + SetQuirk(QUIRK_RUNNING, running); |
639 | + if (running) |
640 | + { |
641 | + EnsureWindowState(); |
642 | + UpdateIconGeometries(GetCenters()); |
643 | + } |
644 | + }); |
645 | + _gsignals.Add(sig); |
646 | + |
647 | + sig = new BamfPropertyChangedSignal(bamf_view, "user-visible-changed", |
648 | + [&] (BamfView*, gboolean visible) { |
649 | + if (!IsSticky()) |
650 | + SetQuirk(QUIRK_VISIBLE, visible); |
651 | + }); |
652 | _gsignals.Add(sig); |
653 | |
654 | sig = new glib::Signal<void, BamfView*>(bamf_view, "closed", |
655 | - [&] (BamfView*) { |
656 | - if (!IsSticky()) |
657 | - Remove(); |
658 | - }); |
659 | + [&] (BamfView*) { |
660 | + if (!IsSticky()) |
661 | + Remove(); |
662 | + }); |
663 | _gsignals.Add(sig); |
664 | |
665 | WindowManager::Default()->window_minimized.connect(sigc::mem_fun(this, &BamfLauncherIcon::OnWindowMinimized)); |
666 | @@ -126,6 +126,7 @@ |
667 | EnsureWindowState(); |
668 | UpdateMenus(); |
669 | UpdateDesktopFile(); |
670 | + SetupZeitgeistMonitor(); |
671 | |
672 | // hack |
673 | SetProgress(0.0f); |
674 | @@ -416,6 +417,7 @@ |
675 | break; |
676 | case G_FILE_MONITOR_EVENT_CHANGES_DONE_HINT: |
677 | UpdateDesktopQuickList(); |
678 | + SetupZeitgeistMonitor(); |
679 | break; |
680 | default: |
681 | break; |
682 | @@ -707,12 +709,12 @@ |
683 | dbusmenu_menuitem_property_set_bool(item, DBUSMENU_MENUITEM_PROP_VISIBLE, TRUE); |
684 | dbusmenu_menuitem_property_set(item, "shortcut-nick", nicks[index]); |
685 | |
686 | - auto sig = new glib::Signal<void, DbusmenuMenuitem*, gint>(item, "item-activated", |
687 | - [&] (DbusmenuMenuitem* item, gint) { |
688 | - const gchar *nick; |
689 | - nick = dbusmenu_menuitem_property_get(item, "shortcut-nick"); |
690 | - indicator_desktop_shortcuts_nick_exec(_desktop_shortcuts, nick); |
691 | - }); |
692 | + auto sig = new MenuitemActivateSignal(item, "item-activated", |
693 | + [&] (DbusmenuMenuitem* item, gint) { |
694 | + const gchar *nick; |
695 | + nick = dbusmenu_menuitem_property_get(item, "shortcut-nick"); |
696 | + indicator_desktop_shortcuts_nick_exec(_desktop_shortcuts, nick); |
697 | + }); |
698 | _gsignals.Add(sig); |
699 | |
700 | dbusmenu_menuitem_child_append(_menu_desktop_shortcuts, item); |
701 | @@ -837,10 +839,10 @@ |
702 | dbusmenu_menuitem_property_set_bool(menu_item, DBUSMENU_MENUITEM_PROP_ENABLED, true); |
703 | dbusmenu_menuitem_property_set_bool(menu_item, DBUSMENU_MENUITEM_PROP_VISIBLE, true); |
704 | |
705 | - _gsignals.Add(new glib::Signal<void, DbusmenuMenuitem*, int>(menu_item, DBUSMENU_MENUITEM_SIGNAL_ITEM_ACTIVATED, |
706 | - [&] (DbusmenuMenuitem*, int) { |
707 | - ToggleSticky(); |
708 | - })); |
709 | + _gsignals.Add(new MenuitemActivateSignal(menu_item, DBUSMENU_MENUITEM_SIGNAL_ITEM_ACTIVATED, |
710 | + [&] (DbusmenuMenuitem*, int) { |
711 | + ToggleSticky(); |
712 | + })); |
713 | |
714 | _menu_items["Pin"] = glib::Object<DbusmenuMenuitem>(menu_item); |
715 | } |
716 | @@ -858,10 +860,10 @@ |
717 | dbusmenu_menuitem_property_set_bool(menu_item, DBUSMENU_MENUITEM_PROP_ENABLED, true); |
718 | dbusmenu_menuitem_property_set_bool(menu_item, DBUSMENU_MENUITEM_PROP_VISIBLE, true); |
719 | |
720 | - _gsignals.Add(new glib::Signal<void, DbusmenuMenuitem*, int>(menu_item, DBUSMENU_MENUITEM_SIGNAL_ITEM_ACTIVATED, |
721 | - [&] (DbusmenuMenuitem*, int) { |
722 | - Quit(); |
723 | - })); |
724 | + _gsignals.Add(new MenuitemActivateSignal(menu_item, DBUSMENU_MENUITEM_SIGNAL_ITEM_ACTIVATED, |
725 | + [&] (DbusmenuMenuitem*, int) { |
726 | + Quit(); |
727 | + })); |
728 | |
729 | _menu_items["Quit"] = glib::Object<DbusmenuMenuitem>(menu_item); |
730 | } |
731 | @@ -901,6 +903,7 @@ |
732 | } |
733 | } |
734 | } |
735 | + |
736 | |
737 | // FIXME: this should totally be added as a _menu_client |
738 | if (DBUSMENU_IS_MENUITEM(_menu_desktop_shortcuts.RawPtr())) |
739 | @@ -960,10 +963,10 @@ |
740 | "unity-use-markup", |
741 | true); |
742 | |
743 | - _gsignals.Add(new glib::Signal<void, DbusmenuMenuitem*, int>(item, DBUSMENU_MENUITEM_SIGNAL_ITEM_ACTIVATED, |
744 | - [&] (DbusmenuMenuitem*, int) { |
745 | - ActivateLauncherIcon(ActionArg(ActionArg::OTHER, 0)); |
746 | - })); |
747 | + _gsignals.Add(new MenuitemActivateSignal(item, DBUSMENU_MENUITEM_SIGNAL_ITEM_ACTIVATED, |
748 | + [&] (DbusmenuMenuitem*, int) { |
749 | + ActivateLauncherIcon(ActionArg(ActionArg::OTHER, 0)); |
750 | + })); |
751 | |
752 | _menu_items_extra["AppName"] = glib::Object<DbusmenuMenuitem>(item); |
753 | } |
754 | @@ -984,6 +987,29 @@ |
755 | } |
756 | result.push_back(item); |
757 | |
758 | + for (auto it = _menu_items_zeitgeist.begin(); it != _menu_items_zeitgeist.end(); ++it) |
759 | + { |
760 | + result.push_back(it->second.RawPtr()); |
761 | + } |
762 | + |
763 | + if (_menu_items_zeitgeist.size() > 0) |
764 | + { |
765 | + auto third_separator = _menu_items_extra.find("ThirdSeparator"); |
766 | + if (third_separator != _menu_items_extra.end()) |
767 | + { |
768 | + item = third_separator->second; |
769 | + } |
770 | + else |
771 | + { |
772 | + item = dbusmenu_menuitem_new(); |
773 | + dbusmenu_menuitem_property_set(item, |
774 | + DBUSMENU_MENUITEM_PROP_TYPE, |
775 | + DBUSMENU_CLIENT_TYPES_SEPARATOR); |
776 | + _menu_items_extra["ThirdSeparator"] = glib::Object<DbusmenuMenuitem>(item); |
777 | + } |
778 | + result.push_back(item); |
779 | + } |
780 | + |
781 | EnsureMenuItemsReady(); |
782 | |
783 | for (auto it_m = _menu_items.begin(); it_m != _menu_items.end(); ++it_m) |
784 | @@ -1231,6 +1257,99 @@ |
785 | } |
786 | } |
787 | |
788 | +void BamfLauncherIcon::SetupZeitgeistMonitor() |
789 | +{ |
790 | + const std::string keyname = "X-Ayatana-Show-Recent-Files"; |
791 | + bool enabled = true; |
792 | + |
793 | + if (_desktop_file.empty()) |
794 | + { |
795 | + enabled = false; |
796 | + } |
797 | + else |
798 | + { |
799 | + glib::Error error; |
800 | + GKeyFile* keyfile = g_key_file_new(); |
801 | + |
802 | + g_key_file_load_from_file(keyfile, _desktop_file.c_str(), G_KEY_FILE_NONE, &error); |
803 | + |
804 | + if (error) |
805 | + { |
806 | + enabled = false; |
807 | + g_key_file_free(keyfile); |
808 | + } |
809 | + else if (g_key_file_has_key(keyfile, G_KEY_FILE_DESKTOP_GROUP, keyname.c_str(), nullptr)) |
810 | + { |
811 | + enabled = g_key_file_get_boolean(keyfile, G_KEY_FILE_DESKTOP_GROUP, keyname.c_str(), nullptr); |
812 | + } |
813 | + |
814 | + g_key_file_free(keyfile); |
815 | + } |
816 | + |
817 | + if (!enabled && _zeitgeist_app.get()) |
818 | + { |
819 | + _zeitgeist_app->RemoveMonitor(zeitgeist::Application::MOST_RECENT_SUBJECTS); |
820 | + _zeitgeist_app.reset(); |
821 | + } |
822 | + else if (enabled && !_zeitgeist_app.get()) |
823 | + { |
824 | + _zeitgeist_app.reset(new zeitgeist::Application(_desktop_file)); |
825 | + _zeitgeist_app->subject_added.connect(sigc::mem_fun(this, &BamfLauncherIcon::OnZeitgeistSubjectAdded)); |
826 | + _zeitgeist_app->subject_removed.connect(sigc::mem_fun(this, &BamfLauncherIcon::OnZeitgeistSubjectRemoved)); |
827 | + _zeitgeist_app->AddMonitor(zeitgeist::Application::MOST_RECENT_SUBJECTS, 5); |
828 | + } |
829 | +} |
830 | + |
831 | +void BamfLauncherIcon::OnZeitgeistSubjectAdded(zeitgeist::Application::MonitorType mtype, |
832 | + zeitgeist::Subject::Ptr const& subject) |
833 | +{ |
834 | + if (mtype != zeitgeist::Application::MOST_RECENT_SUBJECTS) |
835 | + return; |
836 | + |
837 | + glib::Object<DbusmenuMenuitem> menu_item(dbusmenu_menuitem_new()); |
838 | + dbusmenu_menuitem_property_set(menu_item, DBUSMENU_MENUITEM_PROP_LABEL, subject->Text().c_str()); |
839 | + dbusmenu_menuitem_property_set_bool(menu_item, DBUSMENU_MENUITEM_PROP_ENABLED, true); |
840 | + dbusmenu_menuitem_property_set_bool(menu_item, DBUSMENU_MENUITEM_PROP_VISIBLE, true); |
841 | + |
842 | + _gsignals.Add(new MenuitemActivateSignal(menu_item, DBUSMENU_MENUITEM_SIGNAL_ITEM_ACTIVATED, |
843 | + [&] (DbusmenuMenuitem* item, int) |
844 | + { |
845 | + for (auto zmenuitem : _menu_items_zeitgeist) |
846 | + { |
847 | + if (zmenuitem.second == item) |
848 | + { |
849 | + std::string const& uri = zmenuitem.first->Uri(); |
850 | + if (!uri.empty()) |
851 | + { |
852 | + std::set<std::string> uris; |
853 | + uris.insert(uri); |
854 | + OpenInstanceWithUris(uris); |
855 | + } |
856 | + break; |
857 | + } |
858 | + } |
859 | + })); |
860 | + |
861 | + _menu_items_zeitgeist.push_front(ZeitgeistMenuitem(subject, menu_item)); |
862 | +} |
863 | + |
864 | +void BamfLauncherIcon::OnZeitgeistSubjectRemoved(zeitgeist::Application::MonitorType mtype, |
865 | + zeitgeist::Subject::Ptr const& subject) |
866 | +{ |
867 | + if (mtype != zeitgeist::Application::MOST_RECENT_SUBJECTS) |
868 | + return; |
869 | + |
870 | + for (auto it = _menu_items_zeitgeist.begin(); it != _menu_items_zeitgeist.end(); ++it) |
871 | + { |
872 | + if (it->first == subject) |
873 | + { |
874 | + _gsignals.Disconnect(it->second.RawPtr(), DBUSMENU_MENUITEM_SIGNAL_ITEM_ACTIVATED); |
875 | + _menu_items_zeitgeist.erase(it); |
876 | + break; |
877 | + } |
878 | + } |
879 | +} |
880 | + |
881 | std::string BamfLauncherIcon::GetName() const |
882 | { |
883 | return "BamfLauncherIcon"; |
884 | |
885 | === modified file 'plugins/unityshell/src/BamfLauncherIcon.h' |
886 | --- plugins/unityshell/src/BamfLauncherIcon.h 2012-02-12 10:43:11 +0000 |
887 | +++ plugins/unityshell/src/BamfLauncherIcon.h 2012-02-28 17:40:24 +0000 |
888 | @@ -23,6 +23,7 @@ |
889 | |
890 | #include <UnityCore/GLibSignal.h> |
891 | #include <UnityCore/GLibWrapper.h> |
892 | +#include <UnityCore/ZeitgeistApplication.h> |
893 | |
894 | #include <libbamf/libbamf.h> |
895 | #include <libindicator/indicator-desktop-shortcuts.h> |
896 | @@ -93,6 +94,7 @@ |
897 | void UpdateMenus(); |
898 | void UpdateDesktopQuickList(); |
899 | void FillSupportedTypes(); |
900 | + void SetupZeitgeistMonitor(); |
901 | |
902 | void OpenInstanceWithUris(std::set<std::string> uris); |
903 | void Focus(ActionArg arg); |
904 | @@ -100,11 +102,18 @@ |
905 | |
906 | void OnWindowMinimized(guint32 xid); |
907 | void OnWindowMoved(guint32 xid); |
908 | + void OnZeitgeistSubjectAdded(zeitgeist::Application::MonitorType mtype, |
909 | + zeitgeist::Subject::Ptr const& subject); |
910 | + void OnZeitgeistSubjectRemoved(zeitgeist::Application::MonitorType mtype, |
911 | + zeitgeist::Subject::Ptr const& subject); |
912 | |
913 | bool OwnsWindow(Window w) const; |
914 | |
915 | const std::set<std::string>& GetSupportedTypes(); |
916 | |
917 | + typedef glib::Signal<void, BamfView*, gboolean> BamfPropertyChangedSignal; |
918 | + typedef glib::Signal<void, DbusmenuMenuitem*, int> MenuitemActivateSignal; |
919 | + typedef std::pair<zeitgeist::Subject::Ptr, glib::Object<DbusmenuMenuitem>> ZeitgeistMenuitem; |
920 | |
921 | glib::Object<BamfApplication> _bamf_app; |
922 | bool _dnd_hovered; |
923 | @@ -116,10 +125,12 @@ |
924 | |
925 | std::string _remote_uri; |
926 | std::string _desktop_file; |
927 | + zeitgeist::Application::Ptr _zeitgeist_app; |
928 | std::set<std::string> _supported_types; |
929 | std::map<std::string, glib::Object<DbusmenuClient>> _menu_clients; |
930 | std::map<std::string, glib::Object<DbusmenuMenuitem>> _menu_items; |
931 | std::map<std::string, glib::Object<DbusmenuMenuitem>> _menu_items_extra; |
932 | + std::deque<ZeitgeistMenuitem> _menu_items_zeitgeist; |
933 | glib::Object<IndicatorDesktopShortcuts> _desktop_shortcuts; |
934 | glib::Object<DbusmenuMenuitem> _menu_desktop_shortcuts; |
935 | glib::Object<GFileMonitor> _desktop_file_monitor; |
> std::string const& basename = glib::String( g_path_ get_basename( desktop_ file.c_ str())) .Str();
This takes a reference to a temporary. Remove the "const&" bit.
If you have a shared log, why delete it when the last reference was there? why not let the log just live on?
> UnityCore/ ZeitgeistSubjec t.cpp
Has the same two lines about 6 times. Consider a simple function.
The ZeitgeistSubject is obviously not meant to be inherited from, so please don't add a protected section.
Secondly, please don't use friend. What is wrong with having a public constructor?
As you mentioned, this branch is missing tests. A key question is how to ensure it is working.
What needs to exist for this to work properly? How can we minimally test it?
We need to export the relevant bits through autopilot, then we can have some functional tests that show when we do "stuff" we get "other stuff" showing in the quicklists.