Merge lp:~3v1n0/unity/zeitgeist-quicklists into lp:unity

Proposed by Marco Trevisan (Treviño)
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
Reviewer Review Type Date Requested Status
Tim Penhey (community) Needs Fixing
Review via email: mp+93126@code.launchpad.net

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, ZeitgeistApplication and ZeitgeistSubject:

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.

ZeitgeistApplication is the main class to be used in unity and allows to define some kinds of event monitors for the given application.
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 ZeitgeistApplication to receive the events and to generate the quicklist items with the last recent items. Each .desktop file can disable this list of recent files setting to false the "X-Ayatana-Show-Recent-Files" key.

To post a comment you must log in.
lp:~3v1n0/unity/zeitgeist-quicklists updated
1978. By Marco Trevisan (Treviño)

ZeitgeistApplication: some string optimization...

1979. By Marco Trevisan (Treviño)

ZeitgeistApplication: 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)

ZeitgeistApplication: don't use a pointer to handle the shared log...

1982. By Marco Trevisan (Treviño)

ZeitgeistApplication: use manifestation and reorder the received items

Revision history for this message
Tim Penhey (thumper) wrote :

> 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/ZeitgeistSubject.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.

review: Needs Fixing
Revision history for this message
Marco Trevisan (Treviño) (3v1n0) wrote :

> > 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.

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/ZeitgeistSubject.cpp
>
> 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://paste.ubuntu.com/860690/ ?

> 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 ZetigeistApplication should be able to provide. But if you prefer to avoid to use friends, I'll move it out.

> 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.

Revision history for this message
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_log_get_default, but it wouldn't be destroyed anyway when all the Application instances would be removed.

lp:~3v1n0/unity/zeitgeist-quicklists updated
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.

Revision history for this message
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.

lp:~3v1n0/unity/zeitgeist-quicklists updated
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

Revision history for this message
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)

ZeitgeistApplication: use manifestation and reorder the received items

1981. By Marco Trevisan (Treviño)

ZeitgeistApplication: 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)

ZeitgeistApplication: share the instance of ZeitgeistLog, fix memory leaks

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'CMakeLists.txt'
--- CMakeLists.txt 2012-02-23 07:43:46 +0000
+++ CMakeLists.txt 2012-02-28 17:40:24 +0000
@@ -122,7 +122,7 @@
122#122#
123# Compiz Plugins123# Compiz Plugins
124#124#
125set (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")125set (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")
126126
127add_subdirectory(plugins/unityshell)127add_subdirectory(plugins/unityshell)
128add_subdirectory(plugins/gtkloader)128add_subdirectory(plugins/gtkloader)
129129
=== modified file 'UnityCore/CMakeLists.txt'
--- UnityCore/CMakeLists.txt 2012-02-07 07:42:12 +0000
+++ UnityCore/CMakeLists.txt 2012-02-28 17:40:24 +0000
@@ -1,5 +1,5 @@
1find_package (PkgConfig)1find_package (PkgConfig)
2pkg_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)2pkg_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)
33
4execute_process (COMMAND ${PKG_CONFIG_EXECUTABLE} unity --variable lensesdir OUTPUT_VARIABLE _lensesdir OUTPUT_STRIP_TRAILING_WHITESPACE)4execute_process (COMMAND ${PKG_CONFIG_EXECUTABLE} unity --variable lensesdir OUTPUT_VARIABLE _lensesdir OUTPUT_STRIP_TRAILING_WHITESPACE)
55
@@ -40,6 +40,8 @@
40 Result.h40 Result.h
41 Results.h41 Results.h
42 Variant.h42 Variant.h
43 ZeitgeistApplication.h
44 ZeitgeistSubject.h
43 )45 )
4446
45set (CORE_SOURCES47set (CORE_SOURCES
@@ -70,6 +72,8 @@
70 Result.cpp72 Result.cpp
71 Results.cpp73 Results.cpp
72 Variant.cpp74 Variant.cpp
75 ZeitgeistApplication.cpp
76 ZeitgeistSubject.cpp
73 )77 )
7478
75#79#
7680
=== added file 'UnityCore/ZeitgeistApplication.cpp'
--- UnityCore/ZeitgeistApplication.cpp 1970-01-01 00:00:00 +0000
+++ UnityCore/ZeitgeistApplication.cpp 2012-02-28 17:40:24 +0000
@@ -0,0 +1,269 @@
1// -*- Mode: C++; indent-tabs-mode: nil; tab-width: 2 -*-
2/*
3 * Copyright (C) 2012 Canonical Ltd
4 *
5 * This program is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License version 3 as
7 * published by the Free Software Foundation.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program. If not, see <http://www.gnu.org/licenses/>.
16 *
17 * Authored by: Marco Trevisan (Treviño) <3v1n0@ubuntu.com>
18 */
19
20#include "ZeitgeistApplication.h"
21
22namespace unity
23{
24namespace zeitgeist
25{
26static glib::Object<ZeitgeistLog> shared_log_;
27
28Application::Application(std::string const& desktop_file)
29 : application_event_(zeitgeist_event_new())
30{
31 if (!shared_log_ || !ZEITGEIST_IS_LOG(shared_log_.RawPtr()))
32 {
33 shared_log_ = glib::Object<ZeitgeistLog>(zeitgeist_log_new());
34 }
35
36 log_ = shared_log_;
37
38 if (!desktop_file.empty())
39 {
40 std::string basename = glib::String(g_path_get_basename(desktop_file.c_str())).Str();
41
42 if (!basename.empty())
43 {
44 const std::string prefix = "application://";
45 application_uri_ = prefix + basename;
46
47 ZeitgeistSubject* subj = zeitgeist_subject_new();
48 glib::Object<ZeitgeistSubject> application_subject(subj, glib::AddRef());
49 zeitgeist_subject_set_manifestation(application_subject, "!" ZEITGEIST_NFO_SOFTWARE_ITEM);
50 zeitgeist_event_add_subject(application_event_, application_subject);
51 zeitgeist_event_set_actor(application_event_, application_uri_.c_str());
52 }
53 }
54}
55
56Application::~Application()
57{
58 if (ZEITGEIST_IS_LOG(shared_log_.RawPtr()))
59 {
60 auto glog = reinterpret_cast<GObject*>(shared_log_.RawPtr());
61
62 /* If the log has 2 references we can safely nullify the shared instance
63 * In fact, at this point both the application log_ member and the
64 * shared member owns a reference, that's why of this "magic" number */
65 if (glog->ref_count == 2)
66 {
67 shared_log_ = nullptr;
68 }
69 }
70 else if (shared_log_)
71 {
72 shared_log_ = nullptr;
73 }
74}
75
76std::string const& Application::Uri() const
77{
78 return application_uri_;
79}
80
81ZeitgeistResultType Application::GetResultTypeByMonitorType(MonitorType mtype)
82{
83 switch (mtype)
84 {
85 case MOST_RECENT_EVENTS:
86 return ZEITGEIST_RESULT_TYPE_MOST_RECENT_EVENTS;
87 case LEAST_RECENT_EVENTS:
88 return ZEITGEIST_RESULT_TYPE_LEAST_RECENT_EVENTS;
89 case MOST_RECENT_SUBJECTS:
90 return ZEITGEIST_RESULT_TYPE_MOST_RECENT_SUBJECTS;
91 case LEAST_RECENT_SUBJECTS:
92 return ZEITGEIST_RESULT_TYPE_LEAST_RECENT_SUBJECTS;
93 case MOST_POPULAR_SUBJECTS:
94 return ZEITGEIST_RESULT_TYPE_MOST_POPULAR_SUBJECTS;
95 case LEAST_POPULAR_SUBJECTS:
96 return ZEITGEIST_RESULT_TYPE_LEAST_POPULAR_SUBJECTS;
97 default:
98 return ZEITGEIST_RESULT_TYPE_RELEVANCY;
99 }
100}
101
102void Application::HandleResultSet(glib::Object<ZeitgeistResultSet> const& results, MonitorType mtype)
103{
104 Subjects& subjects = subjects_[mtype];
105 std::deque<std::pair<ZeitgeistEvent*, ZeitgeistSubject*>> new_subjects;
106 unsigned int max_items = subjects_pools_[mtype];
107
108 // Reversing the list of the new items.
109 while (zeitgeist_result_set_has_next(results))
110 {
111 ZeitgeistEvent* event = zeitgeist_result_set_next(results);
112
113 for (int i = 0; i < zeitgeist_event_num_subjects(event); ++i)
114 {
115 ZeitgeistSubject* subj = zeitgeist_event_get_subject(event, i);
116 if (!ZEITGEIST_IS_SUBJECT(subj))
117 continue;
118
119 std::pair<ZeitgeistEvent*, ZeitgeistSubject*> new_event(event, subj);
120 new_subjects.push_front(new_event);
121 }
122 }
123
124 for (auto new_pair : new_subjects)
125 {
126 ZeitgeistEvent* event = new_pair.first;
127 guint32 event_id = zeitgeist_event_get_id(event);
128 gint64 timestamp = zeitgeist_event_get_timestamp(event);
129
130 glib::Object<ZeitgeistSubject> gsubject(new_pair.second, glib::AddRef());
131 Subject::Ptr subject_ptr(new Subject(gsubject, event_id, timestamp));
132
133 for (auto it = subjects.begin(); it != subjects.end(); ++it)
134 {
135 if ((*it)->Uri() == subject_ptr->Uri())
136 {
137 subject_removed.emit(mtype, *it);
138 subjects.erase(it);
139 break;
140 }
141 }
142
143 if (subjects.size() == max_items)
144 {
145 subject_removed.emit(mtype, subjects.front());
146 subjects.pop_front();
147 }
148
149 subjects.push_back(subject_ptr);
150 subject_added.emit(mtype, subject_ptr);
151 }
152}
153
154void Application::AddMonitor(MonitorType mtype, unsigned int pool_size)
155{
156 if (monitors_.find(mtype) != monitors_.end() || pool_size == 0)
157 {
158 return;
159 }
160
161 glib::Object<ZeitgeistTimeRange> time_range(zeitgeist_time_range_new_to_now());
162
163 // This must not be free'd, libzeitgeist will take care of it.
164 GPtrArray* event_template = g_ptr_array_sized_new(1);
165 glib::Object<ZeitgeistEvent> event(application_event_, glib::AddRef());
166 g_ptr_array_add(event_template, event);
167
168 subjects_pools_[mtype] = pool_size;
169
170 struct FindEventsData
171 {
172 Application* self;
173 Application::MonitorType type;
174 };
175
176 auto data = new FindEventsData();
177 data->self = this;
178 data->type = mtype;
179
180 zeitgeist_log_find_events(log_, time_range, event_template, ZEITGEIST_STORAGE_STATE_AVAILABLE,
181 pool_size, GetResultTypeByMonitorType(mtype), nullptr,
182 [] (GObject* object, GAsyncResult* res, gpointer data)
183 {
184 glib::Error error;
185 glib::Object<ZeitgeistResultSet> results;
186 auto find_data = static_cast<FindEventsData*>(data);
187 auto log = reinterpret_cast<ZeitgeistLog*>(object);
188
189 results = zeitgeist_log_find_events_finish(log, res, &error);
190
191 if (!error)
192 find_data->self->HandleResultSet(results, find_data->type);
193
194 delete find_data;
195 },
196 data);
197
198 GPtrArray* monitor_template = g_ptr_array_sized_new(1);
199 g_ptr_array_add(monitor_template, event);
200
201 glib::Object<ZeitgeistTimeRange> monitor_time_range(zeitgeist_time_range_new_from_now(), glib::AddRef());
202 glib::Object<ZeitgeistMonitor> monitor(zeitgeist_monitor_new(monitor_time_range, monitor_template), glib::AddRef());
203 g_object_set_data(glib::object_cast<GObject>(monitor), "monitor-type", GUINT_TO_POINTER(mtype));
204
205 monitors_[mtype] = monitor;
206 zeitgeist_log_install_monitor(log_, monitor);
207
208 typedef glib::Signal<void, ZeitgeistMonitor*, ZeitgeistTimeRange*, ZeitgeistResultSet*> EventsAddedSignal;
209
210 signal_manager_.Add(new EventsAddedSignal(monitor, "events-inserted",
211 [&] (ZeitgeistMonitor* zmon, ZeitgeistTimeRange* tm, ZeitgeistResultSet* events)
212 {
213 glib::Object<ZeitgeistTimeRange> time(tm);
214 glib::Object<ZeitgeistResultSet> results(events);
215 gpointer data = g_object_get_data(reinterpret_cast<GObject*>(zmon), "monitor-type");
216 HandleResultSet(results, static_cast<MonitorType>(GPOINTER_TO_UINT(data)));
217 }));
218
219 typedef glib::Signal<void, ZeitgeistMonitor*, ZeitgeistTimeRange*, GArray*> EventsDeletedSignal;
220
221 signal_manager_.Add(new EventsDeletedSignal(monitor, "events-deleted",
222 [&] (ZeitgeistMonitor* zmon, ZeitgeistTimeRange* tm, GArray* events)
223 {
224 glib::Object<ZeitgeistTimeRange> time(tm);
225 gpointer data = g_object_get_data(reinterpret_cast<GObject*>(zmon), "monitor-type");
226 MonitorType mon_type = static_cast<MonitorType>(GPOINTER_TO_UINT(data));
227
228 Subjects& subjects = subjects_[mon_type];
229 std::vector<Subjects::iterator> to_rm;
230
231 for (unsigned int i = 0; events && i < events->len; ++i)
232 {
233 guint32 event_id = g_array_index(events, guint32, i);
234
235 for (auto it = subjects.begin(); it != subjects.end(); ++it)
236 {
237 if ((*it)->EventId() == event_id)
238 {
239 subject_removed.emit(mon_type, *it);
240 to_rm.push_back(it);
241 }
242 }
243 }
244
245 for (auto subject_it : to_rm)
246 subjects.erase(subject_it);
247
248 g_array_unref(events);
249 }));
250}
251
252void Application::RemoveMonitor(MonitorType mtype)
253{
254 if (monitors_.find(mtype) == monitors_.end())
255 return;
256
257 glib::Object<ZeitgeistMonitor> &monitor = monitors_[mtype];
258 signal_manager_.Disconnect(monitor.RawPtr(), "events-inserted");
259 signal_manager_.Disconnect(monitor.RawPtr(), "events-deleted");
260
261 for (auto subject : subjects_[mtype])
262 subject_removed.emit(mtype, subject);
263
264 subjects_.erase(mtype);
265 monitors_.erase(mtype);
266}
267
268}
269}
0270
=== added file 'UnityCore/ZeitgeistApplication.h'
--- UnityCore/ZeitgeistApplication.h 1970-01-01 00:00:00 +0000
+++ UnityCore/ZeitgeistApplication.h 2012-02-28 17:40:24 +0000
@@ -0,0 +1,86 @@
1// -*- Mode: C++; indent-tabs-mode: nil; tab-width: 2 -*-
2/*
3 * Copyright (C) 2012 Canonical Ltd
4 *
5 * This program is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License version 3 as
7 * published by the Free Software Foundation.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program. If not, see <http://www.gnu.org/licenses/>.
16 *
17 * Authored by: Marco Trevisan (Treviño) <3v1n0@ubuntu.com>
18 */
19
20#ifndef UNITY_ZEITGEIST_APPLICATION_H
21#define UNITY_ZEITGEIST_APPLICATION_H
22
23#include <zeitgeist.h>
24
25#include <sigc++/signal.h>
26#include <deque>
27#include <map>
28
29#include "ZeitgeistSubject.h"
30#include "GLibSignal.h"
31
32namespace unity
33{
34namespace zeitgeist
35{
36
37class Application : public sigc::trackable, boost::noncopyable
38{
39public:
40 typedef boost::shared_ptr<Application> Ptr;
41 typedef std::deque<Subject::Ptr> Subjects;
42
43 Application(std::string const& desktop_file);
44 ~Application();
45
46 enum MonitorType
47 {
48 MOST_RECENT_EVENTS = 1,
49 LEAST_RECENT_EVENTS,
50 MOST_RECENT_SUBJECTS,
51 LEAST_RECENT_SUBJECTS,
52 MOST_POPULAR_SUBJECTS,
53 LEAST_POPULAR_SUBJECTS,
54 RELEVANCY
55 };
56
57 std::string const& Uri() const;
58
59 void AddMonitor(MonitorType type, unsigned int pool_size = 10);
60 void RemoveMonitor(MonitorType type);
61
62 Subjects GetSubjectsForMonitor(MonitorType type) const;
63
64 // Signals
65 sigc::signal<void, MonitorType, Subject::Ptr const&> subject_added;
66 sigc::signal<void, MonitorType, Subject::Ptr const&> subject_removed;
67
68private:
69 ZeitgeistResultType GetResultTypeByMonitorType(MonitorType mtype);
70 void HandleResultSet(glib::Object<ZeitgeistResultSet> const& results, MonitorType mtype);
71
72 glib::Object<ZeitgeistLog> log_;
73 glib::Object<ZeitgeistEvent> application_event_;
74 std::string application_uri_;
75 glib::SignalManager signal_manager_;
76
77 std::map<MonitorType, glib::Object<ZeitgeistMonitor>> monitors_;
78 std::map<MonitorType, Subjects> subjects_;
79 std::map<MonitorType, unsigned int> subjects_pools_;
80};
81
82
83}
84}
85
86#endif // UNITY_ZEITGEIST_APPLICATION_H
087
=== added file 'UnityCore/ZeitgeistSubject.cpp'
--- UnityCore/ZeitgeistSubject.cpp 1970-01-01 00:00:00 +0000
+++ UnityCore/ZeitgeistSubject.cpp 2012-02-28 17:40:24 +0000
@@ -0,0 +1,91 @@
1// -*- Mode: C++; indent-tabs-mode: nil; tab-width: 2 -*-
2/*
3 * Copyright (C) 2012 Canonical Ltd
4 *
5 * This program is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License version 3 as
7 * published by the Free Software Foundation.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program. If not, see <http://www.gnu.org/licenses/>.
16 *
17 * Authored by: Marco Trevisan (Treviño) <3v1n0@ubuntu.com>
18 */
19
20#include "ZeitgeistSubject.h"
21
22namespace unity
23{
24namespace zeitgeist
25{
26
27Subject::Subject(glib::Object<ZeitgeistSubject> const& subject, unsigned int id, long long timestamp)
28 : subject_(subject, glib::AddRef()),
29 event_id_(id),
30 event_timestamp_(timestamp)
31{}
32
33unsigned int Subject::EventId() const
34{
35 return event_id_;
36}
37
38long long Subject::EventTimestamp() const
39{
40 return event_timestamp_;
41}
42
43std::string Subject::GetConstString(const gchar* str)
44{
45 return (str) ? str : "";
46}
47
48std::string Subject::Interpretation() const
49{
50 const gchar* str = zeitgeist_subject_get_interpretation(subject_);
51 return GetConstString(str);
52}
53
54std::string Subject::Manifestation() const
55{
56 const gchar* str = zeitgeist_subject_get_manifestation(subject_);
57 return GetConstString(str);
58}
59
60std::string Subject::MimeType() const
61{
62 const gchar* str = zeitgeist_subject_get_mimetype(subject_);
63 return GetConstString(str);
64}
65
66std::string Subject::Origin() const
67{
68 const gchar* str = zeitgeist_subject_get_origin(subject_);
69 return GetConstString(str);
70}
71
72std::string Subject::Storage() const
73{
74 const gchar* str = zeitgeist_subject_get_storage(subject_);
75 return GetConstString(str);
76}
77
78std::string Subject::Text() const
79{
80 const gchar* str = zeitgeist_subject_get_text(subject_);
81 return GetConstString(str);
82}
83
84std::string Subject::Uri() const
85{
86 const gchar* str = zeitgeist_subject_get_uri(subject_);
87 return GetConstString(str);
88}
89
90} // namespace zeitgeist
91} // namespace unity
092
=== added file 'UnityCore/ZeitgeistSubject.h'
--- UnityCore/ZeitgeistSubject.h 1970-01-01 00:00:00 +0000
+++ UnityCore/ZeitgeistSubject.h 2012-02-28 17:40:24 +0000
@@ -0,0 +1,64 @@
1// -*- Mode: C++; indent-tabs-mode: nil; tab-width: 2 -*-
2/*
3 * Copyright (C) 2012 Canonical Ltd
4 *
5 * This program is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License version 3 as
7 * published by the Free Software Foundation.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program. If not, see <http://www.gnu.org/licenses/>.
16 *
17 * Authored by: Marco Trevisan (Treviño) <3v1n0@ubuntu.com>
18 */
19
20#ifndef UNITY_ZEITGEIST_SUBJECT_H
21#define UNITY_ZEITGEIST_SUBJECT_H
22
23#include <zeitgeist.h>
24#include <boost/utility.hpp>
25#include <boost/shared_ptr.hpp>
26
27#include "GLibWrapper.h"
28
29namespace unity
30{
31namespace zeitgeist
32{
33
34class Subject : public boost::noncopyable
35{
36public:
37 typedef boost::shared_ptr<Subject> Ptr;
38
39 unsigned int EventId() const;
40 long long EventTimestamp() const;
41
42 std::string Interpretation() const;
43 std::string Manifestation() const;
44 std::string MimeType() const;
45 std::string Origin() const;
46 std::string Storage() const;
47 std::string Text() const;
48 std::string Uri() const;
49
50private:
51 Subject(glib::Object<ZeitgeistSubject> const& subject, unsigned int id, long long timestamp);
52 static std::string GetConstString(const gchar* str);
53
54 glib::Object<ZeitgeistSubject> subject_;
55 unsigned int event_id_;
56 long long event_timestamp_;
57
58 friend class Application;
59};
60
61}
62}
63
64#endif // UNITY_ZEITGEIST_SUBJECT_H
065
=== modified file 'plugins/unityshell/src/BamfLauncherIcon.cpp'
--- plugins/unityshell/src/BamfLauncherIcon.cpp 2012-02-22 02:17:08 +0000
+++ plugins/unityshell/src/BamfLauncherIcon.cpp 2012-02-28 17:40:24 +0000
@@ -70,52 +70,52 @@
70 glib::SignalBase* sig;70 glib::SignalBase* sig;
7171
72 sig = new glib::Signal<void, BamfView*, BamfView*>(bamf_view, "child-added",72 sig = new glib::Signal<void, BamfView*, BamfView*>(bamf_view, "child-added",
73 [&] (BamfView*, BamfView*) {73 [&] (BamfView*, BamfView*) {
74 EnsureWindowState();74 EnsureWindowState();
75 UpdateMenus();75 UpdateMenus();
76 UpdateIconGeometries(GetCenters());76 UpdateIconGeometries(GetCenters());
77 });77 });
78 _gsignals.Add(sig);78 _gsignals.Add(sig);
7979
80 sig = new glib::Signal<void, BamfView*, BamfView*>(bamf_view, "child-removed",80 sig = new glib::Signal<void, BamfView*, BamfView*>(bamf_view, "child-removed",
81 [&] (BamfView*, BamfView*) { EnsureWindowState(); });81 [&] (BamfView*, BamfView*) { EnsureWindowState(); });
82 _gsignals.Add(sig);82 _gsignals.Add(sig);
8383
84 sig = new glib::Signal<void, BamfView*, gboolean>(bamf_view, "urgent-changed",84 sig = new BamfPropertyChangedSignal(bamf_view, "urgent-changed",
85 [&] (BamfView*, gboolean urgent) {85 [&] (BamfView*, gboolean urgent) {
86 SetQuirk(QUIRK_URGENT, urgent);86 SetQuirk(QUIRK_URGENT, urgent);
87 });87 });
88 _gsignals.Add(sig);88 _gsignals.Add(sig);
8989
90 sig = new glib::Signal<void, BamfView*, gboolean>(bamf_view, "active-changed",90 sig = new BamfPropertyChangedSignal(bamf_view, "active-changed",
91 [&] (BamfView*, gboolean active) {91 [&] (BamfView*, gboolean active) {
92 SetQuirk(QUIRK_ACTIVE, active);92 SetQuirk(QUIRK_ACTIVE, active);
93 });93 });
94 _gsignals.Add(sig);94 _gsignals.Add(sig);
9595
96 sig = new glib::Signal<void, BamfView*, gboolean>(bamf_view, "running-changed",96 sig = new BamfPropertyChangedSignal(bamf_view, "running-changed",
97 [&] (BamfView*, gboolean running) {97 [&] (BamfView*, gboolean running) {
98 SetQuirk(QUIRK_RUNNING, running);98 SetQuirk(QUIRK_RUNNING, running);
99 if (running)99 if (running)
100 {100 {
101 EnsureWindowState();101 EnsureWindowState();
102 UpdateIconGeometries(GetCenters());102 UpdateIconGeometries(GetCenters());
103 }103 }
104 });104 });
105 _gsignals.Add(sig);105 _gsignals.Add(sig);
106106
107 sig = new glib::Signal<void, BamfView*, gboolean>(bamf_view, "user-visible-changed",107 sig = new BamfPropertyChangedSignal(bamf_view, "user-visible-changed",
108 [&] (BamfView*, gboolean visible) {108 [&] (BamfView*, gboolean visible) {
109 if (!IsSticky())109 if (!IsSticky())
110 SetQuirk(QUIRK_VISIBLE, visible);110 SetQuirk(QUIRK_VISIBLE, visible);
111 });111 });
112 _gsignals.Add(sig);112 _gsignals.Add(sig);
113113
114 sig = new glib::Signal<void, BamfView*>(bamf_view, "closed",114 sig = new glib::Signal<void, BamfView*>(bamf_view, "closed",
115 [&] (BamfView*) {115 [&] (BamfView*) {
116 if (!IsSticky())116 if (!IsSticky())
117 Remove();117 Remove();
118 });118 });
119 _gsignals.Add(sig);119 _gsignals.Add(sig);
120120
121 WindowManager::Default()->window_minimized.connect(sigc::mem_fun(this, &BamfLauncherIcon::OnWindowMinimized));121 WindowManager::Default()->window_minimized.connect(sigc::mem_fun(this, &BamfLauncherIcon::OnWindowMinimized));
@@ -126,6 +126,7 @@
126 EnsureWindowState();126 EnsureWindowState();
127 UpdateMenus();127 UpdateMenus();
128 UpdateDesktopFile();128 UpdateDesktopFile();
129 SetupZeitgeistMonitor();
129130
130 // hack131 // hack
131 SetProgress(0.0f);132 SetProgress(0.0f);
@@ -416,6 +417,7 @@
416 break;417 break;
417 case G_FILE_MONITOR_EVENT_CHANGES_DONE_HINT:418 case G_FILE_MONITOR_EVENT_CHANGES_DONE_HINT:
418 UpdateDesktopQuickList();419 UpdateDesktopQuickList();
420 SetupZeitgeistMonitor();
419 break;421 break;
420 default:422 default:
421 break;423 break;
@@ -707,12 +709,12 @@
707 dbusmenu_menuitem_property_set_bool(item, DBUSMENU_MENUITEM_PROP_VISIBLE, TRUE);709 dbusmenu_menuitem_property_set_bool(item, DBUSMENU_MENUITEM_PROP_VISIBLE, TRUE);
708 dbusmenu_menuitem_property_set(item, "shortcut-nick", nicks[index]);710 dbusmenu_menuitem_property_set(item, "shortcut-nick", nicks[index]);
709711
710 auto sig = new glib::Signal<void, DbusmenuMenuitem*, gint>(item, "item-activated",712 auto sig = new MenuitemActivateSignal(item, "item-activated",
711 [&] (DbusmenuMenuitem* item, gint) {713 [&] (DbusmenuMenuitem* item, gint) {
712 const gchar *nick;714 const gchar *nick;
713 nick = dbusmenu_menuitem_property_get(item, "shortcut-nick");715 nick = dbusmenu_menuitem_property_get(item, "shortcut-nick");
714 indicator_desktop_shortcuts_nick_exec(_desktop_shortcuts, nick);716 indicator_desktop_shortcuts_nick_exec(_desktop_shortcuts, nick);
715 });717 });
716 _gsignals.Add(sig);718 _gsignals.Add(sig);
717719
718 dbusmenu_menuitem_child_append(_menu_desktop_shortcuts, item);720 dbusmenu_menuitem_child_append(_menu_desktop_shortcuts, item);
@@ -837,10 +839,10 @@
837 dbusmenu_menuitem_property_set_bool(menu_item, DBUSMENU_MENUITEM_PROP_ENABLED, true);839 dbusmenu_menuitem_property_set_bool(menu_item, DBUSMENU_MENUITEM_PROP_ENABLED, true);
838 dbusmenu_menuitem_property_set_bool(menu_item, DBUSMENU_MENUITEM_PROP_VISIBLE, true);840 dbusmenu_menuitem_property_set_bool(menu_item, DBUSMENU_MENUITEM_PROP_VISIBLE, true);
839841
840 _gsignals.Add(new glib::Signal<void, DbusmenuMenuitem*, int>(menu_item, DBUSMENU_MENUITEM_SIGNAL_ITEM_ACTIVATED,842 _gsignals.Add(new MenuitemActivateSignal(menu_item, DBUSMENU_MENUITEM_SIGNAL_ITEM_ACTIVATED,
841 [&] (DbusmenuMenuitem*, int) {843 [&] (DbusmenuMenuitem*, int) {
842 ToggleSticky();844 ToggleSticky();
843 }));845 }));
844846
845 _menu_items["Pin"] = glib::Object<DbusmenuMenuitem>(menu_item);847 _menu_items["Pin"] = glib::Object<DbusmenuMenuitem>(menu_item);
846 }848 }
@@ -858,10 +860,10 @@
858 dbusmenu_menuitem_property_set_bool(menu_item, DBUSMENU_MENUITEM_PROP_ENABLED, true);860 dbusmenu_menuitem_property_set_bool(menu_item, DBUSMENU_MENUITEM_PROP_ENABLED, true);
859 dbusmenu_menuitem_property_set_bool(menu_item, DBUSMENU_MENUITEM_PROP_VISIBLE, true);861 dbusmenu_menuitem_property_set_bool(menu_item, DBUSMENU_MENUITEM_PROP_VISIBLE, true);
860862
861 _gsignals.Add(new glib::Signal<void, DbusmenuMenuitem*, int>(menu_item, DBUSMENU_MENUITEM_SIGNAL_ITEM_ACTIVATED,863 _gsignals.Add(new MenuitemActivateSignal(menu_item, DBUSMENU_MENUITEM_SIGNAL_ITEM_ACTIVATED,
862 [&] (DbusmenuMenuitem*, int) {864 [&] (DbusmenuMenuitem*, int) {
863 Quit();865 Quit();
864 }));866 }));
865867
866 _menu_items["Quit"] = glib::Object<DbusmenuMenuitem>(menu_item);868 _menu_items["Quit"] = glib::Object<DbusmenuMenuitem>(menu_item);
867 }869 }
@@ -901,6 +903,7 @@
901 }903 }
902 }904 }
903 }905 }
906
904907
905 // FIXME: this should totally be added as a _menu_client908 // FIXME: this should totally be added as a _menu_client
906 if (DBUSMENU_IS_MENUITEM(_menu_desktop_shortcuts.RawPtr()))909 if (DBUSMENU_IS_MENUITEM(_menu_desktop_shortcuts.RawPtr()))
@@ -960,10 +963,10 @@
960 "unity-use-markup",963 "unity-use-markup",
961 true);964 true);
962965
963 _gsignals.Add(new glib::Signal<void, DbusmenuMenuitem*, int>(item, DBUSMENU_MENUITEM_SIGNAL_ITEM_ACTIVATED,966 _gsignals.Add(new MenuitemActivateSignal(item, DBUSMENU_MENUITEM_SIGNAL_ITEM_ACTIVATED,
964 [&] (DbusmenuMenuitem*, int) {967 [&] (DbusmenuMenuitem*, int) {
965 ActivateLauncherIcon(ActionArg(ActionArg::OTHER, 0));968 ActivateLauncherIcon(ActionArg(ActionArg::OTHER, 0));
966 }));969 }));
967970
968 _menu_items_extra["AppName"] = glib::Object<DbusmenuMenuitem>(item);971 _menu_items_extra["AppName"] = glib::Object<DbusmenuMenuitem>(item);
969 }972 }
@@ -984,6 +987,29 @@
984 }987 }
985 result.push_back(item);988 result.push_back(item);
986989
990 for (auto it = _menu_items_zeitgeist.begin(); it != _menu_items_zeitgeist.end(); ++it)
991 {
992 result.push_back(it->second.RawPtr());
993 }
994
995 if (_menu_items_zeitgeist.size() > 0)
996 {
997 auto third_separator = _menu_items_extra.find("ThirdSeparator");
998 if (third_separator != _menu_items_extra.end())
999 {
1000 item = third_separator->second;
1001 }
1002 else
1003 {
1004 item = dbusmenu_menuitem_new();
1005 dbusmenu_menuitem_property_set(item,
1006 DBUSMENU_MENUITEM_PROP_TYPE,
1007 DBUSMENU_CLIENT_TYPES_SEPARATOR);
1008 _menu_items_extra["ThirdSeparator"] = glib::Object<DbusmenuMenuitem>(item);
1009 }
1010 result.push_back(item);
1011 }
1012
987 EnsureMenuItemsReady();1013 EnsureMenuItemsReady();
9881014
989 for (auto it_m = _menu_items.begin(); it_m != _menu_items.end(); ++it_m)1015 for (auto it_m = _menu_items.begin(); it_m != _menu_items.end(); ++it_m)
@@ -1231,6 +1257,99 @@
1231 }1257 }
1232}1258}
12331259
1260void BamfLauncherIcon::SetupZeitgeistMonitor()
1261{
1262 const std::string keyname = "X-Ayatana-Show-Recent-Files";
1263 bool enabled = true;
1264
1265 if (_desktop_file.empty())
1266 {
1267 enabled = false;
1268 }
1269 else
1270 {
1271 glib::Error error;
1272 GKeyFile* keyfile = g_key_file_new();
1273
1274 g_key_file_load_from_file(keyfile, _desktop_file.c_str(), G_KEY_FILE_NONE, &error);
1275
1276 if (error)
1277 {
1278 enabled = false;
1279 g_key_file_free(keyfile);
1280 }
1281 else if (g_key_file_has_key(keyfile, G_KEY_FILE_DESKTOP_GROUP, keyname.c_str(), nullptr))
1282 {
1283 enabled = g_key_file_get_boolean(keyfile, G_KEY_FILE_DESKTOP_GROUP, keyname.c_str(), nullptr);
1284 }
1285
1286 g_key_file_free(keyfile);
1287 }
1288
1289 if (!enabled && _zeitgeist_app.get())
1290 {
1291 _zeitgeist_app->RemoveMonitor(zeitgeist::Application::MOST_RECENT_SUBJECTS);
1292 _zeitgeist_app.reset();
1293 }
1294 else if (enabled && !_zeitgeist_app.get())
1295 {
1296 _zeitgeist_app.reset(new zeitgeist::Application(_desktop_file));
1297 _zeitgeist_app->subject_added.connect(sigc::mem_fun(this, &BamfLauncherIcon::OnZeitgeistSubjectAdded));
1298 _zeitgeist_app->subject_removed.connect(sigc::mem_fun(this, &BamfLauncherIcon::OnZeitgeistSubjectRemoved));
1299 _zeitgeist_app->AddMonitor(zeitgeist::Application::MOST_RECENT_SUBJECTS, 5);
1300 }
1301}
1302
1303void BamfLauncherIcon::OnZeitgeistSubjectAdded(zeitgeist::Application::MonitorType mtype,
1304 zeitgeist::Subject::Ptr const& subject)
1305{
1306 if (mtype != zeitgeist::Application::MOST_RECENT_SUBJECTS)
1307 return;
1308
1309 glib::Object<DbusmenuMenuitem> menu_item(dbusmenu_menuitem_new());
1310 dbusmenu_menuitem_property_set(menu_item, DBUSMENU_MENUITEM_PROP_LABEL, subject->Text().c_str());
1311 dbusmenu_menuitem_property_set_bool(menu_item, DBUSMENU_MENUITEM_PROP_ENABLED, true);
1312 dbusmenu_menuitem_property_set_bool(menu_item, DBUSMENU_MENUITEM_PROP_VISIBLE, true);
1313
1314 _gsignals.Add(new MenuitemActivateSignal(menu_item, DBUSMENU_MENUITEM_SIGNAL_ITEM_ACTIVATED,
1315 [&] (DbusmenuMenuitem* item, int)
1316 {
1317 for (auto zmenuitem : _menu_items_zeitgeist)
1318 {
1319 if (zmenuitem.second == item)
1320 {
1321 std::string const& uri = zmenuitem.first->Uri();
1322 if (!uri.empty())
1323 {
1324 std::set<std::string> uris;
1325 uris.insert(uri);
1326 OpenInstanceWithUris(uris);
1327 }
1328 break;
1329 }
1330 }
1331 }));
1332
1333 _menu_items_zeitgeist.push_front(ZeitgeistMenuitem(subject, menu_item));
1334}
1335
1336void BamfLauncherIcon::OnZeitgeistSubjectRemoved(zeitgeist::Application::MonitorType mtype,
1337 zeitgeist::Subject::Ptr const& subject)
1338{
1339 if (mtype != zeitgeist::Application::MOST_RECENT_SUBJECTS)
1340 return;
1341
1342 for (auto it = _menu_items_zeitgeist.begin(); it != _menu_items_zeitgeist.end(); ++it)
1343 {
1344 if (it->first == subject)
1345 {
1346 _gsignals.Disconnect(it->second.RawPtr(), DBUSMENU_MENUITEM_SIGNAL_ITEM_ACTIVATED);
1347 _menu_items_zeitgeist.erase(it);
1348 break;
1349 }
1350 }
1351}
1352
1234std::string BamfLauncherIcon::GetName() const1353std::string BamfLauncherIcon::GetName() const
1235{1354{
1236 return "BamfLauncherIcon";1355 return "BamfLauncherIcon";
12371356
=== modified file 'plugins/unityshell/src/BamfLauncherIcon.h'
--- plugins/unityshell/src/BamfLauncherIcon.h 2012-02-12 10:43:11 +0000
+++ plugins/unityshell/src/BamfLauncherIcon.h 2012-02-28 17:40:24 +0000
@@ -23,6 +23,7 @@
2323
24#include <UnityCore/GLibSignal.h>24#include <UnityCore/GLibSignal.h>
25#include <UnityCore/GLibWrapper.h>25#include <UnityCore/GLibWrapper.h>
26#include <UnityCore/ZeitgeistApplication.h>
2627
27#include <libbamf/libbamf.h>28#include <libbamf/libbamf.h>
28#include <libindicator/indicator-desktop-shortcuts.h>29#include <libindicator/indicator-desktop-shortcuts.h>
@@ -93,6 +94,7 @@
93 void UpdateMenus();94 void UpdateMenus();
94 void UpdateDesktopQuickList();95 void UpdateDesktopQuickList();
95 void FillSupportedTypes();96 void FillSupportedTypes();
97 void SetupZeitgeistMonitor();
9698
97 void OpenInstanceWithUris(std::set<std::string> uris);99 void OpenInstanceWithUris(std::set<std::string> uris);
98 void Focus(ActionArg arg);100 void Focus(ActionArg arg);
@@ -100,11 +102,18 @@
100102
101 void OnWindowMinimized(guint32 xid);103 void OnWindowMinimized(guint32 xid);
102 void OnWindowMoved(guint32 xid);104 void OnWindowMoved(guint32 xid);
105 void OnZeitgeistSubjectAdded(zeitgeist::Application::MonitorType mtype,
106 zeitgeist::Subject::Ptr const& subject);
107 void OnZeitgeistSubjectRemoved(zeitgeist::Application::MonitorType mtype,
108 zeitgeist::Subject::Ptr const& subject);
103109
104 bool OwnsWindow(Window w) const;110 bool OwnsWindow(Window w) const;
105111
106 const std::set<std::string>& GetSupportedTypes();112 const std::set<std::string>& GetSupportedTypes();
107113
114 typedef glib::Signal<void, BamfView*, gboolean> BamfPropertyChangedSignal;
115 typedef glib::Signal<void, DbusmenuMenuitem*, int> MenuitemActivateSignal;
116 typedef std::pair<zeitgeist::Subject::Ptr, glib::Object<DbusmenuMenuitem>> ZeitgeistMenuitem;
108117
109 glib::Object<BamfApplication> _bamf_app;118 glib::Object<BamfApplication> _bamf_app;
110 bool _dnd_hovered;119 bool _dnd_hovered;
@@ -116,10 +125,12 @@
116125
117 std::string _remote_uri;126 std::string _remote_uri;
118 std::string _desktop_file;127 std::string _desktop_file;
128 zeitgeist::Application::Ptr _zeitgeist_app;
119 std::set<std::string> _supported_types;129 std::set<std::string> _supported_types;
120 std::map<std::string, glib::Object<DbusmenuClient>> _menu_clients;130 std::map<std::string, glib::Object<DbusmenuClient>> _menu_clients;
121 std::map<std::string, glib::Object<DbusmenuMenuitem>> _menu_items;131 std::map<std::string, glib::Object<DbusmenuMenuitem>> _menu_items;
122 std::map<std::string, glib::Object<DbusmenuMenuitem>> _menu_items_extra;132 std::map<std::string, glib::Object<DbusmenuMenuitem>> _menu_items_extra;
133 std::deque<ZeitgeistMenuitem> _menu_items_zeitgeist;
123 glib::Object<IndicatorDesktopShortcuts> _desktop_shortcuts;134 glib::Object<IndicatorDesktopShortcuts> _desktop_shortcuts;
124 glib::Object<DbusmenuMenuitem> _menu_desktop_shortcuts;135 glib::Object<DbusmenuMenuitem> _menu_desktop_shortcuts;
125 glib::Object<GFileMonitor> _desktop_file_monitor;136 glib::Object<GFileMonitor> _desktop_file_monitor;