Merge lp:~mhr3/unity/home-lens-fixes into lp:unity
- home-lens-fixes
- Merge into trunk
Status: | Merged |
---|---|
Approved by: | Michal Hruby |
Approved revision: | no longer in the source branch. |
Merged at revision: | 2639 |
Proposed branch: | lp:~mhr3/unity/home-lens-fixes |
Merge into: | lp:unity |
Diff against target: |
800 lines (+228/-169) 7 files modified
UnityCore/HomeLens.cpp (+83/-65) UnityCore/Lens.cpp (+99/-29) UnityCore/Lens.h (+12/-0) UnityCore/Variant.cpp (+7/-2) UnityCore/Variant.h (+2/-0) dash/LensView.cpp (+24/-71) dash/LensView.h (+1/-2) |
To merge this branch: | bzr merge lp:~mhr3/unity/home-lens-fixes |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Paweł Stołowski (community) | Approve | ||
Tim Penhey (community) | Approve | ||
Review via email: mp+121628@code.launchpad.net |
Commit message
Activate proper result if the categories aren't displayed in-order
Description of the change
Fixed one longstanding and one recently introduced bug.
Fixes existing AP test (although depending on your data it might not have been failing in the first place).
Sam Spilsbury (smspillaz) wrote : | # |
Michal Hruby (mhr3) wrote : | # |
As mentioned in the description there's AP test for one of the issues, the second one is more tricky as it requires killing and restarting a lens.
Tim Penhey (thumper) wrote : | # |
Looks reasonable, minor niggles about * next to vars, but not types, but that is all.
Paweł Stołowski (stolowski) wrote : | # |
Looks good and works fine. My only gripe is about implicit conversion of glib::Variant to bool
619 +Variant::operator bool() const
620 +{
621 + return bool(variant_);
622 +}
IMHO it should only be used it if it improves readability, whereas in this case, if you just look at the interface declaration, it's not apparent that it relies on the internal pointer not being null - plus one could expect bool operator to return a boolean value of the variant when it makes sense (i.e. what GetBool() does atm).
Would you mind changing this to something more verbose, e.g. bool Variant::IsNull(); also 'return variant_ == null' would be more clear.
I'm sorry for being picky, I'm now spoiled by other languages ;)
Michal Hruby (mhr3) wrote : | # |
> Looks good and works fine. My only gripe is about implicit conversion of
> glib::Variant to bool
>
> 619 +Variant::operator bool() const
> 620 +{
> 621 + return bool(variant_);
> 622 +}
>
> IMHO it should only be used it if it improves readability, whereas in this
> case, if you just look at the interface declaration, it's not apparent that it
> relies on the internal pointer not being null - plus one could expect bool
> operator to return a boolean value of the variant when it makes sense (i.e.
> what GetBool() does atm).
>
> Would you mind changing this to something more verbose, e.g. bool
> Variant::IsNull(); also 'return variant_ == null' would be more clear.
>
> I'm sorry for being picky, I'm now spoiled by other languages ;)
I understand your point, but this is consistent with our other wrappers (glib::Object), plus you really shouldn't be using implicit conversion to get the value out of a variant, that sounds like a very bad idea. Moreover this also consistent with the way shared_ptr and unique_ptr work, so as long as you keep in mind this is a wrapper it's not that ambiguous.
Paweł Stołowski (stolowski) wrote : | # |
I wasn't suggesting implicit conversion to get the value out of a variant, just said one could be tricked into thinking it does that by looking at the interface ;); that would indeed be a bad idea.
If it's consistent with other wrappers, then so be it, though that doesn't automatically make me happy :/
Unity Merger (unity-merger) wrote : | # |
The Jenkins job https:/
Not merging it.
Unity Merger (unity-merger) wrote : | # |
The Jenkins job https:/
Not merging it.
Preview Diff
1 | === modified file 'UnityCore/HomeLens.cpp' |
2 | --- UnityCore/HomeLens.cpp 2012-08-17 15:59:41 +0000 |
3 | +++ UnityCore/HomeLens.cpp 2012-08-29 09:48:20 +0000 |
4 | @@ -136,6 +136,21 @@ |
5 | return target_cat_index; |
6 | } |
7 | |
8 | + void UnregisterAllForModel(DeeModel* model) |
9 | + { |
10 | + auto it = reg_category_map_.begin(); |
11 | + |
12 | + // References and iterators to the erased elements are invalidated. |
13 | + // Other references and iterators are not affected. |
14 | + while (it != reg_category_map_.end()) |
15 | + { |
16 | + if (it->first.first == model) |
17 | + reg_category_map_.erase(it++); |
18 | + else |
19 | + ++it; |
20 | + } |
21 | + } |
22 | + |
23 | void NotifyOrderChanged () |
24 | { |
25 | owner_->categories_reordered(); |
26 | @@ -157,17 +172,18 @@ |
27 | ModelMerger(glib::Object<DeeModel> target); |
28 | virtual ~ModelMerger(); |
29 | |
30 | - void AddSource(Lens::Ptr& owner_lens, glib::Object<DeeModel> source); |
31 | + virtual void AddSource(Lens::Ptr& owner_lens, glib::Object<DeeModel> source); |
32 | + virtual void RemoveSource(glib::Object<DeeModel> const& old_source); |
33 | |
34 | protected: |
35 | - virtual void OnSourceRowAdded(DeeModel *model, DeeModelIter *iter); |
36 | + virtual void OnSourceRowAdded(DeeModel* model, DeeModelIter* iter); |
37 | virtual void OnSourceRowRemoved(DeeModel* model, DeeModelIter* iter); |
38 | virtual void OnSourceRowChanged(DeeModel* model, DeeModelIter* iter); |
39 | - void EnsureRowBuf(DeeModel *source); |
40 | + void EnsureRowBuf(DeeModel* source); |
41 | |
42 | /* The merge tag lives on the source models, pointing to the mapped |
43 | * row in the target model */ |
44 | - DeeModelTag* FindSourceToTargetTag(DeeModel *model); |
45 | + DeeModelTag* FindSourceToTargetTag(DeeModel* model); |
46 | |
47 | protected: |
48 | std::map<Lens::Ptr, glib::Object<DeeModel> > sources_by_owner_; |
49 | @@ -197,9 +213,9 @@ |
50 | HomeLens::CategoryRegistry* cat_registry); |
51 | |
52 | protected: |
53 | - void OnSourceRowAdded(DeeModel *model, DeeModelIter *iter); |
54 | - void OnSourceRowRemoved(DeeModel *model, DeeModelIter *iter); |
55 | - void OnSourceRowChanged(DeeModel *model, DeeModelIter *iter); |
56 | + void OnSourceRowAdded(DeeModel* model, DeeModelIter* iter); |
57 | + void OnSourceRowRemoved(DeeModel* model, DeeModelIter* iter); |
58 | + void OnSourceRowChanged(DeeModel* model, DeeModelIter* iter); |
59 | |
60 | private: |
61 | HomeLens::CategoryRegistry* cat_registry_; |
62 | @@ -221,10 +237,13 @@ |
63 | HomeLens::CategoryRegistry* cat_registry, |
64 | MergeMode merge_mode); |
65 | |
66 | - void OnSourceRowAdded(DeeModel *model, DeeModelIter *iter); |
67 | - void OnSourceRowRemoved(DeeModel *model, DeeModelIter *iter); |
68 | - |
69 | - std::vector<unsigned> GetOrder(); |
70 | + void OnSourceRowAdded(DeeModel* model, DeeModelIter* iter); |
71 | + void OnSourceRowRemoved(DeeModel* model, DeeModelIter* iter); |
72 | + |
73 | + std::vector<unsigned> GetDefaultOrder(); |
74 | + |
75 | +protected: |
76 | + void RemoveSource(glib::Object<DeeModel> const& old_source); |
77 | |
78 | private: |
79 | HomeLens::CategoryRegistry* cat_registry_; |
80 | @@ -241,9 +260,9 @@ |
81 | public: |
82 | FiltersMerger(glib::Object<DeeModel> target); |
83 | |
84 | - void OnSourceRowAdded(DeeModel *model, DeeModelIter *iter); |
85 | - void OnSourceRowRemoved(DeeModel *model, DeeModelIter *iter); |
86 | - void OnSourceRowChanged(DeeModel *model, DeeModelIter *iter); |
87 | + void OnSourceRowAdded(DeeModel* model, DeeModelIter* iter); |
88 | + void OnSourceRowRemoved(DeeModel* model, DeeModelIter* iter); |
89 | + void OnSourceRowChanged(DeeModel* model, DeeModelIter* iter); |
90 | }; |
91 | |
92 | /* |
93 | @@ -260,6 +279,7 @@ |
94 | void EnsureCategoryAnnotation(Lens::Ptr& lens, DeeModel* results, DeeModel* categories); |
95 | Lens::Ptr FindLensForUri(std::string const& uri); |
96 | std::vector<unsigned> GetCategoriesOrder(); |
97 | + void LensSearchFinished(Lens::Ptr& lens); |
98 | |
99 | HomeLens* owner_; |
100 | Lenses::LensList lenses_; |
101 | @@ -324,7 +344,7 @@ |
102 | { |
103 | if (it->second == source) |
104 | return; // this model was already added |
105 | - sig_manager_.Disconnect(it->second); |
106 | + RemoveSource(it->second); |
107 | } |
108 | sources_by_owner_[owner_lens] = source; |
109 | |
110 | @@ -344,12 +364,23 @@ |
111 | sigc::mem_fun(this, &HomeLens::ModelMerger::OnSourceRowChanged))); |
112 | } |
113 | |
114 | -void HomeLens::ModelMerger::OnSourceRowAdded(DeeModel *model, DeeModelIter *iter) |
115 | +void HomeLens::ModelMerger::RemoveSource(glib::Object<DeeModel> const& source) |
116 | +{ |
117 | + if (!source) |
118 | + { |
119 | + LOG_ERROR(logger) << "Trying to remove NULL source from ModelMerger"; |
120 | + return; |
121 | + } |
122 | + |
123 | + sig_manager_.Disconnect(source); |
124 | +} |
125 | + |
126 | +void HomeLens::ModelMerger::OnSourceRowAdded(DeeModel* model, DeeModelIter* iter) |
127 | { |
128 | // Default impl. does nothing. |
129 | } |
130 | |
131 | -void HomeLens::ResultsMerger::OnSourceRowAdded(DeeModel *model, DeeModelIter *iter) |
132 | +void HomeLens::ResultsMerger::OnSourceRowAdded(DeeModel* model, DeeModelIter* iter) |
133 | { |
134 | DeeModelIter* target_iter; |
135 | int target_cat_offset, source_cat_offset; |
136 | @@ -390,7 +421,7 @@ |
137 | for (unsigned int i = 0; i < n_cols_; i++) g_variant_unref(row_buf_[i]); |
138 | } |
139 | |
140 | -void HomeLens::CategoryMerger::OnSourceRowAdded(DeeModel *model, DeeModelIter *iter) |
141 | +void HomeLens::CategoryMerger::OnSourceRowAdded(DeeModel* model, DeeModelIter* iter) |
142 | { |
143 | DeeModel* results_model; |
144 | DeeModelIter* target_iter; |
145 | @@ -470,14 +501,14 @@ |
146 | for (unsigned int i = 0; i < n_cols_; i++) g_variant_unref(row_buf_[i]); |
147 | } |
148 | |
149 | -void HomeLens::FiltersMerger::OnSourceRowAdded(DeeModel *model, DeeModelIter *iter) |
150 | +void HomeLens::FiltersMerger::OnSourceRowAdded(DeeModel* model, DeeModelIter* iter) |
151 | { |
152 | /* Supporting filters on the home screen is possible, but *quite* tricky. |
153 | * So... Discard ALL the rows! |
154 | */ |
155 | } |
156 | |
157 | -void HomeLens::CategoryMerger::OnSourceRowRemoved(DeeModel *model, DeeModelIter *iter) |
158 | +void HomeLens::CategoryMerger::OnSourceRowRemoved(DeeModel* model, DeeModelIter* iter) |
159 | { |
160 | /* We don't support removals of categories. |
161 | * You can check out any time you like, but you can never leave |
162 | @@ -488,7 +519,7 @@ |
163 | LOG_DEBUG(logger) << "Removal of categories not supported."; |
164 | } |
165 | |
166 | -void HomeLens::ModelMerger::OnSourceRowRemoved(DeeModel *model, DeeModelIter *iter) |
167 | +void HomeLens::ModelMerger::OnSourceRowRemoved(DeeModel* model, DeeModelIter* iter) |
168 | { |
169 | DeeModelIter* target_iter; |
170 | DeeModelTag* target_tag; |
171 | @@ -506,17 +537,17 @@ |
172 | dee_model_remove(target_, target_iter); |
173 | } |
174 | |
175 | -void HomeLens::ResultsMerger::OnSourceRowRemoved(DeeModel *model, DeeModelIter *iter) |
176 | +void HomeLens::ResultsMerger::OnSourceRowRemoved(DeeModel* model, DeeModelIter* iter) |
177 | { |
178 | ModelMerger::OnSourceRowRemoved(model, iter); |
179 | } |
180 | |
181 | -void HomeLens::FiltersMerger::OnSourceRowRemoved(DeeModel *model, DeeModelIter *iter) |
182 | +void HomeLens::FiltersMerger::OnSourceRowRemoved(DeeModel* model, DeeModelIter* iter) |
183 | { |
184 | /* We aren't adding any rows to the merged model, so nothing to do here */ |
185 | } |
186 | |
187 | -void HomeLens::ModelMerger::OnSourceRowChanged(DeeModel *model, DeeModelIter *iter) |
188 | +void HomeLens::ModelMerger::OnSourceRowChanged(DeeModel* model, DeeModelIter* iter) |
189 | { |
190 | DeeModelIter* target_iter; |
191 | DeeModelTag* target_tag; |
192 | @@ -534,18 +565,18 @@ |
193 | for (unsigned int i = 0; i < n_cols_; i++) g_variant_unref(row_buf_[i]); |
194 | } |
195 | |
196 | -void HomeLens::ResultsMerger::OnSourceRowChanged(DeeModel *model, DeeModelIter *iter) |
197 | +void HomeLens::ResultsMerger::OnSourceRowChanged(DeeModel* model, DeeModelIter* iter) |
198 | { |
199 | // FIXME: We can support this, but we need to re-calculate the category offset |
200 | LOG_WARN(logger) << "In-line changing of results not supported in the home lens. Sorry."; |
201 | } |
202 | |
203 | -void HomeLens::FiltersMerger::OnSourceRowChanged(DeeModel *model, DeeModelIter *iter) |
204 | +void HomeLens::FiltersMerger::OnSourceRowChanged(DeeModel* model, DeeModelIter* iter) |
205 | { |
206 | /* We aren't adding any rows to the merged model, so nothing to do here */ |
207 | } |
208 | |
209 | -void HomeLens::ModelMerger::EnsureRowBuf(DeeModel *model) |
210 | +void HomeLens::ModelMerger::EnsureRowBuf(DeeModel* model) |
211 | { |
212 | if (G_UNLIKELY (n_cols_ == 0)) |
213 | { |
214 | @@ -606,12 +637,20 @@ |
215 | } |
216 | } |
217 | |
218 | -DeeModelTag* HomeLens::ModelMerger::FindSourceToTargetTag(DeeModel *model) |
219 | +DeeModelTag* HomeLens::ModelMerger::FindSourceToTargetTag(DeeModel* model) |
220 | { |
221 | return source_to_target_tags_[model]; |
222 | } |
223 | |
224 | -std::vector<unsigned> HomeLens::CategoryMerger::GetOrder() |
225 | +void HomeLens::CategoryMerger::RemoveSource(glib::Object<DeeModel> const& source) |
226 | +{ |
227 | + // call base() |
228 | + HomeLens::ModelMerger::RemoveSource(source); |
229 | + |
230 | + cat_registry_->UnregisterAllForModel(source); |
231 | +} |
232 | + |
233 | +std::vector<unsigned> HomeLens::CategoryMerger::GetDefaultOrder() |
234 | { |
235 | std::vector<unsigned> result; |
236 | for (auto it = category_ordering_.begin(); it != category_ordering_.end(); ++it) |
237 | @@ -746,6 +785,7 @@ |
238 | lens->global_search_finished.connect([&] (Hints const& hints) { |
239 | running_searches_--; |
240 | |
241 | + LensSearchFinished(lens); |
242 | if (running_searches_ <= 0) |
243 | { |
244 | owner_->search_finished.emit(Hints()); |
245 | @@ -784,41 +824,15 @@ |
246 | filters_merger_.AddSource(lens, filters_prop()); |
247 | } |
248 | |
249 | - /* |
250 | - * We'll assume that the models' swarm names do not change during life cycle |
251 | - * of a lens. |
252 | - * Otherwise we might run into a race where we would associate category |
253 | - * model to a results model that is about to be replaced by a new one. |
254 | - */ |
255 | - lens->connected.changed.connect([&] (bool is_connected) |
256 | - { |
257 | - if (is_connected) |
258 | - { |
259 | - EnsureCategoryAnnotation(lens, lens->categories()->model(), |
260 | - lens->global_results()->model()); |
261 | - categories_merger_.AddSource(lens, lens->categories()->model()); |
262 | - results_merger_.AddSource(lens, lens->global_results()->model()); |
263 | - filters_merger_.AddSource(lens, lens->filters()->model()); |
264 | - } |
265 | - }); |
266 | - /* |
267 | - results_prop.changed.connect([&] (glib::Object<DeeModel> model) |
268 | - { |
269 | - EnsureCategoryAnnotation(lens, lens->categories()->model(), model); |
270 | - results_merger_.AddSource(model); |
271 | - }); |
272 | - |
273 | - categories_prop.changed.connect([&] (glib::Object<DeeModel> model) |
274 | - { |
275 | - EnsureCategoryAnnotation(lens, model, lens->global_results()->model()); |
276 | - categories_merger_.AddSource(model); |
277 | - }); |
278 | - |
279 | - filters_prop.changed.connect([&] (glib::Object<DeeModel> model) |
280 | - { |
281 | - filters_merger_.AddSource(model); |
282 | - }); |
283 | - */ |
284 | + /* Make sure the models are properly annotated when they change */ |
285 | + lens->models_changed.connect([&] () |
286 | + { |
287 | + EnsureCategoryAnnotation(lens, lens->categories()->model(), |
288 | + lens->global_results()->model()); |
289 | + categories_merger_.AddSource(lens, lens->categories()->model()); |
290 | + results_merger_.AddSource(lens, lens->global_results()->model()); |
291 | + filters_merger_.AddSource(lens, lens->filters()->model()); |
292 | + }); |
293 | |
294 | /* |
295 | * Register pre-existing categories up front |
296 | @@ -838,9 +852,13 @@ |
297 | } |
298 | } |
299 | |
300 | +void HomeLens::Impl::LensSearchFinished(Lens::Ptr& lens) |
301 | +{ |
302 | +} |
303 | + |
304 | std::vector<unsigned> HomeLens::Impl::GetCategoriesOrder() |
305 | { |
306 | - return categories_merger_.GetOrder(); |
307 | + return categories_merger_.GetDefaultOrder(); |
308 | } |
309 | |
310 | HomeLens::HomeLens(std::string const& name, |
311 | |
312 | === modified file 'UnityCore/Lens.cpp' |
313 | --- UnityCore/Lens.cpp 2012-08-15 21:47:27 +0000 |
314 | +++ UnityCore/Lens.cpp 2012-08-29 09:48:20 +0000 |
315 | @@ -36,6 +36,8 @@ |
316 | namespace |
317 | { |
318 | nux::logging::Logger logger("unity.dash.lens"); |
319 | + |
320 | +const unsigned CATEGORY_COLUMN = 2; |
321 | } |
322 | |
323 | using std::string; |
324 | @@ -91,6 +93,8 @@ |
325 | glib::Variant const& preview_update, |
326 | glib::DBusProxy::ReplyCallback reply_cb); |
327 | std::vector<unsigned> GetCategoriesOrder(); |
328 | + glib::Object<DeeModel> GetFilterModelForCategory(unsigned category); |
329 | + void GetFilterForCategoryIndex(unsigned category, DeeFilter* filter); |
330 | |
331 | string const& id() const; |
332 | string const& dbus_name() const; |
333 | @@ -109,6 +113,9 @@ |
334 | Filters::Ptr const& filters() const; |
335 | bool connected() const; |
336 | |
337 | + string const& last_search_string() const { return last_search_string_; } |
338 | + string const& last_global_search_string() const { return last_global_search_string_; } |
339 | + |
340 | Lens* owner_; |
341 | |
342 | string id_; |
343 | @@ -128,14 +135,16 @@ |
344 | bool connected_; |
345 | |
346 | string private_connection_name_; |
347 | + string last_search_string_; |
348 | + string last_global_search_string_; |
349 | |
350 | glib::DBusProxy* proxy_; |
351 | glib::Object<GCancellable> search_cancellable_; |
352 | glib::Object<GCancellable> global_search_cancellable_; |
353 | glib::Object<GCancellable> preview_cancellable_; |
354 | |
355 | - GVariant *results_variant_; |
356 | - GVariant *global_results_variant_; |
357 | + glib::Variant results_variant_; |
358 | + glib::Variant global_results_variant_; |
359 | }; |
360 | |
361 | Lens::Impl::Impl(Lens* owner, |
362 | @@ -166,8 +175,6 @@ |
363 | , filters_(new Filters(model_type)) |
364 | , connected_(false) |
365 | , proxy_(NULL) |
366 | - , results_variant_(NULL) |
367 | - , global_results_variant_(NULL) |
368 | { |
369 | if (model_type == ModelType::REMOTE) |
370 | { |
371 | @@ -199,6 +206,8 @@ |
372 | owner_->categories.SetGetterFunction(sigc::mem_fun(this, &Lens::Impl::categories)); |
373 | owner_->filters.SetGetterFunction(sigc::mem_fun(this, &Lens::Impl::filters)); |
374 | owner_->connected.SetGetterFunction(sigc::mem_fun(this, &Lens::Impl::connected)); |
375 | + owner_->last_search_string.SetGetterFunction(sigc::mem_fun(this, &Lens::Impl::last_search_string)); |
376 | + owner_->last_global_search_string.SetGetterFunction(sigc::mem_fun(this, &Lens::Impl::last_global_search_string)); |
377 | owner_->view_type.changed.connect(sigc::mem_fun(this, &Lens::Impl::OnViewTypeChanged)); |
378 | } |
379 | |
380 | @@ -236,13 +245,11 @@ |
381 | void Lens::Impl::ResultsModelUpdated(unsigned long long begin_seqnum, |
382 | unsigned long long end_seqnum) |
383 | { |
384 | - if (results_variant_ != NULL && |
385 | - end_seqnum >= ExtractModelSeqnum (results_variant_)) |
386 | + if (results_variant_ && end_seqnum >= ExtractModelSeqnum (results_variant_)) |
387 | { |
388 | - glib::Variant dict(results_variant_, glib::StealRef()); |
389 | Hints hints; |
390 | |
391 | - dict.ASVToHints(hints); |
392 | + results_variant_.ASVToHints(hints); |
393 | |
394 | owner_->search_finished.emit(hints); |
395 | |
396 | @@ -253,13 +260,12 @@ |
397 | void Lens::Impl::GlobalResultsModelUpdated(unsigned long long begin_seqnum, |
398 | unsigned long long end_seqnum) |
399 | { |
400 | - if (global_results_variant_ != NULL && |
401 | + if (global_results_variant_ && |
402 | end_seqnum >= ExtractModelSeqnum (global_results_variant_)) |
403 | { |
404 | - glib::Variant dict(global_results_variant_, glib::StealRef()); |
405 | Hints hints; |
406 | |
407 | - dict.ASVToHints(hints); |
408 | + global_results_variant_.ASVToHints(hints); |
409 | |
410 | owner_->global_search_finished.emit(hints); |
411 | |
412 | @@ -296,8 +302,7 @@ |
413 | if (results_->seqnum < reply_seqnum) |
414 | { |
415 | // wait for the end-transaction signal |
416 | - if (results_variant_) g_variant_unref (results_variant_); |
417 | - results_variant_ = g_variant_ref (parameters); |
418 | + results_variant_ = parameters; |
419 | |
420 | // ResultsModelUpdated will emit OnSearchFinished |
421 | return; |
422 | @@ -318,8 +323,7 @@ |
423 | if (global_results_->seqnum < reply_seqnum) |
424 | { |
425 | // wait for the end-transaction signal |
426 | - if (global_results_variant_) g_variant_unref (global_results_variant_); |
427 | - global_results_variant_ = g_variant_ref (parameters); |
428 | + global_results_variant_ = parameters; |
429 | |
430 | // GlobalResultsModelUpdated will emit OnGlobalSearchFinished |
431 | return; |
432 | @@ -367,15 +371,27 @@ |
433 | << " Filters: " << filters_model_name << "\n"; |
434 | if (dbus_path.Str() == dbus_path_) |
435 | { |
436 | + std::string categories_model_swarm_name(categories_model_name.Str()); |
437 | + std::string filters_model_swarm_name(filters_model_name.Str()); |
438 | + std::string results_model_swarm_name(results_model_name.Str()); |
439 | + std::string global_results_model_swarm_name(global_results_model_name.Str()); |
440 | + bool models_changed = |
441 | + categories_model_swarm_name != categories_->swarm_name || |
442 | + filters_model_swarm_name != filters_->swarm_name || |
443 | + results_model_swarm_name != results_->swarm_name || |
444 | + global_results_model_swarm_name != global_results_->swarm_name; |
445 | + |
446 | /* FIXME: We ignore hints for now */ |
447 | UpdateProperties(search_in_global, |
448 | visible, |
449 | search_hint.Str(), |
450 | private_connection_name.Str(), |
451 | - results_model_name.Str(), |
452 | - global_results_model_name.Str(), |
453 | - categories_model_name.Str(), |
454 | - filters_model_name.Str()); |
455 | + results_model_swarm_name, |
456 | + global_results_model_swarm_name, |
457 | + categories_model_swarm_name, |
458 | + filters_model_swarm_name); |
459 | + |
460 | + if (models_changed) owner_->models_changed.emit(); |
461 | } |
462 | else |
463 | { |
464 | @@ -447,11 +463,8 @@ |
465 | g_cancellable_cancel (global_search_cancellable_); |
466 | global_search_cancellable_ = g_cancellable_new (); |
467 | |
468 | - if (global_results_variant_) |
469 | - { |
470 | - g_variant_unref (global_results_variant_); |
471 | - global_results_variant_ = NULL; |
472 | - } |
473 | + global_results_variant_ = NULL; |
474 | + last_global_search_string_ = search_string; |
475 | |
476 | proxy_->Call("GlobalSearch", |
477 | g_variant_new("(sa{sv})", |
478 | @@ -478,11 +491,8 @@ |
479 | if (search_cancellable_) g_cancellable_cancel (search_cancellable_); |
480 | search_cancellable_ = g_cancellable_new (); |
481 | |
482 | - if (results_variant_) |
483 | - { |
484 | - g_variant_unref (results_variant_); |
485 | - results_variant_ = NULL; |
486 | - } |
487 | + results_variant_ = NULL; |
488 | + last_search_string_ = search_string; |
489 | |
490 | proxy_->Call("Search", |
491 | g_variant_new("(sa{sv})", |
492 | @@ -621,6 +631,61 @@ |
493 | return result; |
494 | } |
495 | |
496 | +glib::Object<DeeModel> Lens::Impl::GetFilterModelForCategory(unsigned category) |
497 | +{ |
498 | + DeeFilter filter; |
499 | + GetFilterForCategoryIndex(category, &filter); |
500 | + glib::Object<DeeModel> filter_model(dee_filter_model_new(results_->model(), &filter)); |
501 | + |
502 | + return filter_model; |
503 | +} |
504 | + |
505 | +static void category_filter_map_func (DeeModel* orig_model, |
506 | + DeeFilterModel* filter_model, |
507 | + gpointer user_data) |
508 | +{ |
509 | + DeeModelIter* iter; |
510 | + DeeModelIter* end; |
511 | + unsigned index = GPOINTER_TO_UINT(user_data); |
512 | + |
513 | + iter = dee_model_get_first_iter(orig_model); |
514 | + end = dee_model_get_last_iter(orig_model); |
515 | + while (iter != end) |
516 | + { |
517 | + unsigned category_index = dee_model_get_uint32(orig_model, iter, |
518 | + CATEGORY_COLUMN); |
519 | + if (index == category_index) |
520 | + { |
521 | + dee_filter_model_append_iter(filter_model, iter); |
522 | + } |
523 | + iter = dee_model_next(orig_model, iter); |
524 | + } |
525 | +} |
526 | + |
527 | +static gboolean category_filter_notify_func (DeeModel* orig_model, |
528 | + DeeModelIter* orig_iter, |
529 | + DeeFilterModel* filter_model, |
530 | + gpointer user_data) |
531 | +{ |
532 | + unsigned index = GPOINTER_TO_UINT(user_data); |
533 | + unsigned category_index = dee_model_get_uint32(orig_model, orig_iter, |
534 | + CATEGORY_COLUMN); |
535 | + |
536 | + if (index != category_index) |
537 | + return FALSE; |
538 | + |
539 | + dee_filter_model_insert_iter_with_original_order(filter_model, orig_iter); |
540 | + return TRUE; |
541 | +} |
542 | + |
543 | +void Lens::Impl::GetFilterForCategoryIndex(unsigned category, DeeFilter* filter) |
544 | +{ |
545 | + filter->map_func = category_filter_map_func; |
546 | + filter->map_notify = category_filter_notify_func; |
547 | + filter->destroy = nullptr; |
548 | + filter->userdata = GUINT_TO_POINTER(category); |
549 | +} |
550 | + |
551 | string const& Lens::Impl::id() const |
552 | { |
553 | return id_; |
554 | @@ -797,6 +862,11 @@ |
555 | return pimpl->GetCategoriesOrder(); |
556 | } |
557 | |
558 | +glib::Object<DeeModel> Lens::GetFilterModelForCategory(unsigned category) |
559 | +{ |
560 | + return pimpl->GetFilterModelForCategory(category); |
561 | +} |
562 | + |
563 | |
564 | } |
565 | } |
566 | |
567 | === modified file 'UnityCore/Lens.h' |
568 | --- UnityCore/Lens.h 2012-08-15 21:47:27 +0000 |
569 | +++ UnityCore/Lens.h 2012-08-29 09:48:20 +0000 |
570 | @@ -90,6 +90,13 @@ |
571 | virtual void SignalPreview(std::string const& uri, |
572 | glib::Variant const& preview_update, |
573 | glib::DBusProxy::ReplyCallback reply_cb = nullptr); |
574 | + |
575 | + /** |
576 | + * Note that this model is only valid for as long as the results model |
577 | + * doesn't change. |
578 | + * (you should call this again after models_changed is emitted) |
579 | + */ |
580 | + virtual glib::Object<DeeModel> GetFilterModelForCategory(unsigned category); |
581 | virtual std::vector<unsigned> GetCategoriesOrder(); |
582 | |
583 | nux::RWProperty<std::string> id; |
584 | @@ -107,10 +114,15 @@ |
585 | nux::RWProperty<Categories::Ptr> categories; |
586 | nux::RWProperty<Filters::Ptr> filters; |
587 | nux::RWProperty<bool> connected; |
588 | + nux::ROProperty<std::string> last_search_string; |
589 | + nux::ROProperty<std::string> last_global_search_string; |
590 | |
591 | nux::Property<ViewType> view_type; |
592 | |
593 | sigc::signal<void> categories_reordered; |
594 | + /* Emitted when any of the models' swarm name changes, but collates the name |
595 | + * changes into a single signal emission (when all are changed) */ |
596 | + sigc::signal<void> models_changed; |
597 | sigc::signal<void, Hints const&> search_finished; |
598 | sigc::signal<void, Hints const&> global_search_finished; |
599 | sigc::signal<void, std::string const&, HandledType, Hints const&> activated; |
600 | |
601 | === modified file 'UnityCore/Variant.cpp' |
602 | --- UnityCore/Variant.cpp 2012-06-01 14:01:29 +0000 |
603 | +++ UnityCore/Variant.cpp 2012-08-29 09:48:20 +0000 |
604 | @@ -97,8 +97,8 @@ |
605 | |
606 | Variant& Variant::operator=(GVariant* val) |
607 | { |
608 | - if (variant_) g_variant_unref (variant_); |
609 | - variant_ = g_variant_ref_sink (val); |
610 | + if (variant_) g_variant_unref(variant_); |
611 | + variant_ = val ? g_variant_ref_sink(val) : val; |
612 | |
613 | return *this; |
614 | } |
615 | @@ -108,6 +108,11 @@ |
616 | return variant_; |
617 | } |
618 | |
619 | +Variant::operator bool() const |
620 | +{ |
621 | + return bool(variant_); |
622 | +} |
623 | + |
624 | } // namespace glib |
625 | |
626 | namespace variant |
627 | |
628 | === modified file 'UnityCore/Variant.h' |
629 | --- UnityCore/Variant.h 2012-06-01 14:01:29 +0000 |
630 | +++ UnityCore/Variant.h 2012-08-29 09:48:20 +0000 |
631 | @@ -55,6 +55,8 @@ |
632 | |
633 | Variant& operator=(GVariant*); |
634 | operator GVariant*() const; |
635 | + operator bool() const; |
636 | + |
637 | private: |
638 | GVariant* variant_; |
639 | }; |
640 | |
641 | === modified file 'dash/LensView.cpp' |
642 | --- dash/LensView.cpp 2012-08-28 12:23:15 +0000 |
643 | +++ dash/LensView.cpp 2012-08-29 09:48:20 +0000 |
644 | @@ -45,8 +45,6 @@ |
645 | |
646 | const int CARD_VIEW_GAP_VERT = 24; // pixels |
647 | const int CARD_VIEW_GAP_HORIZ = 25; // pixels |
648 | - |
649 | -const unsigned CATEGORY_COLUMN = 2; |
650 | } |
651 | |
652 | // This is so we can access some protected members in scrollview. |
653 | @@ -248,11 +246,8 @@ |
654 | { |
655 | for (unsigned int i = 0; i < categories_.size(); ++i) |
656 | { |
657 | - PlacesGroup* group = categories_[i]; |
658 | - ResultViewGrid* grid = static_cast<ResultViewGrid*>(group->GetChildView()); |
659 | - DeeFilter filter; |
660 | - GetFilterForCategoryIndex(i, &filter); |
661 | - glib::Object<DeeModel> filter_model(dee_filter_model_new(model, &filter)); |
662 | + ResultViewGrid* grid = GetGridForCategory(i); |
663 | + glib::Object<DeeModel> filter_model(lens_->GetFilterModelForCategory(i)); |
664 | Results::Ptr results_model = lens_->results; |
665 | grid->SetModel(filter_model, results_model->GetTag()); |
666 | } |
667 | @@ -360,9 +355,7 @@ |
668 | Results::Ptr results_model = lens_->results; |
669 | if (results_model->model()) |
670 | { |
671 | - DeeFilter filter; |
672 | - GetFilterForCategoryIndex(index, &filter); |
673 | - glib::Object<DeeModel> filter_model(dee_filter_model_new(results_model->model(), &filter)); |
674 | + glib::Object<DeeModel> filter_model(lens_->GetFilterModelForCategory(index)); |
675 | grid->SetModel(filter_model, results_model->GetTag()); |
676 | } |
677 | |
678 | @@ -422,62 +415,13 @@ |
679 | } |
680 | } |
681 | |
682 | -static void category_filter_map_func (DeeModel* orig_model, |
683 | - DeeFilterModel* filter_model, |
684 | - gpointer user_data) |
685 | -{ |
686 | - DeeModelIter* iter; |
687 | - DeeModelIter* end; |
688 | - unsigned index = GPOINTER_TO_UINT(user_data); |
689 | - |
690 | - iter = dee_model_get_first_iter(orig_model); |
691 | - end = dee_model_get_last_iter(orig_model); |
692 | - while (iter != end) |
693 | - { |
694 | - unsigned category_index = dee_model_get_uint32(orig_model, iter, |
695 | - CATEGORY_COLUMN); |
696 | - if (index == category_index) |
697 | - { |
698 | - dee_filter_model_append_iter(filter_model, iter); |
699 | - } |
700 | - iter = dee_model_next(orig_model, iter); |
701 | - } |
702 | -} |
703 | - |
704 | -static gboolean category_filter_notify_func (DeeModel* orig_model, |
705 | - DeeModelIter* orig_iter, |
706 | - DeeFilterModel* filter_model, |
707 | - gpointer user_data) |
708 | -{ |
709 | - unsigned index = GPOINTER_TO_UINT(user_data); |
710 | - unsigned category_index = dee_model_get_uint32(orig_model, orig_iter, |
711 | - CATEGORY_COLUMN); |
712 | - |
713 | - if (index != category_index) |
714 | - return FALSE; |
715 | - |
716 | - dee_filter_model_insert_iter_with_original_order(filter_model, orig_iter); |
717 | - return TRUE; |
718 | -} |
719 | - |
720 | -void LensView::GetFilterForCategoryIndex(unsigned index, DeeFilter* filter) |
721 | -{ |
722 | - filter->map_func = category_filter_map_func; |
723 | - filter->map_notify = category_filter_notify_func; |
724 | - filter->destroy = nullptr; |
725 | - filter->userdata = GUINT_TO_POINTER(index); |
726 | -} |
727 | - |
728 | bool LensView::ReinitializeFilterModels() |
729 | { |
730 | Results::Ptr results_model = lens_->results; |
731 | for (unsigned i = last_good_filter_model_ + 1; i < categories_.size(); ++i) |
732 | { |
733 | - PlacesGroup* group = categories_[i]; |
734 | - ResultViewGrid* grid = static_cast<ResultViewGrid*>(group->GetChildView()); |
735 | - DeeFilter filter; |
736 | - GetFilterForCategoryIndex(i, &filter); |
737 | - glib::Object<DeeModel> filter_model(dee_filter_model_new(results_model->model(), &filter)); |
738 | + ResultViewGrid* grid = GetGridForCategory(i); |
739 | + glib::Object<DeeModel> filter_model(lens_->GetFilterModelForCategory(i)); |
740 | grid->SetModel(filter_model, results_model->GetTag()); |
741 | } |
742 | |
743 | @@ -486,6 +430,13 @@ |
744 | return false; |
745 | } |
746 | |
747 | +ResultViewGrid* LensView::GetGridForCategory(unsigned category_index) |
748 | +{ |
749 | + if (category_index >= categories_.size()) return nullptr; |
750 | + PlacesGroup* group = categories_.at(category_index); |
751 | + return static_cast<ResultViewGrid*>(group->GetChildView()); |
752 | +} |
753 | + |
754 | void LensView::OnResultAdded(Result const& result) |
755 | { |
756 | try { |
757 | @@ -755,18 +706,20 @@ |
758 | Results::Ptr results = lens_->results; |
759 | if (results->count()) |
760 | { |
761 | - // FIXME: Linear search in the result model, use category grid's model! |
762 | - for (unsigned int c = 0; c < scroll_layout_->GetChildren().size(); ++c) |
763 | + // the first displayed category might not be categories_[0] |
764 | + auto category_order = lens_->GetCategoriesOrder(); |
765 | + for (unsigned int i = 0; i < category_order.size(); i++) |
766 | { |
767 | - for (unsigned int i = 0; i < results->count(); ++i) |
768 | + unsigned cat_index = category_order.at(i); |
769 | + ResultViewGrid* grid = GetGridForCategory(cat_index); |
770 | + if (grid == nullptr) continue; |
771 | + auto it = grid->GetIteratorAtRow(0); |
772 | + if (!it.IsLast()) |
773 | { |
774 | - Result result = results->RowAtIndex(i); |
775 | - if (result.category_index == c && result.uri != "") |
776 | - { |
777 | - uri_activated(result.uri); |
778 | - lens_->Activate(result.uri); |
779 | - return; |
780 | - } |
781 | + Result result(*it); |
782 | + uri_activated(result.uri); |
783 | + lens_->Activate(result.uri); |
784 | + return; |
785 | } |
786 | } |
787 | // Fallback |
788 | |
789 | === modified file 'dash/LensView.h' |
790 | --- dash/LensView.h 2012-08-28 12:23:15 +0000 |
791 | +++ dash/LensView.h 2012-08-29 09:48:20 +0000 |
792 | @@ -95,8 +95,7 @@ |
793 | void QueueFixRenderering(); |
794 | bool FixRenderering(); |
795 | bool ReinitializeFilterModels(); |
796 | - |
797 | - static void GetFilterForCategoryIndex(unsigned index, DeeFilter* filter); |
798 | + ResultViewGrid* GetGridForCategory(unsigned category_index); |
799 | |
800 | void BuildPreview(std::string const& uri, Preview::Ptr model); |
801 |
Looks good on style and usage. Don't know about functionality.
Are there any automated unit tests for this area?