Merge lp:~rafalcieslak256/ubuntu-accomplishments-viewer/uav-display-modes into lp:ubuntu-accomplishments-viewer
- uav-display-modes
- Merge into accomplishments-viewer
Status: | Merged | ||||||||
---|---|---|---|---|---|---|---|---|---|
Merged at revision: | 209 | ||||||||
Proposed branch: | lp:~rafalcieslak256/ubuntu-accomplishments-viewer/uav-display-modes | ||||||||
Merge into: | lp:ubuntu-accomplishments-viewer | ||||||||
Diff against target: |
1635 lines (+702/-460) 3 files modified
Changelog (+5/-0) accomplishments_viewer/AccomplishmentsViewerWindow.py (+499/-383) data/ui/AccomplishmentsViewerWindow.ui (+198/-77) |
||||||||
To merge this branch: | bzr merge lp:~rafalcieslak256/ubuntu-accomplishments-viewer/uav-display-modes | ||||||||
Related bugs: |
|
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Matt Fischer | Approve | ||
Review via email: mp+133583@code.launchpad.net |
Commit message
Description of the change
This branch introduces lighting-fast filtering (fixes: #1076574), as well as search feature (#1076561) (which are actually fairly related).
It saves lots of time by not recreating treemodels everytime the filters change. Instead, this implementation makes heavy use of GtkTreeModelFil
Another mass efficiency gain is from dropping that terrible update_views function, which used to recreate all data we had from scratch, and is was called far too frequently. I solved that by implementing set_display(...) function, that takes a lot of optional arguments which are used to set new filter details. Usually called with just one parameter that has to be changed in the filter, it determines how to apply that change, and what will need refiltering. It also hides unnecesary UI elements. It's quite elegant, and very clear to use from many other places in code. It's also easily extensible, if one day we'll want to add a 'welcome' page, or implement help within the main window, it will be a piece of cake.
The search bar UI design is a suggestion, we may want to reorder the entry field with label, place them horisontally etc. Note that searching works for both opportunities and trophies (I find it most amazing in the "latest trophies view", as searching through it may cause some groups of accomplishments to appear/hide).
I have tested this branch carefully on both Quantal and Precise. I might have missed some UX details, let me know about any concerns you have and we'll discuss solutions.
Matt Fischer (mfisch) wrote : | # |
Rafał Cieślak (rafalcieslak256) wrote : | # |
Great thanks for taking time to look as this, Matt! :)
To answer your questions:
The XXX note in this diff's line 178 is an annotation for following prepare_models() call. The prepare_models() function is the only time-consuming bit now, as it initializes both treemodels. The call in line 178 is within function that runs when a new trophy is received. The point is that it makes no sense to clear both treemodels and recreating them from scratch when a new trophy is awarded, instead, we might just remove that new trophy from opprotunities list and add it to mytrophies. We do know the accomID of that new trophy, as daemon provides us with that data, so it's just a matter of implementing support for such action. It would be just faster.
Code in on_window_resized() is moved to a string because I wanted to remove it, but moving it to a comment looked to me as a more appropriate way of disabling it, so that the original code is left in case we wanted to reuse it some time. Currently it's not needed, as GTK now correctly manages iconview's width, and we don't need any silly workarounds to have the window properly resizing. Moreover, that trick we used as a workaround based on clearing and recreating all treemodels - and that's what this branch wants to avoid, since it's a very time-consuming operation.
I have not changed any of the "use_action_
If you want to, I can provide some more detail on how the GTK stuff works here.
- 218. By Rafał Cieślak
-
Using GtkSearchEntry instead of GtkEntry for the searchbar, it's much more intuitive this way
Matt Fischer (mfisch) wrote : | # |
I think you should just remove the on_window_resized code, we can get it back via bzr history if we need to, otherwise it looks good. I don't figure you're going to get an in depth review from Jono anytime soon, maybe Michael Hall could review it? Personally I think you should just push it in, we'll need to do extensive testing on this code before 0.4 anyway and now is the time for major changes like this.
Rafał Cieślak (rafalcieslak256) wrote : | # |
Thank you for the review. I'll push these changes, it's the first major thing for 0.4 so we'll have lots of time to test it afterwards.
- 219. By Rafał Cieślak
-
Finalising fix; added changelog entry and ironed out minor cosmetics
Preview Diff
1 | === modified file 'Changelog' |
2 | --- Changelog 2012-10-21 03:17:20 +0000 |
3 | +++ Changelog 2012-11-16 07:15:23 +0000 |
4 | @@ -18,6 +18,11 @@ |
5 | |
6 | Next Version Target: 0.4 |
7 | |
8 | + [Rafał Cieślak] |
9 | + * Added search feature (LP: #1076561) |
10 | + * Significantly improved filtering performance and responsivness (LP: #1076574) |
11 | + * Reorganised code that filters trophies, now using GtkTreeModelFilters. |
12 | + |
13 | [Matt Fischer] |
14 | * Fix lintian issues |
15 | * Added a manpage (LP: #1069264) |
16 | |
17 | === modified file 'accomplishments_viewer/AccomplishmentsViewerWindow.py' |
18 | --- accomplishments_viewer/AccomplishmentsViewerWindow.py 2012-09-13 19:19:11 +0000 |
19 | +++ accomplishments_viewer/AccomplishmentsViewerWindow.py 2012-11-16 07:15:23 +0000 |
20 | @@ -66,9 +66,32 @@ |
21 | COL_LOCKED = 3 |
22 | COL_COLLECTION = 4 |
23 | COL_ID = 5 |
24 | - |
25 | -MYTROPHIES_FILTER_ALL = 0 |
26 | -MYTROPHIES_FILTER_LATEST = 1 |
27 | +COL_DATE_ACCOMPLISHED = 6 |
28 | +COL_CATEGORIES = 7 |
29 | + |
30 | +MYTROPHIES_FILTER_UNSPECIFIED = 0 |
31 | +MYTROPHIES_FILTER_ALL = 1 |
32 | +MYTROPHIES_FILTER_LATEST = 2 |
33 | + |
34 | +DISPLAY_MODE_UNSPECIFIED = 0 |
35 | +DISPLAY_MODE_DETAILS = 1 |
36 | +DISPLAY_MODE_TROPHIES = 2 |
37 | +DISPLAY_MODE_OPPORTUNITIES = 3 |
38 | + |
39 | +DISPLAY_FILTER_LOCKED_UNSPECIFIED = 0 |
40 | +DISPLAY_FILTER_LOCKED_SHOW = 1 |
41 | +DISPLAY_FILTER_LOCKED_HIDE = 2 |
42 | + |
43 | +DISPLAY_FILTER_COLLECTION_UNSPECIFIED = 0 |
44 | +DISPLAY_FILTER_CATEGORY_UNSPECIFIED = 0 |
45 | +DISPLAY_FILTER_SUBCAT_UNSPECIFIED = 0 |
46 | +DISPLAY_FILTER_SEARCH_UNSPECIFIED = 0 |
47 | + |
48 | +TROPHIES_FILTER_TODAY = 1 |
49 | +TROPHIES_FILTER_WEEK = 2 |
50 | +TROPHIES_FILTER_MONTH = 3 |
51 | +TROPHIES_FILTER_SIXMONTHS = 4 |
52 | +TROPHIES_FILTER_EARLIER = 100 |
53 | |
54 | TROPHY_GALLERY_URL = 'http://213.138.100.229:8000' |
55 | |
56 | @@ -88,9 +111,19 @@ |
57 | self.EditExtraDialog.parent = self |
58 | self.curr_height = 0 |
59 | self.curr_width = 0 |
60 | - self.do_not_react_on_cat_changes = False |
61 | - self.mytrophies_filtermode = MYTROPHIES_FILTER_ALL |
62 | - self.mytrophies_store_all = [] |
63 | + |
64 | + # Following variables store current display settings. |
65 | + self.display_mytrophies_filtermode = MYTROPHIES_FILTER_ALL |
66 | + self.display_mode = DISPLAY_MODE_OPPORTUNITIES |
67 | + self.display_filter_locked = DISPLAY_FILTER_LOCKED_SHOW |
68 | + self.display_filter_collection = "" |
69 | + self.display_filter_category = "" |
70 | + self.display_filter_subcat = "" |
71 | + self.display_filter_search = "" |
72 | + |
73 | + # These two store list of pairs [filter, iconview] for all accomplishment groups in mytrophies view. |
74 | + self.trophies_collection_filters = [] |
75 | + self.mytrophies_latest_boxes = [] |
76 | # Code for other initialization actions should be added here. |
77 | |
78 | |
79 | @@ -142,10 +175,16 @@ |
80 | self.subcats_forward = self.builder.get_object("subcats_forward") |
81 | self.subcats_buttonbox = self.builder.get_object("subcats_buttonbox") |
82 | self.subcats_container = self.builder.get_object("subcats_container") |
83 | - self.mytrophies_mainbox = self.builder.get_object("mytrophies_mainbox") |
84 | self.mytrophies_filter_latest = self.builder.get_object("mytrophies_filter_latest") |
85 | self.mytrophies_filter_all = self.builder.get_object("mytrophies_filter_all") |
86 | self.opp_frame = self.builder.get_object("opp_frame") |
87 | + self.mytrophies_box_latest = self.builder.get_object("mytrophies_box_latest") |
88 | + self.mytrophies_box_all = self.builder.get_object("mytrophies_box_all") |
89 | + self.mytrophies_box_latest_window = self.builder.get_object("mytrophies_box_latest_window") |
90 | + self.mytrophies_box_all_window = self.builder.get_object("mytrophies_box_all_window") |
91 | + self.mytrophies_notebook = self.builder.get_object("mytrophies_notebook") |
92 | + self.searchbar = self.builder.get_object("searchbar") |
93 | + self.searchbar_box = self.builder.get_object("searchbar_box") |
94 | |
95 | # don't display the sub-cats scrollbars |
96 | sb_h = self.subcats_scroll.get_hscrollbar() |
97 | @@ -161,38 +200,34 @@ |
98 | context = self.toolbar.get_style_context() |
99 | context.add_class(Gtk.STYLE_CLASS_PRIMARY_TOOLBAR) |
100 | |
101 | - # create the stores used by the IconViews in the Latest View |
102 | - |
103 | - self.mytrophies_filter_today = Gtk.ListStore(str, GdkPixbuf.Pixbuf, bool, bool, str, str) # title, icon accomplished, locked, col, accomplishment |
104 | - self.mytrophies_filter_today.set_sort_column_id(COL_TITLE, Gtk.SortType.ASCENDING) |
105 | - |
106 | - self.mytrophies_filter_week = Gtk.ListStore(str, GdkPixbuf.Pixbuf, bool, bool, str, str) # title, icon accomplished, locked, col, accomplishment |
107 | - self.mytrophies_filter_week.set_sort_column_id(COL_TITLE, Gtk.SortType.ASCENDING) |
108 | - |
109 | - self.mytrophies_filter_month = Gtk.ListStore(str, GdkPixbuf.Pixbuf, bool, bool, str, str) # title, icon accomplished, locked, col, accomplishment |
110 | - self.mytrophies_filter_month.set_sort_column_id(COL_TITLE, Gtk.SortType.ASCENDING) |
111 | - |
112 | - self.mytrophies_filter_sixmonths = Gtk.ListStore(str, GdkPixbuf.Pixbuf, bool, bool, str, str) # title, icon accomplished, locked, col, accomplishment |
113 | - self.mytrophies_filter_sixmonths.set_sort_column_id(COL_TITLE, Gtk.SortType.ASCENDING) |
114 | - |
115 | - self.mytrophies_filter_earlier = Gtk.ListStore(str, GdkPixbuf.Pixbuf, bool, bool, str, str) # title, icon accomplished, locked, col, accomplishment |
116 | - self.mytrophies_filter_earlier.set_sort_column_id(COL_TITLE, Gtk.SortType.ASCENDING) |
117 | - |
118 | - |
119 | - self.oppstore = Gtk.ListStore(str, GdkPixbuf.Pixbuf, bool, bool, str, str) # title, icon, accomplished, locked, col, accomplishment |
120 | + # Create stores and corelated filters |
121 | + |
122 | + self.oppstore = Gtk.ListStore(str, GdkPixbuf.Pixbuf, bool, bool, str, str, str, str) # title, icon, accomplished, locked, col, accomplishment, date-accomplished, categories |
123 | self.oppstore.set_sort_column_id(COL_TITLE, Gtk.SortType.ASCENDING) |
124 | - self.opp_icon.set_model(self.oppstore) |
125 | - |
126 | - #self.trophy_icon.set_text_column(COL_TITLE) |
127 | - #self.trophy_icon.set_pixbuf_column(COL_PIXBUF) |
128 | - |
129 | + self.oppstore_filtered = self.oppstore.filter_new() |
130 | + # The following sets the function for tree model filter. That function has |
131 | + # to return true if a given row has to be visible. This way we can control |
132 | + # which opportunities are displayed, and which are not. |
133 | + self.oppstore_filtered.set_visible_func(self._opp_visible_func) |
134 | + |
135 | + self.trophiesstore = Gtk.ListStore(str, GdkPixbuf.Pixbuf, bool, bool, str, str, str, str) # title, icon, accomplished, locked, col, accomplishment, date-accomplished, categories |
136 | + self.trophiesstore.set_sort_column_id(COL_TITLE, Gtk.SortType.ASCENDING) |
137 | + self.trophiesstore_filter_today = self.trophiesstore.filter_new() |
138 | + self.trophiesstore_filter_today.set_visible_func(self._trophy_recent_visible_func,TROPHIES_FILTER_TODAY) |
139 | + self.trophiesstore_filter_week = self.trophiesstore.filter_new() |
140 | + self.trophiesstore_filter_week.set_visible_func(self._trophy_recent_visible_func,TROPHIES_FILTER_WEEK) |
141 | + self.trophiesstore_filter_month = self.trophiesstore.filter_new() |
142 | + self.trophiesstore_filter_month.set_visible_func(self._trophy_recent_visible_func,TROPHIES_FILTER_MONTH) |
143 | + self.trophiesstore_filter_sixmonths = self.trophiesstore.filter_new() |
144 | + self.trophiesstore_filter_sixmonths.set_visible_func(self._trophy_recent_visible_func,TROPHIES_FILTER_SIXMONTHS) |
145 | + self.trophiesstore_filter_earlier = self.trophiesstore.filter_new() |
146 | + self.trophiesstore_filter_earlier.set_visible_func(self._trophy_recent_visible_func,TROPHIES_FILTER_EARLIER) |
147 | + |
148 | + self.opp_icon.set_model(self.oppstore_filtered) |
149 | self.opp_icon.set_text_column(COL_TITLE) |
150 | self.opp_icon.set_pixbuf_column(COL_PIXBUF) |
151 | |
152 | - #self.opp_icon.show() |
153 | - |
154 | # set up webkit |
155 | - |
156 | self.webview = WebKit.WebView() |
157 | self.scrolledwindow.add(self.webview) |
158 | self.webview.props.settings.props.enable_default_context_menu = False |
159 | @@ -257,7 +292,7 @@ |
160 | # IMPORTANT: This function should do no initialisations that depend |
161 | # on having the daemon running. This is because if the daemon is not |
162 | # yet started it will take some time to connect to it. Such |
163 | - # initialistions should land in appropriate place in run_daemon_timeout(...). |
164 | + # initialistions should land in appropriate place in finalise_daemon_connection(...). |
165 | |
166 | self.datapath = get_data_path() |
167 | |
168 | @@ -285,6 +320,7 @@ |
169 | def on_reload_accomplishments_clicked(self, widget): |
170 | self.additional_no_collections.set_visible(False) |
171 | self.reload_accomplishments() |
172 | + self.set_display(DISPLAY_MODE_OPPORTUNITIES) |
173 | |
174 | def reload_accomplishments(self): |
175 | if not self.connected: |
176 | @@ -295,10 +331,9 @@ |
177 | self.libaccom.reload_accom_database() |
178 | self.statusbar_reload_msg_stop() |
179 | |
180 | - self.populate_opp_combos() |
181 | + self._load_accomplishments() |
182 | if len(self.accomdb) == 0: |
183 | self.add_no_collections_installed() |
184 | - self.update_views(None) |
185 | |
186 | def statusbar_reload_msg_start(self): |
187 | self.statusbar.set_text(_("Reloading accomplishments collections...")) |
188 | @@ -324,7 +359,9 @@ |
189 | |
190 | # run this to refresh our accomplishments list |
191 | self._load_accomplishments() |
192 | - self.update_views(None) |
193 | + |
194 | + #XXX: It would be MUCH faster if we determined the new accomID and added just it, not recreating whole trees! |
195 | + self.prepare_models() |
196 | |
197 | # set the Launcher icon to be urgent and show new trophy count |
198 | self.launcher.set_property("urgent", True) |
199 | @@ -334,9 +371,6 @@ |
200 | self.launcher.set_property("count_visible", True) |
201 | else: |
202 | self.launcher.set_property("count_visible", False) |
203 | - |
204 | - if not self.notebook.get_current_page() == 0: |
205 | - self.on_tb_mytrophies_clicked(None) |
206 | |
207 | def on_help_askubuntu_activate(self, widget): |
208 | webbrowser.open("http://askubuntu.com/questions/ask?tags=accomplishments", True) |
209 | @@ -360,33 +394,6 @@ |
210 | if bool(self.has_u1) is True and bool(self.has_verif) is True: |
211 | self.check_for_extra_info_required() |
212 | |
213 | - def add_mytrophies_view(self, section, liststore): |
214 | - outerbox = Gtk.VBox() |
215 | - header = Gtk.Label("<span font_family='Ubuntu' size='18000' weight='light'>" + section + "</span>") |
216 | - header.set_use_markup(True) |
217 | - header.set_property("xalign", 0) |
218 | - header.set_property("margin_left", 10) |
219 | - header.set_property("margin_top", 5) |
220 | - header.set_property("margin_bottom", 2) |
221 | - separator = Gtk.Separator() |
222 | - separator.set_property("margin_left", 10) |
223 | - separator.set_property("margin_right", 10) |
224 | - |
225 | - iconview = Gtk.IconView() |
226 | - iconview.set_model(liststore) |
227 | - iconview.set_text_column(COL_TITLE) |
228 | - iconview.set_pixbuf_column(COL_PIXBUF) |
229 | - iconview.set_item_width(120) |
230 | - iconview.set_columns(-1) |
231 | - iconview.connect("selection-changed",self.mytrophy_clicked) |
232 | - |
233 | - outerbox.pack_start(header, False, False, 0) |
234 | - outerbox.pack_start(separator, False, False, 0) |
235 | - outerbox.pack_start(iconview, False, False, 0) |
236 | - outerbox.show_all() |
237 | - |
238 | - self.mytrophies_mainbox.add(outerbox) |
239 | - |
240 | def connect_to_daemon(self): |
241 | """Tries to connect to the daemon""" |
242 | |
243 | @@ -496,13 +503,12 @@ |
244 | |
245 | def finalise_daemon_connection(self): |
246 | self.libaccom.create_all_trophy_icons() |
247 | + self._load_accomplishments() |
248 | + self.prepare_models() |
249 | self.populate_opp_combos() |
250 | if len(self.accomdb) == 0: |
251 | self.add_no_collections_installed() |
252 | - self.update_views(None) |
253 | - self.check_and_ask_for_info() |
254 | - self.notebook.set_current_page(2) |
255 | - self.tb_opportunities.set_active(1) |
256 | + self.set_display(DISPLAY_MODE_OPPORTUNITIES) |
257 | |
258 | |
259 | def update_widgets_sensitivity(self): |
260 | @@ -542,56 +548,8 @@ |
261 | self.subcats_back.set_sensitive(True) |
262 | self.subcats_forward.set_sensitive(True) |
263 | |
264 | - def subcats_show(self, col, cat): |
265 | - tempcats = [] |
266 | - if cat == "everything": |
267 | - self.subcats_container.hide() |
268 | - else: |
269 | - # set up the subcats |
270 | - cats = self.libaccom.get_collection_categories(col) |
271 | - for c in cats: |
272 | - if c == cat: |
273 | - tempcats = cats[c] |
274 | - |
275 | - finalcats = [] |
276 | - |
277 | - for s in tempcats: |
278 | - for i in self.accomdb: |
279 | - if i["collection"] == col and i["categories"][0] == cat + ":" + s and i["accomplished"] == False: |
280 | - finalcats.append(s) |
281 | - |
282 | - # convert to a set to remove dupes |
283 | - finalcats = set(finalcats) |
284 | - |
285 | - # remove previous buttons from the button box |
286 | - for b in self.subcats_buttonbox.get_children(): |
287 | - self.subcats_buttonbox.remove(b) |
288 | - |
289 | - # Add 'All' button |
290 | - button = Gtk.Button(_("All")) |
291 | - button.props.relief = Gtk.ReliefStyle.NONE |
292 | - button.connect("clicked", self.subcat_clicked, cat) |
293 | - self.subcats_buttonbox.add(button) |
294 | - button.show() |
295 | - |
296 | - # fill the button box with the sub categories |
297 | - for s in finalcats: |
298 | - button = Gtk.Button(s) |
299 | - button.props.relief = Gtk.ReliefStyle.NONE |
300 | - button.connect("clicked", self.subcat_clicked, cat) |
301 | - self.subcats_buttonbox.add(button) |
302 | - button.show() |
303 | - |
304 | - if len(finalcats) > 0: |
305 | - self.subcats_buttonbox.show_all() |
306 | - self.subcats_container.show() |
307 | - else: |
308 | - self.subcats_container.hide() |
309 | - |
310 | - |
311 | def subcat_clicked(self, button, data): |
312 | - self.subcat = button.get_label() |
313 | - self.update_views(None) |
314 | + self.set_display(filter_subcat = data) |
315 | |
316 | def subcats_back_button(self, widget): |
317 | h = self.subcats_scroll.get_hadjustment() |
318 | @@ -662,7 +620,7 @@ |
319 | |
320 | if uri.startswith('accomplishment:'): |
321 | id = uri[17:] |
322 | - self.accomplishment_info(id) |
323 | + self.set_display(DISPLAY_MODE_DETAILS,accomID=id) |
324 | return True |
325 | |
326 | pol_dec.ignore() |
327 | @@ -750,6 +708,8 @@ |
328 | self.additional_ubuntu1.set_visible(True) |
329 | |
330 | def on_window_resized(self,widget): |
331 | + """ |
332 | + Since there is no more need to recalculate data when resized, the following is no more needed. |
333 | # get the new size |
334 | new_width = widget.get_size()[0] |
335 | new_height = widget.get_size()[1] |
336 | @@ -760,278 +720,73 @@ |
337 | self.curr_height = new_height |
338 | # and refill iconviews with icons to adjust columns number |
339 | if self.connected: |
340 | - self.update_views(widget) |
341 | - self.update_mytrophy_filter() |
342 | + if self.display_mode is DISPLAY_MODE_OPPORTUNITIES: |
343 | + self._update_opportunities_view(None) |
344 | + if self.display_mode is DISPLAY_MODE_TROPHIES: |
345 | + self._update_mytrophy_filter() |
346 | else: |
347 | # Control flow may reach here if the daemon is not yet running |
348 | # and therefore connection is yet to be made. Passing here will |
349 | # avoid errors about not-existing libaccom. |
350 | pass |
351 | - |
352 | - |
353 | - def update_views(self, widget): |
354 | - """Update all of the views to reflect the current state of Trophies and Opportunities.""" |
355 | - status_trophies = 0 |
356 | - status_opps = 0 |
357 | - |
358 | - show_locked = True |
359 | - |
360 | - if self.opp_showlocked.get_active(): |
361 | - show_locked = True |
362 | - else: |
363 | - show_locked = False |
364 | - |
365 | - self.mytrophies_store_all = [] |
366 | - |
367 | - #trophymodel = self.trophy_icon.get_model() |
368 | - oppmodel = self.opp_icon.get_model() |
369 | - |
370 | - # clear the models |
371 | - oppmodel.clear() |
372 | - self.mytrophies_filter_today.clear() |
373 | - self.mytrophies_filter_week.clear() |
374 | - self.mytrophies_filter_month.clear() |
375 | - self.mytrophies_filter_sixmonths.clear() |
376 | - self.mytrophies_filter_earlier.clear() |
377 | - |
378 | - coltree_iter = self.opp_combo_col.get_active_iter() |
379 | - colmodel = self.opp_combo_col.get_model() |
380 | - |
381 | - if coltree_iter == None: |
382 | - col = "" |
383 | - colname = "" |
384 | - else: |
385 | - col, colname = colmodel[coltree_iter][:2] |
386 | - |
387 | - col_active_item = self.opp_combo_col.get_active() |
388 | - |
389 | - if col_active_item == 0: |
390 | - self.opp_combo_cat.set_sensitive(False) |
391 | - else: |
392 | - self.opp_combo_cat.set_sensitive(True) |
393 | - |
394 | - cattree_iter = self.opp_combo_cat.get_active_iter() |
395 | - catmodel = self.opp_combo_cat.get_model() |
396 | - |
397 | - if cattree_iter == None: |
398 | - cat = "" |
399 | - catname = "" |
400 | - else: |
401 | - cat, catname = catmodel[cattree_iter][:2] |
402 | - |
403 | - if cat == "": |
404 | - self.subcats_container.hide() |
405 | - else: |
406 | - self.subcats_show(col, cat) |
407 | - |
408 | - # update opportunities |
409 | - for acc in self.accomdb: |
410 | - icon = None |
411 | - icon = GdkPixbuf.Pixbuf.new_from_file_at_size(str(acc["iconpath"]), 90, 90) |
412 | - |
413 | - if str(acc["accomplished"]) == '1': |
414 | - #self.mytrophies_filter_all = testlist.append( { acc["collection-human"] : [acc["title"], icon, bool(acc["accomplished"]), acc["locked"], acc["collection"], acc["id"]] } ) |
415 | - self.mytrophies_store_all.append([{ "title" : acc["title"], "icon" : icon, "accomplished" : bool(acc["accomplished"]), "locked" : acc["locked"], "collection" : acc["collection"], "id" : acc["id"], "collection-human" : acc["collection-human"] }]) |
416 | - |
417 | - today = datetime.date.today() |
418 | - margin_today = datetime.timedelta(days = 1) |
419 | - margin_week = datetime.timedelta(days = 7) |
420 | - margin_month = datetime.timedelta(days = 31) |
421 | - margin_sixmonths = datetime.timedelta(days = 180) |
422 | - |
423 | - match = False |
424 | - |
425 | - if str(acc["date-accomplished"]) == "None": |
426 | - pass |
427 | - else: |
428 | - year = int(acc["date-accomplished"].split("-")[0]) |
429 | - month = int(acc["date-accomplished"].split("-")[1]) |
430 | - day = int(acc["date-accomplished"].split("-")[2].split(" ")[0]) |
431 | - |
432 | - if (today - margin_today <= datetime.date(year, month, day) <= today + margin_today) == True: |
433 | - self.mytrophies_filter_today.append([acc["title"], icon, bool(acc["accomplished"]), bool(acc["locked"]), acc["collection"], acc["id"]]) |
434 | - elif (today - margin_week <= datetime.date(year, month, day) <= today + margin_week) == True: |
435 | - self.mytrophies_filter_week.append([acc["title"], icon, bool(acc["accomplished"]), bool(acc["locked"]), acc["collection"], acc["id"]]) |
436 | - elif (today - margin_month <= datetime.date(year, month, day) <= today + margin_month) == True: |
437 | - self.mytrophies_filter_month.append([acc["title"], icon, bool(acc["accomplished"]), bool(acc["locked"]), acc["collection"], acc["id"]]) |
438 | - elif (today - margin_sixmonths <= datetime.date(year, month, day) <= today + margin_sixmonths) == True: |
439 | - self.mytrophies_filter_sixmonths.append([acc["title"], icon, bool(acc["accomplished"]), bool(acc["locked"]), acc["collection"], acc["id"]]) |
440 | - #else: |
441 | - # self.mytrophies_filter_earlier.append([acc["title"], icon, bool(acc["accomplished"]), bool(acc["locked"]), acc["collection"], acc["id"]]) |
442 | - |
443 | - status_trophies = status_trophies + 1 |
444 | - else: |
445 | - subcat = "" |
446 | - thiscat = "" |
447 | - |
448 | - c = [i for i in acc["categories"] if i == cat] |
449 | - if len(c) is not 0: |
450 | - thiscat = c[0] |
451 | - else: |
452 | - thiscat = "" |
453 | - |
454 | - status_opps = status_opps + 1 |
455 | - |
456 | - if self.subcat is not None: |
457 | - subcat = str(cat) + ":" + str(self.subcat) |
458 | - if self.subcat == "All": |
459 | - if acc["collection"] == col and cat in list(acc["categories"])[0]: |
460 | - if not acc["locked"] or show_locked: |
461 | - oppmodel.append([acc["title"], icon, bool(acc["accomplished"]), bool(acc["locked"]), acc["collection"], acc["id"]]) |
462 | - else: |
463 | - if acc["collection"] == col and list(acc["categories"])[0] == subcat: |
464 | - if not acc["locked"] or show_locked: |
465 | - oppmodel.append([acc["title"], icon, bool(acc["accomplished"]), bool(acc["locked"]), acc["collection"], acc["id"]]) |
466 | - else: |
467 | - if acc["collection"] == col and cat in list(acc["categories"])[0]: |
468 | - if not acc["locked"] or show_locked: |
469 | - oppmodel.append([acc["title"], icon, bool(acc["accomplished"]), bool(acc["locked"]), acc["collection"], acc["id"]]) |
470 | - elif col == "" and cat == "": |
471 | - if not acc["locked"] or show_locked: |
472 | - oppmodel.append([acc["title"], icon, bool(acc["accomplished"]), bool(acc["locked"]), acc["collection"], acc["id"]]) |
473 | - elif acc["collection"] == col and cat == "": |
474 | - if not acc["locked"] or show_locked: |
475 | - oppmodel.append([acc["title"], icon, bool(acc["accomplished"]), bool(acc["locked"]), acc["collection"], acc["id"]]) |
476 | + """ |
477 | + pass |
478 | |
479 | def populate_opp_combos(self): |
480 | - |
481 | - # grab data |
482 | - self._load_accomplishments() |
483 | - |
484 | temp = [] |
485 | - |
486 | for i in self.accomdb: |
487 | temp.append({i["collection"] : i["collection-human"] }) |
488 | - |
489 | # uniqify the values |
490 | result = [dict(tupleized) for tupleized in set(tuple(item.items()) for item in temp)] |
491 | - |
492 | + |
493 | # set up app |
494 | self.opp_col_store.append(["", "All"]) |
495 | - |
496 | for i in sorted(result): |
497 | self.opp_col_store.append([i.keys()[0], i.values()[0]]) |
498 | - |
499 | self.opp_combo_col.set_model(self.opp_col_store) |
500 | - |
501 | self.opp_combo_col.set_active(0) |
502 | self.opp_combo_col.show() |
503 | |
504 | - # set up cat |
505 | - |
506 | + # Prepare categories combo |
507 | self.opp_combo_cat.set_model(self.opp_cat_store) |
508 | - |
509 | self.opp_combo_cat.show() |
510 | |
511 | - |
512 | - def opp_app_updated(self, widget): |
513 | - self.do_not_react_on_cat_changes = True |
514 | - catlist = set() |
515 | - tree_iter = widget.get_active_iter() |
516 | - model = widget.get_model() |
517 | - col, name = model[tree_iter][:2] |
518 | - |
519 | - if col == "": |
520 | - self.opp_cat_store.clear() |
521 | - self.opp_cat_store.append(["", _("everything")]) |
522 | - |
523 | - self.subcat = None |
524 | - |
525 | - self.update_views(None) |
526 | - else: |
527 | - cats = self.libaccom.get_collection_categories(col) |
528 | - |
529 | - for i in cats: |
530 | - catlist.add(i) |
531 | - |
532 | - self.opp_cat_store.clear() |
533 | - |
534 | - self.opp_cat_store.append(["", _("everything")]) |
535 | - |
536 | - for i in sorted(catlist): |
537 | - self.opp_cat_store.append([i, i]) |
538 | - |
539 | - self.do_not_react_on_cat_changes = False |
540 | - self.opp_combo_cat.set_active(0) |
541 | - |
542 | - self.subcats_container.hide() |
543 | - # Following does not have to be done, because using |
544 | - # opp_combo_cat.set_active will cause opp_cat_updated |
545 | - # to run update_views |
546 | - #self.update_views(None) |
547 | - |
548 | + def on_filter_collection_changed(self,widget): |
549 | + tree_iter = widget.get_active_iter() |
550 | + model = widget.get_model() |
551 | + collection, name = model[tree_iter][:2] |
552 | + self.set_display(filter_collection = collection) |
553 | + |
554 | + def on_filter_category_changed(self, widget): |
555 | + tree_iter = widget.get_active_iter() |
556 | + if tree_iter == None: # Special case if the categories combo is not sensitive |
557 | + return |
558 | + model = widget.get_model() |
559 | + category, name = model[tree_iter][:2] |
560 | + self.set_display(filter_category = category) |
561 | + |
562 | + def on_filter_show_locked_clicked(self, widget): |
563 | + if widget.get_active(): |
564 | + self.set_display(filter_locked=DISPLAY_FILTER_LOCKED_SHOW) |
565 | + else: |
566 | + self.set_display(filter_locked=DISPLAY_FILTER_LOCKED_HIDE) |
567 | + |
568 | + def on_search_changed(self,widget): |
569 | + value = widget.get_text() |
570 | + self.set_display(search_query=value) |
571 | + |
572 | + def on_search_clear_clicked(self,widget,icon,data): |
573 | + self.searchbar.set_text("") |
574 | + |
575 | def check_accomplishments(self, widget): |
576 | """Called when Check Accomplishments is selected in the interface.""" |
577 | - |
578 | self.libaccom.run_scripts(True) |
579 | - #self.notebook.set_current_page(2) |
580 | - |
581 | - def opp_cat_updated(self, widget): |
582 | - if self.do_not_react_on_cat_changes: |
583 | - return |
584 | - |
585 | - cattree_iter = self.opp_combo_cat.get_active_iter() |
586 | - catmodel = self.opp_combo_cat.get_model() |
587 | - |
588 | - if cattree_iter == None: |
589 | - cat = "" |
590 | - catname = "" |
591 | - else: |
592 | - cat, catname = catmodel[cattree_iter][:2] |
593 | - |
594 | - self.subcat = None |
595 | - |
596 | - self.update_views(None) |
597 | - |
598 | - def update_mytrophy_filter(self): |
599 | - |
600 | - kids = self.mytrophies_mainbox.get_children() |
601 | - |
602 | - if len(kids) > 0: |
603 | - for k in kids: |
604 | - self.mytrophies_mainbox.remove(k) |
605 | - |
606 | - if (self.mytrophies_filtermode == MYTROPHIES_FILTER_ALL): |
607 | - collections = self.libaccom.list_collections() |
608 | - |
609 | - for c in collections: |
610 | - ls = Gtk.ListStore(str, GdkPixbuf.Pixbuf, bool, bool, str, str) # title, icon accomplished, locked, col, accomplishment |
611 | - ls.set_sort_column_id(COL_TITLE, Gtk.SortType.ASCENDING) |
612 | - ls.clear() |
613 | - collectionhuman = "" |
614 | - for i in self.mytrophies_store_all: |
615 | - if i[0]["collection"] == c: |
616 | - collectionhuman = i[0]["collection-human"] |
617 | - ls.append([i[0]["title"], i[0]["icon"], i[0]["accomplished"], i[0]["locked"], i[0]["collection"], i[0]["id"]]) |
618 | - |
619 | - if len(ls) > 0: |
620 | - self.add_mytrophies_view(collectionhuman, ls) |
621 | - elif (self.mytrophies_filtermode == MYTROPHIES_FILTER_LATEST): |
622 | - if len(self.mytrophies_filter_today) > 0: |
623 | - self.add_mytrophies_view(_("Today"), self.mytrophies_filter_today) |
624 | - |
625 | - if len(self.mytrophies_filter_week) > 0: |
626 | - self.add_mytrophies_view(_("This Week"), self.mytrophies_filter_week) |
627 | - |
628 | - if len(self.mytrophies_filter_month) > 0: |
629 | - self.add_mytrophies_view(_("This Month"), self.mytrophies_filter_month) |
630 | - |
631 | - if len(self.mytrophies_filter_sixmonths) > 0: |
632 | - self.add_mytrophies_view(_("Last Six Months"), self.mytrophies_filter_sixmonths) |
633 | - |
634 | - if len(self.mytrophies_filter_earlier) > 0: |
635 | - self.add_mytrophies_view(_("Earlier"), self.mytrophies_filter_earlier) |
636 | - |
637 | - |
638 | - |
639 | + |
640 | def on_mytrophies_filter_latest_toggled(self, widget): |
641 | - self.mytrophies_filtermode = MYTROPHIES_FILTER_LATEST |
642 | - self.update_mytrophy_filter() |
643 | - |
644 | + self.set_display(trophies_mode=MYTROPHIES_FILTER_LATEST) |
645 | |
646 | def on_mytrophies_filter_all_toggled(self, widget): |
647 | - self.mytrophies_filtermode = MYTROPHIES_FILTER_ALL |
648 | - self.update_mytrophy_filter() |
649 | + self.set_display(trophies_mode=MYTROPHIES_FILTER_ALL) |
650 | |
651 | def on_tb_mytrophies_clicked(self, widget): |
652 | """Called when the My Trophies button is clicked.""" |
653 | @@ -1040,14 +795,9 @@ |
654 | opportunities_toggled = self.tb_opportunities.get_active() |
655 | |
656 | if mytrophies_toggled == True: |
657 | - self.tb_opportunities.handler_block_by_func(self.on_tb_opportunities_clicked) |
658 | - self.tb_opportunities.set_active(False) |
659 | - self.tb_opportunities.handler_unblock_by_func(self.on_tb_opportunities_clicked) |
660 | - self.mytrophies_filter_all.set_active(True) |
661 | - self.on_mytrophies_filter_all_toggled(None) |
662 | - self.notebook.set_current_page(1) |
663 | + self.set_display(DISPLAY_MODE_TROPHIES) |
664 | else: |
665 | - self.tb_mytrophies.set_active(True) |
666 | + self.tb_mytrophies.set_active(True) # This also fires the signal handler |
667 | |
668 | def on_tb_opportunities_clicked(self, widget): |
669 | """Called when the Opportunities button is clicked.""" |
670 | @@ -1060,12 +810,9 @@ |
671 | opportunities_toggled = self.tb_opportunities.get_active() |
672 | |
673 | if opportunities_toggled == True: |
674 | - self.tb_mytrophies.handler_block_by_func(self.on_tb_mytrophies_clicked) |
675 | - self.tb_mytrophies.set_active(False) |
676 | - self.tb_mytrophies.handler_unblock_by_func(self.on_tb_mytrophies_clicked) |
677 | - self.notebook.set_current_page(2) |
678 | + self.set_display(DISPLAY_MODE_OPPORTUNITIES) |
679 | else: |
680 | - self.tb_opportunities.set_active(True) |
681 | + self.tb_opportunities.set_active(True) # This also fires the signal handler |
682 | |
683 | def menu_prefs_clicked(self,widget): |
684 | """Display the preferences window.""" |
685 | @@ -1143,7 +890,7 @@ |
686 | widget.unselect_path(item) |
687 | model = widget.get_model() |
688 | accomID = model[item][COL_ID] |
689 | - self.accomplishment_info(accomID) |
690 | + self.set_display(DISPLAY_MODE_DETAILS,accomID=accomID) |
691 | |
692 | def mytrophy_clicked(self, widget): |
693 | selection = widget.get_selected_items() |
694 | @@ -1153,7 +900,7 @@ |
695 | widget.unselect_path(item) |
696 | model = widget.get_model() |
697 | accomID = model[item][COL_ID] |
698 | - self.accomplishment_info(accomID) |
699 | + self.set_display(DISPLAY_MODE_DETAILS,accomID=accomID) |
700 | |
701 | def optparse_accomplishment(self, accom_id): |
702 | """Process the -a command line option""" |
703 | @@ -1162,9 +909,379 @@ |
704 | print "There is no accomplishment with this ID." |
705 | return |
706 | |
707 | - self.accomplishment_info(accom_id) |
708 | - |
709 | - def accomplishment_info(self, accomID): |
710 | + self.set_display(DISPLAY_MODE_DETAILS,accomID=accom_id) |
711 | + |
712 | + def prepare_models(self): |
713 | + """ |
714 | + This function is the only one that clears liststores and fills them with data. |
715 | + It also prepares some of filters - these which are used in mytrophies view. |
716 | + """ |
717 | + self.oppstore.clear() |
718 | + self.trophiesstore.clear() |
719 | + # Fill in the opportunities tree |
720 | + for acc in self.accomdb: |
721 | + icon = GdkPixbuf.Pixbuf.new_from_file_at_size(str(acc["iconpath"]), 90, 90) |
722 | + if str(acc["accomplished"]) != '1': |
723 | + self.oppstore.append([acc["title"], icon, bool(acc["accomplished"]), bool(acc["locked"]), acc["collection"], acc["id"], acc["date-accomplished"], '|'.join(acc["categories"])]) |
724 | + else: |
725 | + self.trophiesstore.append([acc["title"], icon, bool(acc["accomplished"]), bool(acc["locked"]), acc["collection"], acc["id"], acc["date-accomplished"], '|'.join(acc["categories"])]) |
726 | + # Prepare latest trophies iconviews |
727 | + if len(self.mytrophies_box_latest.get_children()) == 0: |
728 | + self.mytrophies_latest_boxes = [] |
729 | + box = self.add_mytrophies_view(self.mytrophies_box_latest,_("Today"), self.trophiesstore_filter_today) |
730 | + self.mytrophies_latest_boxes.append([self.trophiesstore_filter_today,box]) |
731 | + box = self.add_mytrophies_view(self.mytrophies_box_latest,_("This Week"), self.trophiesstore_filter_week) |
732 | + self.mytrophies_latest_boxes.append([self.trophiesstore_filter_week,box]) |
733 | + box = self.add_mytrophies_view(self.mytrophies_box_latest,_("This Month"), self.trophiesstore_filter_month) |
734 | + self.mytrophies_latest_boxes.append([self.trophiesstore_filter_month,box]) |
735 | + box = self.add_mytrophies_view(self.mytrophies_box_latest,_("Last Six Months"), self.trophiesstore_filter_sixmonths) |
736 | + self.mytrophies_latest_boxes.append([self.trophiesstore_filter_sixmonths,box]) |
737 | + box = self.add_mytrophies_view(self.mytrophies_box_latest,_("Earlier"), self.trophiesstore_filter_earlier) |
738 | + self.mytrophies_latest_boxes.append([self.trophiesstore_filter_earlier,box]) |
739 | + |
740 | + # Prepare all trophies iconviews |
741 | + kids = self.mytrophies_box_all.get_children() |
742 | + for kid in kids: |
743 | + self.mytrophies_box_all.remove(k) |
744 | + for f in self.trophies_collection_filters: |
745 | + del f[0] #Remove the filter! |
746 | + self.trophies_collection_filters = [] |
747 | + collections = self.libaccom.list_collections() |
748 | + for c in collections: |
749 | + new_filter = self.trophiesstore.filter_new() |
750 | + new_filter.set_visible_func(self._trophy_all_visible_func,c) |
751 | + box = self.add_mytrophies_view(self.mytrophies_box_all, self.libaccom.get_collection_name(c), new_filter) |
752 | + self.trophies_collection_filters.append([new_filter,box]) |
753 | + |
754 | + def add_mytrophies_view(self, parent, section, model): |
755 | + """ |
756 | + This function is used for adding a new group of accomplishments in mytrophies view. |
757 | + It creates unified UI elements, packs them and adds to @parent. The @section argument |
758 | + will be the header of the section. The @model argument should be the treemodel of this |
759 | + new iconview (prefferably a treemodelfilter). |
760 | + """ |
761 | + outerbox = Gtk.VBox() |
762 | + header = Gtk.Label("<span font_family='Ubuntu' size='18000' weight='light'>" + section + "</span>") |
763 | + header.set_use_markup(True) |
764 | + header.set_property("xalign", 0) |
765 | + header.set_property("margin_left", 10) |
766 | + header.set_property("margin_top", 5) |
767 | + header.set_property("margin_bottom", 2) |
768 | + separator = Gtk.Separator() |
769 | + separator.set_property("margin_left", 10) |
770 | + separator.set_property("margin_right", 10) |
771 | + |
772 | + iconview = Gtk.IconView() |
773 | + iconview.set_model(model) |
774 | + iconview.set_text_column(COL_TITLE) |
775 | + iconview.set_pixbuf_column(COL_PIXBUF) |
776 | + iconview.set_item_width(120) |
777 | + iconview.set_columns(-1) |
778 | + iconview.connect("selection-changed",self.mytrophy_clicked) |
779 | + |
780 | + outerbox.pack_start(header, False, False, 0) |
781 | + outerbox.pack_start(separator, False, False, 0) |
782 | + outerbox.pack_start(iconview, False, False, 0) |
783 | + outerbox.show_all() |
784 | + |
785 | + parent.add(outerbox) |
786 | + return outerbox |
787 | + |
788 | + def set_display(self, |
789 | + mode = DISPLAY_MODE_UNSPECIFIED, |
790 | + accomID = "", |
791 | + trophies_mode = MYTROPHIES_FILTER_UNSPECIFIED, |
792 | + filter_locked = DISPLAY_FILTER_LOCKED_UNSPECIFIED, |
793 | + filter_collection = DISPLAY_FILTER_COLLECTION_UNSPECIFIED, |
794 | + filter_category = DISPLAY_FILTER_CATEGORY_UNSPECIFIED, |
795 | + filter_subcat = DISPLAY_FILTER_SUBCAT_UNSPECIFIED, |
796 | + search_query = DISPLAY_FILTER_SEARCH_UNSPECIFIED): |
797 | + """ |
798 | + Switches display mode as specified in arguments. |
799 | + It takes care about flipping notebook pages, hiding unnecessary UI pieces etc. |
800 | + This function shouldn't be called with many arguments, pass only these that you want to override. |
801 | + """ |
802 | + # The ordering of following IF statements *IS* important! |
803 | + # For example, passing both collection and category to this function |
804 | + # may not result in skipping some of these data as they get cleared |
805 | + # later on. Therefore hierarhical order is desired. |
806 | + if mode is not DISPLAY_MODE_UNSPECIFIED: |
807 | + self.display_mode = mode |
808 | + # Reflect changes in the UI |
809 | + if self.display_mode is DISPLAY_MODE_DETAILS: |
810 | + #Displaying details for an accomplishment |
811 | + |
812 | + if accomID == "": |
813 | + print "Unable to display details view, you probably forgot the accomID argument." |
814 | + return |
815 | + |
816 | + # Set togglable buttons to reflect current state |
817 | + self.tb_mytrophies.handler_block_by_func(self.on_tb_mytrophies_clicked) |
818 | + self.tb_opportunities.handler_block_by_func(self.on_tb_opportunities_clicked) |
819 | + self.tb_mytrophies.set_active(False) |
820 | + self.tb_opportunities.set_active(False) |
821 | + self.tb_mytrophies.handler_unblock_by_func(self.on_tb_mytrophies_clicked) |
822 | + self.tb_opportunities.handler_unblock_by_func(self.on_tb_opportunities_clicked) |
823 | + |
824 | + # Select all characters in searchbar |
825 | + self.searchbar.grab_focus() |
826 | + |
827 | + self.notebook.set_current_page(0) |
828 | + self.searchbar_box.hide() |
829 | + |
830 | + elif self.display_mode is DISPLAY_MODE_TROPHIES: |
831 | + #Display the list of trophies |
832 | + |
833 | + # Set togglable buttons to reflect current state |
834 | + self.tb_mytrophies.handler_block_by_func(self.on_tb_mytrophies_clicked) |
835 | + self.tb_opportunities.handler_block_by_func(self.on_tb_opportunities_clicked) |
836 | + self.tb_mytrophies.set_active(True) |
837 | + self.tb_opportunities.set_active(False) |
838 | + self.tb_mytrophies.handler_unblock_by_func(self.on_tb_mytrophies_clicked) |
839 | + self.tb_opportunities.handler_unblock_by_func(self.on_tb_opportunities_clicked) |
840 | + |
841 | + # Select all characters in searchbar |
842 | + self.searchbar.grab_focus() |
843 | + |
844 | + self.notebook.set_current_page(1) |
845 | + self.searchbar_box.show() |
846 | + |
847 | + elif self.display_mode is DISPLAY_MODE_OPPORTUNITIES: |
848 | + |
849 | + # Set togglable buttons to reflect current state |
850 | + self.tb_mytrophies.handler_block_by_func(self.on_tb_mytrophies_clicked) |
851 | + self.tb_opportunities.handler_block_by_func(self.on_tb_opportunities_clicked) |
852 | + self.tb_mytrophies.set_active(False) |
853 | + self.tb_opportunities.set_active(True) |
854 | + self.tb_mytrophies.handler_unblock_by_func(self.on_tb_mytrophies_clicked) |
855 | + self.tb_opportunities.handler_unblock_by_func(self.on_tb_opportunities_clicked) |
856 | + |
857 | + self.notebook.set_current_page(2) |
858 | + self.searchbar_box.show() |
859 | + |
860 | + if trophies_mode is not MYTROPHIES_FILTER_UNSPECIFIED: |
861 | + self.display_mytrophies_filtermode = trophies_mode |
862 | + # Show/hide appropriate iconview |
863 | + if self.display_mytrophies_filtermode is MYTROPHIES_FILTER_ALL: |
864 | + self.mytrophies_notebook.set_current_page(0) |
865 | + elif self.display_mytrophies_filtermode is MYTROPHIES_FILTER_LATEST: |
866 | + self.mytrophies_notebook.set_current_page(1) |
867 | + |
868 | + if filter_locked is not DISPLAY_FILTER_LOCKED_UNSPECIFIED: |
869 | + self.display_filter_locked = filter_locked |
870 | + if filter_collection is not DISPLAY_FILTER_COLLECTION_UNSPECIFIED: |
871 | + self.display_filter_collection = filter_collection |
872 | + |
873 | + # As the requested collection changed, we need to update the categories combo. |
874 | + if filter_collection == "": |
875 | + self.opp_cat_store.clear() |
876 | + self.opp_cat_store.append(["", _("everything")]) |
877 | + self.opp_combo_cat.set_sensitive(False) |
878 | + else: |
879 | + cats = self.libaccom.get_collection_categories(filter_collection) |
880 | + self.opp_cat_store.clear() |
881 | + self.opp_cat_store.append(["", _("everything")]) |
882 | + for i in sorted(cats): |
883 | + self.opp_cat_store.append([i, i]) |
884 | + self.opp_combo_cat.set_sensitive(True) |
885 | + |
886 | + # Set the active item to "everything". |
887 | + self.display_filter_category = "" |
888 | + self.opp_combo_cat.handler_block_by_func(self.on_filter_category_changed) |
889 | + self.opp_combo_cat.set_active(0) |
890 | + self.opp_combo_cat.handler_unblock_by_func(self.on_filter_category_changed) |
891 | + |
892 | + # It is likely that we need to update the subcategories. |
893 | + # A special case is when it needs to be hidden after collection change. |
894 | + self._update_subcats() |
895 | + |
896 | + if filter_category is not DISPLAY_FILTER_CATEGORY_UNSPECIFIED: |
897 | + self.display_filter_category = filter_category |
898 | + |
899 | + # Changing category, therefore we should display the subcats bar too. |
900 | + self._update_subcats() |
901 | + |
902 | + if filter_subcat is not DISPLAY_FILTER_SUBCAT_UNSPECIFIED: |
903 | + self.display_filter_subcat = filter_subcat |
904 | + if search_query is not DISPLAY_FILTER_SEARCH_UNSPECIFIED: |
905 | + self.display_filter_search = search_query |
906 | + |
907 | + |
908 | + # Finally, pass refreshing/rerendering to specialised functions |
909 | + if self.display_mode is DISPLAY_MODE_DETAILS: |
910 | + self._accomplishment_info(accomID) |
911 | + elif self.display_mode is DISPLAY_MODE_TROPHIES: |
912 | + self._update_mytrophy_view() |
913 | + elif self.display_mode is DISPLAY_MODE_OPPORTUNITIES: |
914 | + self._update_opportunities_view() |
915 | + |
916 | + def _update_mytrophy_view(self): |
917 | + # Causes the treemodel to call visible_func for all rows. |
918 | + # It also hides/shows boxes depending on whether they are empty. |
919 | + if self.display_mytrophies_filtermode is MYTROPHIES_FILTER_ALL: |
920 | + filterlist = self.trophies_collection_filters |
921 | + elif self.display_mytrophies_filtermode is MYTROPHIES_FILTER_LATEST: |
922 | + filterlist = self.mytrophies_latest_boxes |
923 | + |
924 | + for f in filterlist: |
925 | + f[0].refilter() |
926 | + if len(f[0]) is 0: |
927 | + f[1].hide() |
928 | + else: |
929 | + f[1].show() |
930 | + |
931 | + def _update_opportunities_view(self): |
932 | + # Causes the treemodel to call visible_func for all rows. |
933 | + self.oppstore_filtered.refilter() |
934 | + |
935 | + def _opp_visible_func(self, model, iterator, data): |
936 | + """ |
937 | + This function is crucial for filtering opportunities. It is called |
938 | + by some internal GTK callbacks, whenever the treemodel changes. |
939 | + It has to return True/False, which states whether the given row |
940 | + should be displayed or not. |
941 | + """ |
942 | + # If we are hiding locked accoms: |
943 | + if (self.display_filter_locked is DISPLAY_FILTER_LOCKED_HIDE) and model.get_value(iterator,COL_LOCKED): |
944 | + return False |
945 | + # If we ale looking for a certain collection: |
946 | + if (self.display_filter_collection != "") and (self.display_filter_collection != model.get_value(iterator,COL_COLLECTION)): |
947 | + return False |
948 | + # If we ale looking for a certain category... |
949 | + if (self.display_filter_category != ""): |
950 | + #...and a subcategory |
951 | + if (self.display_filter_subcat != ""): |
952 | + q = self.display_filter_category + ":" + self.display_filter_subcat |
953 | + if not (q in model.get_value(iterator,COL_CATEGORIES)): |
954 | + return False |
955 | + if not (self.display_filter_category in model.get_value(iterator,COL_CATEGORIES)): |
956 | + return False |
957 | + # If there is a search term and this row does not match the query: |
958 | + if (self.display_filter_search != "") and not (self.display_filter_search.lower() in model.get_value(iterator,COL_TITLE).lower()) and not (self.display_filter_search.lower() in model.get_value(iterator,COL_ID).split("/")[1].lower()): |
959 | + return False |
960 | + return True |
961 | + |
962 | + def _trophy_recent_visible_func(self,model,iterator,data): |
963 | + """ |
964 | + This function is crucial for filtering recently awarded trophies. It is called |
965 | + by some internal GTK callbacks, whenever the treemodel changes. |
966 | + It has to return True/False, which states whether the given row |
967 | + should be displayed or not. |
968 | + The @data argument specifies which box's filter it actually is, |
969 | + be it "today" or "last month" |
970 | + """ |
971 | + |
972 | + #XXX: Making these constants global might save some filtering time. |
973 | + today = datetime.date.today() |
974 | + margin_today = datetime.timedelta(days = 1) |
975 | + margin_week = datetime.timedelta(days = 7) |
976 | + margin_month = datetime.timedelta(days = 31) |
977 | + margin_sixmonths = datetime.timedelta(days = 180) |
978 | + |
979 | + when = model.get_value(iterator,COL_DATE_ACCOMPLISHED) |
980 | + if when == "None": |
981 | + return False |
982 | + year, month, day = when.split("-") |
983 | + when = datetime.date(int(year), int(month), int(day.split(" ")[0])) |
984 | + |
985 | + if (today - margin_today <= when <= today + margin_today): |
986 | + if data is TROPHIES_FILTER_TODAY: |
987 | + pass #proceed to further filtering |
988 | + else: |
989 | + return False |
990 | + elif (today - margin_week <= when <= today + margin_week): |
991 | + if data is TROPHIES_FILTER_WEEK: |
992 | + pass #proceed to further filtering |
993 | + else: |
994 | + return False |
995 | + elif (today - margin_month <= when <= today + margin_month): |
996 | + if data is TROPHIES_FILTER_MONTH: |
997 | + pass #proceed to further filtering |
998 | + else: |
999 | + return False |
1000 | + elif (today - margin_sixmonths <= when <= today + margin_sixmonths): |
1001 | + if data is TROPHIES_FILTER_SIXMONTHS: |
1002 | + pass #proceed to further filtering |
1003 | + else: |
1004 | + return False |
1005 | + else: |
1006 | + if data is TROPHIES_FILTER_EARLIER: |
1007 | + pass #proceed to further filtering |
1008 | + else: |
1009 | + return False |
1010 | + |
1011 | + # If there is a search term and this row does not match the query: |
1012 | + if (self.display_filter_search != "") and not (self.display_filter_search.lower() in model.get_value(iterator,COL_TITLE).lower()) and not (self.display_filter_search.lower() in model.get_value(iterator,COL_ID).split("/")[1].lower()): |
1013 | + return False |
1014 | + |
1015 | + return True |
1016 | + |
1017 | + def _trophy_all_visible_func(self,model,iterator,collection): |
1018 | + """ |
1019 | + This function is crucial for filtering mytrophies. It is called |
1020 | + by some internal GTK callbacks, whenever the treemodel changes. |
1021 | + It has to return True/False, which states whether the given row |
1022 | + should be displayed or not. |
1023 | + The @data argument specifies filtered collection. |
1024 | + """ |
1025 | + # If row's collection matches the desired for this filter |
1026 | + if (collection != model.get_value(iterator,COL_COLLECTION)): |
1027 | + return False |
1028 | + # If there is a search term and this row does not match the query: |
1029 | + if (self.display_filter_search != "") and not (self.display_filter_search.lower() in model.get_value(iterator,COL_TITLE).lower()) and not (self.display_filter_search.lower() in model.get_value(iterator,COL_ID).split("/")[1].lower()): |
1030 | + return False |
1031 | + return True |
1032 | + |
1033 | + def _update_subcats(self): |
1034 | + """ |
1035 | + This function creates the buttons for subcategories, requesting required data from the daemon. |
1036 | + """ |
1037 | + tempcats = [] |
1038 | + if self.display_filter_category == "" or self.display_filter_collection == "": |
1039 | + self.subcats_container.hide() |
1040 | + else: |
1041 | + # set up the subcats |
1042 | + cats = self.libaccom.get_collection_categories(self.display_filter_collection) |
1043 | + for c in cats: |
1044 | + if c == self.display_filter_category: |
1045 | + tempcats = cats[c] |
1046 | + |
1047 | + finalcats = [] |
1048 | + |
1049 | + for s in tempcats: |
1050 | + for i in self.accomdb: |
1051 | + if i["collection"] == self.display_filter_collection and i["categories"][0] == self.display_filter_category + ":" + s and i["accomplished"] == False: |
1052 | + finalcats.append(s) |
1053 | + |
1054 | + # convert to a set to remove dupes |
1055 | + finalcats = set(finalcats) |
1056 | + |
1057 | + # remove previous buttons from the button box |
1058 | + for b in self.subcats_buttonbox.get_children(): |
1059 | + self.subcats_buttonbox.remove(b) |
1060 | + |
1061 | + if len(finalcats) > 1: |
1062 | + # Add 'All' button |
1063 | + button = Gtk.Button(_("All")) |
1064 | + button.props.relief = Gtk.ReliefStyle.NONE |
1065 | + button.connect("clicked", self.subcat_clicked, "") |
1066 | + self.subcats_buttonbox.add(button) |
1067 | + button.show() |
1068 | + |
1069 | + # fill the button box with the sub categories |
1070 | + for s in finalcats: |
1071 | + button = Gtk.Button(s) |
1072 | + button.props.relief = Gtk.ReliefStyle.NONE |
1073 | + button.connect("clicked", self.subcat_clicked, s) |
1074 | + self.subcats_buttonbox.add(button) |
1075 | + button.show() |
1076 | + |
1077 | + self.subcats_buttonbox.show_all() |
1078 | + self.subcats_container.show() |
1079 | + else: |
1080 | + self.subcats_container.hide() |
1081 | + |
1082 | + def _accomplishment_info(self, accomID): |
1083 | """Display information about the selected accomplishment.""" |
1084 | data = [] |
1085 | |
1086 | @@ -1428,6 +1545,5 @@ |
1087 | </html>" |
1088 | |
1089 | self.webview.load_html_string(html, "file:///") |
1090 | - self.notebook.set_current_page(0) |
1091 | self.webview.show() |
1092 | |
1093 | |
1094 | === modified file 'data/ui/AccomplishmentsViewerWindow.ui' |
1095 | --- data/ui/AccomplishmentsViewerWindow.ui 2012-09-07 18:16:29 +0000 |
1096 | +++ data/ui/AccomplishmentsViewerWindow.ui 2012-11-16 07:15:23 +0000 |
1097 | @@ -1,14 +1,14 @@ |
1098 | <?xml version="1.0" encoding="UTF-8"?> |
1099 | <interface> |
1100 | + <!-- interface-requires accomplishments_viewer_window 1.0 --> |
1101 | <!-- interface-requires gtk+ 3.0 --> |
1102 | - <!-- interface-requires accomplishments_viewer_window 1.0 --> |
1103 | <!-- interface-local-resource-path ../media --> |
1104 | <object class="AccomplishmentsViewerWindow" id="accomplishments_viewer_window"> |
1105 | <property name="height_request">270</property> |
1106 | <property name="can_focus">False</property> |
1107 | <property name="title" translatable="yes">Accomplishment Information</property> |
1108 | <property name="window_position">center</property> |
1109 | - <property name="default_width">705</property> |
1110 | + <property name="default_width">735</property> |
1111 | <property name="default_height">450</property> |
1112 | <property name="icon_name">distributor-logo</property> |
1113 | <signal name="check-resize" handler="on_window_resized" swapped="no"/> |
1114 | @@ -22,7 +22,6 @@ |
1115 | <property name="can_focus">False</property> |
1116 | <child> |
1117 | <object class="GtkMenuItem" id="mnu_file"> |
1118 | - <property name="use_action_appearance">False</property> |
1119 | <property name="visible">True</property> |
1120 | <property name="can_focus">False</property> |
1121 | <property name="label" translatable="yes">_File</property> |
1122 | @@ -34,7 +33,6 @@ |
1123 | <child> |
1124 | <object class="GtkImageMenuItem" id="mnu_check_acc"> |
1125 | <property name="label" translatable="yes">Check Accomplishments</property> |
1126 | - <property name="use_action_appearance">False</property> |
1127 | <property name="visible">True</property> |
1128 | <property name="can_focus">False</property> |
1129 | <property name="use_stock">False</property> |
1130 | @@ -48,7 +46,6 @@ |
1131 | </child> |
1132 | <child> |
1133 | <object class="GtkMenuItem" id="mnu_edit"> |
1134 | - <property name="use_action_appearance">False</property> |
1135 | <property name="visible">True</property> |
1136 | <property name="can_focus">False</property> |
1137 | <property name="label" translatable="yes">_Edit</property> |
1138 | @@ -60,7 +57,6 @@ |
1139 | <child> |
1140 | <object class="GtkImageMenuItem" id="mnu_preferences"> |
1141 | <property name="label">gtk-preferences</property> |
1142 | - <property name="use_action_appearance">False</property> |
1143 | <property name="visible">True</property> |
1144 | <property name="can_focus">False</property> |
1145 | <property name="use_underline">True</property> |
1146 | @@ -70,7 +66,6 @@ |
1147 | </child> |
1148 | <child> |
1149 | <object class="GtkMenuItem" id="mnu_edit_reload_accoms"> |
1150 | - <property name="use_action_appearance">False</property> |
1151 | <property name="visible">True</property> |
1152 | <property name="can_focus">False</property> |
1153 | <property name="label" translatable="yes">_Reload accomplishments collections...</property> |
1154 | @@ -81,7 +76,6 @@ |
1155 | <child> |
1156 | <object class="GtkImageMenuItem" id="mnu_edit_ident"> |
1157 | <property name="label" translatable="yes">_Identification...</property> |
1158 | - <property name="use_action_appearance">False</property> |
1159 | <property name="visible">True</property> |
1160 | <property name="can_focus">False</property> |
1161 | <property name="use_underline">True</property> |
1162 | @@ -96,7 +90,6 @@ |
1163 | </child> |
1164 | <child> |
1165 | <object class="GtkMenuItem" id="mnu_help"> |
1166 | - <property name="use_action_appearance">False</property> |
1167 | <property name="visible">True</property> |
1168 | <property name="can_focus">False</property> |
1169 | <property name="label" translatable="yes">_Help</property> |
1170 | @@ -108,7 +101,6 @@ |
1171 | <child> |
1172 | <object class="GtkImageMenuItem" id="mnu_contents"> |
1173 | <property name="label" translatable="yes">Contents</property> |
1174 | - <property name="use_action_appearance">False</property> |
1175 | <property name="visible">True</property> |
1176 | <property name="can_focus">False</property> |
1177 | <property name="image">image2</property> |
1178 | @@ -118,7 +110,6 @@ |
1179 | </child> |
1180 | <child> |
1181 | <object class="GtkMenuItem" id="help_askubuntu"> |
1182 | - <property name="use_action_appearance">False</property> |
1183 | <property name="visible">True</property> |
1184 | <property name="can_focus">False</property> |
1185 | <property name="label" translatable="yes">Ask a question...</property> |
1186 | @@ -129,7 +120,6 @@ |
1187 | </child> |
1188 | <child> |
1189 | <object class="GtkSeparatorMenuItem" id="menuitem1"> |
1190 | - <property name="use_action_appearance">False</property> |
1191 | <property name="visible">True</property> |
1192 | <property name="can_focus">False</property> |
1193 | </object> |
1194 | @@ -137,7 +127,6 @@ |
1195 | <child> |
1196 | <object class="GtkImageMenuItem" id="mnu_about"> |
1197 | <property name="label">gtk-about</property> |
1198 | - <property name="use_action_appearance">False</property> |
1199 | <property name="visible">True</property> |
1200 | <property name="can_focus">False</property> |
1201 | <property name="use_underline">True</property> |
1202 | @@ -163,10 +152,8 @@ |
1203 | <property name="toolbar_style">both</property> |
1204 | <child> |
1205 | <object class="GtkToggleToolButton" id="tb_mytrophies"> |
1206 | - <property name="use_action_appearance">False</property> |
1207 | <property name="visible">True</property> |
1208 | <property name="can_focus">False</property> |
1209 | - <property name="use_action_appearance">False</property> |
1210 | <property name="label" translatable="yes">My Trophies</property> |
1211 | <property name="use_underline">True</property> |
1212 | <property name="icon_widget">image9</property> |
1213 | @@ -178,12 +165,10 @@ |
1214 | </child> |
1215 | <child> |
1216 | <object class="GtkToggleToolButton" id="tb_opportunities"> |
1217 | - <property name="use_action_appearance">False</property> |
1218 | <property name="visible">True</property> |
1219 | <property name="can_focus">True</property> |
1220 | <property name="has_focus">True</property> |
1221 | <property name="is_focus">True</property> |
1222 | - <property name="use_action_appearance">False</property> |
1223 | <property name="label" translatable="yes">Opportunities</property> |
1224 | <property name="use_underline">True</property> |
1225 | <property name="icon_widget">image4</property> |
1226 | @@ -193,6 +178,69 @@ |
1227 | <property name="homogeneous">True</property> |
1228 | </packing> |
1229 | </child> |
1230 | + <child> |
1231 | + <object class="GtkToolItem" id="toolbutton1"> |
1232 | + <property name="visible">True</property> |
1233 | + <property name="can_focus">False</property> |
1234 | + <child> |
1235 | + <object class="GtkBox" id="box12"> |
1236 | + <property name="visible">True</property> |
1237 | + <property name="can_focus">False</property> |
1238 | + <child> |
1239 | + <placeholder/> |
1240 | + </child> |
1241 | + <child> |
1242 | + <object class="GtkBox" id="searchbar_box"> |
1243 | + <property name="visible">True</property> |
1244 | + <property name="can_focus">False</property> |
1245 | + <property name="margin_right">5</property> |
1246 | + <property name="margin_bottom">5</property> |
1247 | + <property name="orientation">vertical</property> |
1248 | + <child> |
1249 | + <object class="GtkEntry" id="searchbar"> |
1250 | + <property name="visible">True</property> |
1251 | + <property name="can_focus">True</property> |
1252 | + <property name="invisible_char">•</property> |
1253 | + <property name="secondary_icon_stock">gtk-clear</property> |
1254 | + <signal name="changed" handler="on_search_changed" swapped="no"/> |
1255 | + <signal name="icon-press" handler="on_search_clear_clicked" swapped="no"/> |
1256 | + </object> |
1257 | + <packing> |
1258 | + <property name="expand">False</property> |
1259 | + <property name="fill">True</property> |
1260 | + <property name="pack_type">end</property> |
1261 | + <property name="position">0</property> |
1262 | + </packing> |
1263 | + </child> |
1264 | + <child> |
1265 | + <object class="GtkLabel" id="label9"> |
1266 | + <property name="visible">True</property> |
1267 | + <property name="can_focus">False</property> |
1268 | + <property name="label" translatable="yes">Search:</property> |
1269 | + </object> |
1270 | + <packing> |
1271 | + <property name="expand">False</property> |
1272 | + <property name="fill">True</property> |
1273 | + <property name="pack_type">end</property> |
1274 | + <property name="position">1</property> |
1275 | + </packing> |
1276 | + </child> |
1277 | + </object> |
1278 | + <packing> |
1279 | + <property name="expand">False</property> |
1280 | + <property name="fill">False</property> |
1281 | + <property name="pack_type">end</property> |
1282 | + <property name="position">1</property> |
1283 | + </packing> |
1284 | + </child> |
1285 | + </object> |
1286 | + </child> |
1287 | + </object> |
1288 | + <packing> |
1289 | + <property name="expand">True</property> |
1290 | + <property name="homogeneous">True</property> |
1291 | + </packing> |
1292 | + </child> |
1293 | </object> |
1294 | <packing> |
1295 | <property name="expand">False</property> |
1296 | @@ -276,12 +324,10 @@ |
1297 | <child> |
1298 | <object class="GtkButton" id="button3"> |
1299 | <property name="label">gtk-ok</property> |
1300 | - <property name="use_action_appearance">False</property> |
1301 | <property name="visible">True</property> |
1302 | <property name="can_focus">True</property> |
1303 | <property name="receives_default">True</property> |
1304 | <property name="margin_right">10</property> |
1305 | - <property name="use_action_appearance">False</property> |
1306 | <property name="use_stock">True</property> |
1307 | <signal name="clicked" handler="daemon_session_ok" swapped="no"/> |
1308 | </object> |
1309 | @@ -386,12 +432,10 @@ |
1310 | <child> |
1311 | <object class="GtkButton" id="add_no_collections_scan"> |
1312 | <property name="label">Scan Again</property> |
1313 | - <property name="use_action_appearance">False</property> |
1314 | <property name="visible">True</property> |
1315 | <property name="can_focus">True</property> |
1316 | <property name="receives_default">True</property> |
1317 | <property name="margin_right">10</property> |
1318 | - <property name="use_action_appearance">False</property> |
1319 | <signal name="clicked" handler="on_reload_accomplishments_clicked" swapped="no"/> |
1320 | </object> |
1321 | <packing> |
1322 | @@ -403,12 +447,10 @@ |
1323 | <child> |
1324 | <object class="GtkButton" id="add_no_collections_quit"> |
1325 | <property name="label">gtk-quit</property> |
1326 | - <property name="use_action_appearance">False</property> |
1327 | <property name="visible">True</property> |
1328 | <property name="can_focus">True</property> |
1329 | <property name="receives_default">True</property> |
1330 | <property name="margin_right">10</property> |
1331 | - <property name="use_action_appearance">False</property> |
1332 | <property name="use_stock">True</property> |
1333 | </object> |
1334 | <packing> |
1335 | @@ -524,12 +566,10 @@ |
1336 | <child> |
1337 | <object class="GtkButton" id="button1"> |
1338 | <property name="label" translatable="yes">Edit credentials</property> |
1339 | - <property name="use_action_appearance">False</property> |
1340 | <property name="visible">True</property> |
1341 | <property name="can_focus">True</property> |
1342 | <property name="receives_default">True</property> |
1343 | <property name="margin_right">10</property> |
1344 | - <property name="use_action_appearance">False</property> |
1345 | <signal name="clicked" handler="edit_auth_info" swapped="no"/> |
1346 | </object> |
1347 | <packing> |
1348 | @@ -541,11 +581,9 @@ |
1349 | <child> |
1350 | <object class="GtkButton" id="button4"> |
1351 | <property name="label" translatable="yes">Later</property> |
1352 | - <property name="use_action_appearance">False</property> |
1353 | <property name="visible">True</property> |
1354 | <property name="can_focus">True</property> |
1355 | <property name="receives_default">True</property> |
1356 | - <property name="use_action_appearance">False</property> |
1357 | <property name="image_position">right</property> |
1358 | <signal name="clicked" handler="edit_auth_info_cancel" swapped="no"/> |
1359 | </object> |
1360 | @@ -728,12 +766,10 @@ |
1361 | <child> |
1362 | <object class="GtkButton" id="button2"> |
1363 | <property name="label" translatable="yes">Don't Use Ubuntu One</property> |
1364 | - <property name="use_action_appearance">False</property> |
1365 | <property name="visible">True</property> |
1366 | <property name="can_focus">True</property> |
1367 | <property name="receives_default">True</property> |
1368 | <property name="valign">start</property> |
1369 | - <property name="use_action_appearance">False</property> |
1370 | <property name="yalign">0.46000000834465027</property> |
1371 | <signal name="clicked" handler="cancel_register_with_u1" swapped="no"/> |
1372 | </object> |
1373 | @@ -825,11 +861,9 @@ |
1374 | <child> |
1375 | <object class="GtkRadioButton" id="mytrophies_filter_all"> |
1376 | <property name="label" translatable="yes">All</property> |
1377 | - <property name="use_action_appearance">False</property> |
1378 | <property name="visible">True</property> |
1379 | <property name="can_focus">True</property> |
1380 | <property name="receives_default">False</property> |
1381 | - <property name="use_action_appearance">False</property> |
1382 | <property name="xalign">0</property> |
1383 | <property name="active">True</property> |
1384 | <property name="draw_indicator">False</property> |
1385 | @@ -843,11 +877,9 @@ |
1386 | <child> |
1387 | <object class="GtkRadioButton" id="mytrophies_filter_latest"> |
1388 | <property name="label" translatable="yes">Latest</property> |
1389 | - <property name="use_action_appearance">False</property> |
1390 | <property name="visible">True</property> |
1391 | <property name="can_focus">True</property> |
1392 | <property name="receives_default">False</property> |
1393 | - <property name="use_action_appearance">False</property> |
1394 | <property name="xalign">0</property> |
1395 | <property name="active">True</property> |
1396 | <property name="draw_indicator">False</property> |
1397 | @@ -867,48 +899,143 @@ |
1398 | </packing> |
1399 | </child> |
1400 | <child> |
1401 | - <object class="GtkScrolledWindow" id="scrolledwindow2"> |
1402 | + <object class="GtkNotebook" id="mytrophies_notebook"> |
1403 | <property name="visible">True</property> |
1404 | <property name="can_focus">True</property> |
1405 | - <property name="hscrollbar_policy">always</property> |
1406 | - <child> |
1407 | - <object class="GtkViewport" id="viewport3"> |
1408 | - <property name="visible">True</property> |
1409 | - <property name="can_focus">False</property> |
1410 | - <property name="shadow_type">none</property> |
1411 | - <child> |
1412 | - <object class="GtkGrid" id="mytrophies_mainbox"> |
1413 | - <property name="visible">True</property> |
1414 | - <property name="can_focus">False</property> |
1415 | - <property name="orientation">vertical</property> |
1416 | - <property name="column_homogeneous">True</property> |
1417 | - <child> |
1418 | - <placeholder/> |
1419 | - </child> |
1420 | - <child> |
1421 | - <placeholder/> |
1422 | - </child> |
1423 | - <child> |
1424 | - <placeholder/> |
1425 | - </child> |
1426 | - <child> |
1427 | - <placeholder/> |
1428 | - </child> |
1429 | - <child> |
1430 | - <placeholder/> |
1431 | - </child> |
1432 | - <child> |
1433 | - <placeholder/> |
1434 | - </child> |
1435 | - </object> |
1436 | - </child> |
1437 | - </object> |
1438 | + <property name="show_tabs">False</property> |
1439 | + <child> |
1440 | + <object class="GtkScrolledWindow" id="mytrophies_box_all_window"> |
1441 | + <property name="visible">True</property> |
1442 | + <property name="can_focus">True</property> |
1443 | + <property name="hscrollbar_policy">always</property> |
1444 | + <child> |
1445 | + <object class="GtkViewport" id="viewport3"> |
1446 | + <property name="visible">True</property> |
1447 | + <property name="can_focus">False</property> |
1448 | + <property name="shadow_type">none</property> |
1449 | + <child> |
1450 | + <object class="GtkGrid" id="mytrophies_box_all"> |
1451 | + <property name="visible">True</property> |
1452 | + <property name="can_focus">False</property> |
1453 | + <property name="orientation">vertical</property> |
1454 | + <property name="column_homogeneous">True</property> |
1455 | + <child> |
1456 | + <placeholder/> |
1457 | + </child> |
1458 | + <child> |
1459 | + <placeholder/> |
1460 | + </child> |
1461 | + <child> |
1462 | + <placeholder/> |
1463 | + </child> |
1464 | + <child> |
1465 | + <placeholder/> |
1466 | + </child> |
1467 | + <child> |
1468 | + <placeholder/> |
1469 | + </child> |
1470 | + <child> |
1471 | + <placeholder/> |
1472 | + </child> |
1473 | + <child> |
1474 | + <placeholder/> |
1475 | + </child> |
1476 | + <child> |
1477 | + <placeholder/> |
1478 | + </child> |
1479 | + <child> |
1480 | + <placeholder/> |
1481 | + </child> |
1482 | + </object> |
1483 | + </child> |
1484 | + </object> |
1485 | + </child> |
1486 | + </object> |
1487 | + </child> |
1488 | + <child type="tab"> |
1489 | + <object class="GtkLabel" id="label11"> |
1490 | + <property name="visible">True</property> |
1491 | + <property name="can_focus">False</property> |
1492 | + <property name="label" translatable="yes">page 1</property> |
1493 | + </object> |
1494 | + <packing> |
1495 | + <property name="tab_fill">False</property> |
1496 | + </packing> |
1497 | + </child> |
1498 | + <child> |
1499 | + <object class="GtkScrolledWindow" id="mytrophies_box_latest_window"> |
1500 | + <property name="visible">True</property> |
1501 | + <property name="can_focus">True</property> |
1502 | + <property name="hscrollbar_policy">always</property> |
1503 | + <child> |
1504 | + <object class="GtkViewport" id="viewport4"> |
1505 | + <property name="visible">True</property> |
1506 | + <property name="can_focus">False</property> |
1507 | + <property name="shadow_type">none</property> |
1508 | + <child> |
1509 | + <object class="GtkGrid" id="mytrophies_box_latest"> |
1510 | + <property name="visible">True</property> |
1511 | + <property name="can_focus">False</property> |
1512 | + <property name="orientation">vertical</property> |
1513 | + <property name="column_homogeneous">True</property> |
1514 | + <child> |
1515 | + <placeholder/> |
1516 | + </child> |
1517 | + <child> |
1518 | + <placeholder/> |
1519 | + </child> |
1520 | + <child> |
1521 | + <placeholder/> |
1522 | + </child> |
1523 | + <child> |
1524 | + <placeholder/> |
1525 | + </child> |
1526 | + <child> |
1527 | + <placeholder/> |
1528 | + </child> |
1529 | + <child> |
1530 | + <placeholder/> |
1531 | + </child> |
1532 | + <child> |
1533 | + <placeholder/> |
1534 | + </child> |
1535 | + <child> |
1536 | + <placeholder/> |
1537 | + </child> |
1538 | + <child> |
1539 | + <placeholder/> |
1540 | + </child> |
1541 | + </object> |
1542 | + </child> |
1543 | + </object> |
1544 | + </child> |
1545 | + </object> |
1546 | + <packing> |
1547 | + <property name="position">1</property> |
1548 | + </packing> |
1549 | + </child> |
1550 | + <child type="tab"> |
1551 | + <object class="GtkLabel" id="label15"> |
1552 | + <property name="visible">True</property> |
1553 | + <property name="can_focus">False</property> |
1554 | + <property name="label" translatable="yes">page 2</property> |
1555 | + </object> |
1556 | + <packing> |
1557 | + <property name="position">1</property> |
1558 | + <property name="tab_fill">False</property> |
1559 | + </packing> |
1560 | + </child> |
1561 | + <child> |
1562 | + <placeholder/> |
1563 | + </child> |
1564 | + <child type="tab"> |
1565 | + <placeholder/> |
1566 | </child> |
1567 | </object> |
1568 | <packing> |
1569 | <property name="expand">True</property> |
1570 | <property name="fill">True</property> |
1571 | - <property name="position">1</property> |
1572 | + <property name="position">3</property> |
1573 | </packing> |
1574 | </child> |
1575 | </object> |
1576 | @@ -977,7 +1104,7 @@ |
1577 | <object class="GtkComboBox" id="opp_combo_app"> |
1578 | <property name="visible">True</property> |
1579 | <property name="can_focus">False</property> |
1580 | - <signal name="changed" handler="opp_app_updated" swapped="no"/> |
1581 | + <signal name="changed" handler="on_filter_collection_changed" swapped="no"/> |
1582 | </object> |
1583 | <packing> |
1584 | <property name="expand">False</property> |
1585 | @@ -1001,7 +1128,7 @@ |
1586 | <object class="GtkComboBox" id="opp_combo_cat"> |
1587 | <property name="visible">True</property> |
1588 | <property name="can_focus">False</property> |
1589 | - <signal name="changed" handler="opp_cat_updated" swapped="no"/> |
1590 | + <signal name="changed" handler="on_filter_category_changed" swapped="no"/> |
1591 | </object> |
1592 | <packing> |
1593 | <property name="expand">False</property> |
1594 | @@ -1012,16 +1139,14 @@ |
1595 | <child> |
1596 | <object class="GtkCheckButton" id="opp_showlocked"> |
1597 | <property name="label" translatable="yes">Show Locked</property> |
1598 | - <property name="use_action_appearance">False</property> |
1599 | <property name="visible">True</property> |
1600 | <property name="can_focus">True</property> |
1601 | <property name="receives_default">False</property> |
1602 | <property name="margin_left">5</property> |
1603 | - <property name="use_action_appearance">False</property> |
1604 | <property name="xalign">0</property> |
1605 | <property name="active">True</property> |
1606 | <property name="draw_indicator">True</property> |
1607 | - <signal name="toggled" handler="update_views" swapped="no"/> |
1608 | + <signal name="toggled" handler="on_filter_show_locked_clicked" swapped="no"/> |
1609 | </object> |
1610 | <packing> |
1611 | <property name="expand">False</property> |
1612 | @@ -1056,11 +1181,9 @@ |
1613 | <property name="can_focus">False</property> |
1614 | <child> |
1615 | <object class="GtkButton" id="subcats_back"> |
1616 | - <property name="use_action_appearance">False</property> |
1617 | <property name="visible">True</property> |
1618 | <property name="can_focus">True</property> |
1619 | <property name="receives_default">True</property> |
1620 | - <property name="use_action_appearance">False</property> |
1621 | <property name="relief">none</property> |
1622 | <signal name="clicked" handler="subcats_back_button" swapped="no"/> |
1623 | <child> |
1624 | @@ -1114,11 +1237,9 @@ |
1625 | </child> |
1626 | <child> |
1627 | <object class="GtkButton" id="subcats_forward"> |
1628 | - <property name="use_action_appearance">False</property> |
1629 | <property name="visible">True</property> |
1630 | <property name="can_focus">True</property> |
1631 | <property name="receives_default">True</property> |
1632 | - <property name="use_action_appearance">False</property> |
1633 | <property name="relief">none</property> |
1634 | <signal name="clicked" handler="subcats_forward_button" swapped="no"/> |
1635 | <child> |
I don't claim to understand all the GTK stuff here, but the theory makes sense to me. I do have a few questions.
What about the XXX on line 178? I don't follow what the optimization is?
Q: Why is the code in on_window_resized() all moved into a string?
I see this note about making these global, I think they'd make sense as global: date.today( ) timedelta( days = 1) timedelta( days = 7) timedelta( days = 31) timedelta( days = 180)
951 + today = datetime.
952 + margin_today = datetime.
953 + margin_week = datetime.
954 + margin_month = datetime.
955 + margin_sixmonths = datetime.
Why did you remove all these lines? What did they do? action_ appearance" >False< /property>
<property name="use_